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
22typedef uint64 fileblock_t;		// file block number
23typedef uint64 fsblock_t;		// filesystem block number
24
25typedef uint32 cluster_t;
26
27
28#define EXFAT_SUPER_BLOCK_OFFSET	0x0
29#define EXFAT_FIRST_DATA_CLUSTER	2
30
31
32struct 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
101struct 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
183struct 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
191extern fs_volume_ops gExfatVolumeOps;
192extern fs_vnode_ops gExfatVnodeOps;
193
194#endif	// EXFAT_H
195