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