1 /* 2 * Copyright 2011-2019, Jérôme Duval, jerome.duval@gmail.com. 3 * Copyright 2014 Haiku, Inc. All Rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 * 7 * Authors: 8 * Jérôme Duval, korli@users.berlios.de 9 * John Scipione, jscipione@gmail.com 10 */ 11 #ifndef EXFAT_H 12 #define EXFAT_H 13 14 15 #include <sys/stat.h> 16 17 #include <ByteOrder.h> 18 #include <fs_interface.h> 19 #include <KernelExport.h> 20 21 22 typedef uint64 fileblock_t; // file block number 23 typedef uint64 fsblock_t; // filesystem block number 24 25 typedef uint32 cluster_t; 26 27 28 #define EXFAT_SUPER_BLOCK_OFFSET 0x0 29 #define EXFAT_FIRST_DATA_CLUSTER 2 30 31 32 struct exfat_super_block { 33 uint8 jump_boot[3]; 34 char filesystem[8]; 35 uint8 reserved[53]; 36 uint64 first_block; 37 uint64 num_blocks; 38 uint32 first_fat_block; 39 uint32 fat_length; 40 uint32 first_data_block; 41 uint32 cluster_count; 42 uint32 root_dir_cluster; 43 uint32 serial_number; 44 uint8 version_minor; 45 uint8 version_major; 46 uint16 flags; 47 uint8 block_shift; 48 uint8 blocks_per_cluster_shift; 49 uint8 fat_count; 50 uint8 drive_select; 51 uint8 used_percent; 52 uint8 reserved2[7]; 53 uint8 boot_code[390]; 54 uint16 signature; 55 56 bool IsValid(); 57 // implemented in Volume.cpp 58 uint64 FirstBlock() const { return B_LENDIAN_TO_HOST_INT64(first_block); } 59 uint64 NumBlocks() const { return B_LENDIAN_TO_HOST_INT64(num_blocks); } 60 uint32 FirstFatBlock() const 61 { return B_LENDIAN_TO_HOST_INT32(first_fat_block); } 62 uint32 FatLength() const 63 { return B_LENDIAN_TO_HOST_INT32(fat_length); } 64 uint32 FirstDataBlock() const 65 { return B_LENDIAN_TO_HOST_INT32(first_data_block); } 66 uint32 ClusterCount() const 67 { return B_LENDIAN_TO_HOST_INT32(cluster_count); } 68 uint32 RootDirCluster() const 69 { return B_LENDIAN_TO_HOST_INT32(root_dir_cluster); } 70 uint32 SerialNumber() const 71 { return B_LENDIAN_TO_HOST_INT32(serial_number); } 72 uint8 VersionMinor() const { return version_minor; } 73 uint8 VersionMajor() const { return version_major; } 74 uint16 Flags() const { return B_LENDIAN_TO_HOST_INT16(flags); } 75 uint8 BlockShift() const { return block_shift; } 76 uint8 BlocksPerClusterShift() const { return blocks_per_cluster_shift; } 77 uint8 FatCount() const { return fat_count; } 78 uint8 DriveSelect() const { return drive_select; } 79 uint8 UsedPercent() const { return used_percent; } 80 } _PACKED; 81 82 83 #define EXFAT_SUPER_BLOCK_MAGIC "EXFAT " 84 85 #define EXFAT_ENTRY_TYPE_NOT_IN_USE 0x03 86 #define EXFAT_ENTRY_TYPE_BITMAP 0x81 87 #define EXFAT_ENTRY_TYPE_UPPERCASE 0x82 88 #define EXFAT_ENTRY_TYPE_LABEL 0x83 89 #define EXFAT_ENTRY_TYPE_FILE 0x85 90 #define EXFAT_ENTRY_TYPE_GUID 0xa0 91 #define EXFAT_ENTRY_TYPE_FILEINFO 0xc0 92 #define EXFAT_ENTRY_TYPE_FILENAME 0xc1 93 #define EXFAT_CLUSTER_END 0xffffffff 94 #define EXFAT_ENTRY_ATTRIB_SUBDIR 0x10 95 96 #define EXFAT_ENTRY_FLAG_CONTIGUOUS 0x3 97 98 #define EXFAT_FILENAME_MAX_LENGTH 512 99 100 101 struct exfat_entry { 102 uint8 type; 103 union { 104 struct { 105 uint8 length; 106 uint16 name[11]; 107 uint8 reserved[8]; 108 } _PACKED volume_label; 109 struct { 110 uint8 chunkCount; 111 uint16 checksum; 112 uint16 flags; 113 uint8 guid[16]; 114 uint8 reserved[10]; 115 } _PACKED volume_guid; 116 struct { 117 uint8 reserved[3]; 118 uint32 checksum; 119 uint8 reserved2[12]; 120 uint32 start_cluster; 121 uint64 size; 122 } _PACKED bitmap_uppercase; 123 struct { 124 uint8 chunkCount; 125 uint16 checksum; 126 uint16 attribs; 127 uint16 reserved; 128 uint16 creation_time; 129 uint16 creation_date; 130 uint16 modification_time; 131 uint16 modification_date; 132 uint16 access_time; 133 uint16 access_date; 134 uint8 creation_time_low; 135 uint8 modification_time_low; 136 uint8 reserved2[10]; 137 uint16 ModificationTime() const 138 { return B_LENDIAN_TO_HOST_INT16(modification_time); } 139 uint16 ModificationDate() const 140 { return B_LENDIAN_TO_HOST_INT16(modification_date); } 141 uint16 AccessTime() const 142 { return B_LENDIAN_TO_HOST_INT16(access_time); } 143 uint16 AccessDate() const 144 { return B_LENDIAN_TO_HOST_INT16(access_date); } 145 uint16 CreationTime() const 146 { return B_LENDIAN_TO_HOST_INT16(creation_time); } 147 uint16 CreationDate() const 148 { return B_LENDIAN_TO_HOST_INT16(creation_date); } 149 uint16 Attribs() const 150 { return B_LENDIAN_TO_HOST_INT16(attribs); } 151 void SetAttribs(uint16 newAttribs) 152 { attribs = B_HOST_TO_LENDIAN_INT16(newAttribs); } 153 } _PACKED file; 154 struct { 155 uint8 flag; 156 uint8 reserved; 157 uint8 name_length; 158 uint16 name_hash; 159 uint8 reserved2[2]; 160 uint64 size1; 161 uint8 reserved3[4]; 162 uint32 start_cluster; 163 uint64 size2; 164 uint32 StartCluster() const 165 { return B_LENDIAN_TO_HOST_INT32(start_cluster); } 166 void SetStartCluster(uint32 startCluster) 167 { start_cluster = B_HOST_TO_LENDIAN_INT32(startCluster); } 168 bool IsContiguous() const 169 { return (flag & EXFAT_ENTRY_FLAG_CONTIGUOUS) != 0; } 170 void SetFlag(uint8 newFlag) 171 { flag = newFlag; } 172 uint64 Size() const 173 { return B_LENDIAN_TO_HOST_INT64(size2); } 174 } _PACKED file_info; 175 struct { 176 uint8 flags; 177 uint16 name[15]; 178 } _PACKED file_name; 179 }; 180 } _PACKED; 181 182 183 struct file_cookie { 184 bigtime_t last_notification; 185 off_t last_size; 186 int open_mode; 187 }; 188 189 #define EXFAT_OPEN_MODE_USER_MASK 0x7fffffff 190 191 extern fs_volume_ops gExfatVolumeOps; 192 extern fs_vnode_ops gExfatVnodeOps; 193 194 #endif // EXFAT_H 195