Lorenz Brun | bd2ce6d | 2022-07-22 00:00:13 +0000 | [diff] [blame] | 1 | package fat32 |
| 2 | |
| 3 | const ( |
| 4 | // FAT32 entries are only 28 bits |
| 5 | fatMask = 0x0fffffff |
| 6 | // Free entries are 0 |
| 7 | fatFree = 0x0 |
| 8 | // Entry at the end of a cluster chain |
| 9 | fatEOF = 0x0ffffff8 |
| 10 | ) |
| 11 | |
| 12 | // FAT32 Boot Sector and BIOS Parameter Block. This structure is 512 bytes long, |
| 13 | // even if the logical block size is longer. The rest should be filled up with |
| 14 | // zeroes. |
| 15 | type bootSector struct { |
| 16 | // Jump instruction to boot code. |
| 17 | JmpInstruction [3]byte |
| 18 | // Creator name. "MSWIN4.1" recommended for compatibility. |
| 19 | OEMName [8]byte |
| 20 | // Count of bytes per block (i.e. logical block size) |
| 21 | // Must be one of 512, 1024, 2048 or 4096 |
| 22 | BlockSize uint16 |
| 23 | // Number of blocks per allocation unit (cluster). |
| 24 | // Must be a power of 2 that is greater than 0. |
| 25 | BlocksPerCluster uint8 |
| 26 | // Number of reserved blocks in the reserved region of the volume starting |
| 27 | // at the first block of the volume. This field must not be 0. |
| 28 | ReservedBlocks uint16 |
| 29 | // The count of FAT data structures on the volume. This field should always |
| 30 | // contain the value of 2 for any FAT volume of any type. |
| 31 | NumFATs uint8 |
| 32 | _ [4]byte |
| 33 | // Legacy value for media determination, must be 0xf8. |
| 34 | MediaCode uint8 |
| 35 | _ [2]byte |
| 36 | // Number of sectors per track for 0x13 interrupts. |
| 37 | SectorsPerTrack uint16 |
| 38 | // Number of heads for 0x13 interrupts. |
| 39 | NumHeads uint16 |
| 40 | // Count of hidden blocks preceding the partition that contains this FAT |
| 41 | // volume. |
| 42 | HiddenBlocks uint32 |
| 43 | // Total count of blocks on the volume. |
| 44 | TotalBlocks uint32 |
| 45 | // Count of blocks per FAT. |
| 46 | BlocksPerFAT uint32 |
| 47 | // Flags for FAT32 |
| 48 | Flags uint16 |
| 49 | _ [2]byte |
| 50 | // Cluster number of the first cluster of the root directory. Usually 2. |
| 51 | RootClusterNumber uint32 |
| 52 | // Block number of the FSINFO structure in the reserved area. |
| 53 | FSInfoBlock uint16 |
| 54 | // Block number of the copy of the boot record in the reserved area. |
| 55 | BackupStartBlock uint16 |
| 56 | _ [12]byte |
| 57 | // Drive number for 0x13 interrupts. |
| 58 | DriveNumber uint8 |
| 59 | _ [1]byte |
| 60 | BootSignature uint8 |
| 61 | // ID of this filesystem |
| 62 | ID uint32 |
| 63 | // Human-readable label of this filesystem, padded with spaces (0x20) |
| 64 | Label [11]byte |
| 65 | // Always set to ASCII "FAT32 " |
| 66 | Type [8]byte |
| 67 | _ [420]byte |
| 68 | // Always 0x55, 0xAA |
| 69 | Signature [2]byte |
| 70 | } |
| 71 | |
| 72 | // Special block (usually at block 1) containing additional metadata, |
| 73 | // specifically the number of free clusters and the next free cluster. |
| 74 | // Always 512 bytes, rest of the block should be padded with zeroes. |
| 75 | type fsinfo struct { |
| 76 | // Validates that this is an FSINFO block. Always 0x52, 0x52, 0x61, 0x41 |
| 77 | LeadSignature [4]byte |
| 78 | _ [480]byte |
| 79 | // Another signature. Always 0x72, 0x72, 0x41, 0x61 |
| 80 | StructSignature [4]byte |
| 81 | // Last known number of free clusters on the volume. |
| 82 | FreeCount uint32 |
| 83 | // Next free cluster hint. All 1's is interpreted as undefined. |
| 84 | NextFreeCluster uint32 |
| 85 | _ [14]byte |
| 86 | // One more signature. Always 0x55, 0xAA. |
| 87 | TrailingSignature [2]byte |
| 88 | } |
| 89 | |
| 90 | // Directory entry |
| 91 | type dirEntry struct { |
| 92 | // DOS 8.3 file name. |
| 93 | DOSName [11]byte |
| 94 | // Attribtes of the file or directory, 0x0f reserved to mark entry as a |
| 95 | // LFN entry (see lfnEntry below) |
| 96 | Attributes uint8 |
| 97 | _ byte |
| 98 | CreationTenMilli uint8 // Actually 10ms units, 0-199 range |
| 99 | CreationTime uint16 |
| 100 | CreationDate uint16 |
| 101 | _ [2]byte |
| 102 | FirstClusterHigh uint16 |
| 103 | LastWrittenToTime uint16 |
| 104 | LastWrittenToDate uint16 |
| 105 | FirstClusterLow uint16 |
| 106 | FileSize uint32 |
| 107 | } |
| 108 | |
| 109 | const ( |
| 110 | // lastSequenceNumberFlag is logically-ORed with the sequence number of the |
| 111 | // last Long File Name entry to mark it as such. |
| 112 | lastSequenceNumberFlag = 0x40 |
| 113 | // codepointsPerEntry is the number of UTF-16 codepoints that fit into a |
| 114 | // single Long File Name entry. |
| 115 | codepointsPerEntry = 5 + 6 + 2 |
| 116 | ) |
| 117 | |
| 118 | // VFAT long file name prepended entry |
| 119 | type lfnEntry struct { |
| 120 | SequenceNumber uint8 |
| 121 | // First 5 UTF-16 code units |
| 122 | NamePart1 [5]uint16 |
| 123 | // Attributes (must be 0x0f) |
| 124 | Attributes uint8 |
| 125 | _ byte |
| 126 | // Checksum of the 8.3 name. |
| 127 | Checksum uint8 |
| 128 | // Next 6 UTF-16 code units |
| 129 | NamePart2 [6]uint16 |
| 130 | _ [2]byte |
| 131 | // Next 2 UTF-16 code units |
| 132 | NamePart3 [2]uint16 |
| 133 | } |