xref: /haiku/src/add-ons/kernel/file_systems/exfat/exfat.h (revision 1d3959edfb0741a8a8ac768638133add307f8a19)
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
FirstBlockexfat_super_block58 	uint64 FirstBlock() const { return B_LENDIAN_TO_HOST_INT64(first_block); }
NumBlocksexfat_super_block59 	uint64 NumBlocks() const { return B_LENDIAN_TO_HOST_INT64(num_blocks); }
FirstFatBlockexfat_super_block60 	uint32 FirstFatBlock() const
61 		{ return B_LENDIAN_TO_HOST_INT32(first_fat_block); }
FatLengthexfat_super_block62 	uint32 FatLength() const
63 		{ return B_LENDIAN_TO_HOST_INT32(fat_length); }
FirstDataBlockexfat_super_block64 	uint32 FirstDataBlock() const
65 		{ return B_LENDIAN_TO_HOST_INT32(first_data_block); }
ClusterCountexfat_super_block66 	uint32 ClusterCount() const
67 		{ return B_LENDIAN_TO_HOST_INT32(cluster_count); }
RootDirClusterexfat_super_block68 	uint32 RootDirCluster() const
69 		{ return B_LENDIAN_TO_HOST_INT32(root_dir_cluster); }
SerialNumberexfat_super_block70 	uint32 SerialNumber() const
71 		{ return B_LENDIAN_TO_HOST_INT32(serial_number); }
VersionMinorexfat_super_block72 	uint8 VersionMinor() const { return version_minor; }
VersionMajorexfat_super_block73 	uint8 VersionMajor() const { return version_major; }
Flagsexfat_super_block74 	uint16 Flags() const { return B_LENDIAN_TO_HOST_INT16(flags); }
BlockShiftexfat_super_block75 	uint8 BlockShift() const { return block_shift; }
BlocksPerClusterShiftexfat_super_block76 	uint8 BlocksPerClusterShift() const { return blocks_per_cluster_shift; }
FatCountexfat_super_block77 	uint8 FatCount() const { return fat_count; }
DriveSelectexfat_super_block78 	uint8 DriveSelect() const { return drive_select; }
UsedPercentexfat_super_block79 	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];
ModificationTimeexfat_entry::__anon1f505b17010a::__anon1f505b170508137 			uint16 ModificationTime() const
138 				{ return B_LENDIAN_TO_HOST_INT16(modification_time); }
ModificationDateexfat_entry::__anon1f505b17010a::__anon1f505b170508139 			uint16 ModificationDate() const
140 				{ return B_LENDIAN_TO_HOST_INT16(modification_date); }
AccessTimeexfat_entry::__anon1f505b17010a::__anon1f505b170508141 			uint16 AccessTime() const
142 				{ return B_LENDIAN_TO_HOST_INT16(access_time); }
AccessDateexfat_entry::__anon1f505b17010a::__anon1f505b170508143 			uint16 AccessDate() const
144 				{ return B_LENDIAN_TO_HOST_INT16(access_date); }
CreationTimeexfat_entry::__anon1f505b17010a::__anon1f505b170508145 			uint16 CreationTime() const
146 				{ return B_LENDIAN_TO_HOST_INT16(creation_time); }
CreationDateexfat_entry::__anon1f505b17010a::__anon1f505b170508147 			uint16 CreationDate() const
148 				{ return B_LENDIAN_TO_HOST_INT16(creation_date); }
Attribsexfat_entry::__anon1f505b17010a::__anon1f505b170508149 			uint16 Attribs() const
150 				{ return B_LENDIAN_TO_HOST_INT16(attribs); }
SetAttribsexfat_entry::__anon1f505b17010a::__anon1f505b170508151 			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;
StartClusterexfat_entry::__anon1f505b17010a::__anon1f505b170608164 			uint32 StartCluster() const
165 				{ return B_LENDIAN_TO_HOST_INT32(start_cluster); }
SetStartClusterexfat_entry::__anon1f505b17010a::__anon1f505b170608166 			void SetStartCluster(uint32 startCluster)
167 				{ start_cluster = B_HOST_TO_LENDIAN_INT32(startCluster); }
IsContiguousexfat_entry::__anon1f505b17010a::__anon1f505b170608168 			bool IsContiguous() const
169 				{ return (flag & EXFAT_ENTRY_FLAG_CONTIGUOUS) != 0; }
SetFlagexfat_entry::__anon1f505b17010a::__anon1f505b170608170 			void SetFlag(uint8 newFlag)
171 				{ flag = newFlag; }
Sizeexfat_entry::__anon1f505b17010a::__anon1f505b170608172 			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