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