1a7ce5b29Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
2a7ce5b29Sopenharmony_ci/*
3a7ce5b29Sopenharmony_ci *  Copyright (C) 2019 Namjae Jeon <linkinjeon@kernel.org>
4a7ce5b29Sopenharmony_ci */
5a7ce5b29Sopenharmony_ci
6a7ce5b29Sopenharmony_ci#ifndef _EXFAT_H
7a7ce5b29Sopenharmony_ci#define _EXFAT_H
8a7ce5b29Sopenharmony_ci
9a7ce5b29Sopenharmony_ci#include <stdint.h>
10a7ce5b29Sopenharmony_ci#include <linux/fs.h>
11a7ce5b29Sopenharmony_ci
12a7ce5b29Sopenharmony_ci#ifdef HAVE_CONFIG_H
13a7ce5b29Sopenharmony_ci#include <config.h>
14a7ce5b29Sopenharmony_ci#endif
15a7ce5b29Sopenharmony_ci
16a7ce5b29Sopenharmony_ci#ifdef WORDS_BIGENDIAN
17a7ce5b29Sopenharmony_ci#define cpu_to_le16(x)	((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))
18a7ce5b29Sopenharmony_ci#define cpu_to_le32(x)	\
19a7ce5b29Sopenharmony_ci	((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >>  8) | \
20a7ce5b29Sopenharmony_ci	 (((x) & 0x0000ff00u) <<  8) | (((x) & 0x000000ffu) << 24))
21a7ce5b29Sopenharmony_ci#define cpu_to_le64(x)	(cpu_to_le32((uint64_t)(x)) << 32 | \
22a7ce5b29Sopenharmony_ci			cpu_to_le32((uint64_t)(x) >> 32))
23a7ce5b29Sopenharmony_ci#else
24a7ce5b29Sopenharmony_ci#define cpu_to_le16(x)	(x)
25a7ce5b29Sopenharmony_ci#define cpu_to_le32(x)	(x)
26a7ce5b29Sopenharmony_ci#define cpu_to_le64(x)	(x)
27a7ce5b29Sopenharmony_ci#endif
28a7ce5b29Sopenharmony_ci
29a7ce5b29Sopenharmony_ci#define le64_to_cpu(x)  ((uint64_t)cpu_to_le64(x))
30a7ce5b29Sopenharmony_ci#define le32_to_cpu(x)  ((uint32_t)cpu_to_le32(x))
31a7ce5b29Sopenharmony_ci#define le16_to_cpu(x)  ((uint16_t)cpu_to_le16(x))
32a7ce5b29Sopenharmony_ci
33a7ce5b29Sopenharmony_ci#define PBR_SIGNATURE		0xAA55
34a7ce5b29Sopenharmony_ci
35a7ce5b29Sopenharmony_ci#define VOL_CLEAN		0x0000
36a7ce5b29Sopenharmony_ci#define VOL_DIRTY		0x0002
37a7ce5b29Sopenharmony_ci
38a7ce5b29Sopenharmony_ci#define DENTRY_SIZE		32 /* directory entry size */
39a7ce5b29Sopenharmony_ci#define DENTRY_SIZE_BITS	5
40a7ce5b29Sopenharmony_ci/* exFAT allows 8388608(256MB) directory entries */
41a7ce5b29Sopenharmony_ci#define MAX_EXFAT_DENTRIES	8388608
42a7ce5b29Sopenharmony_ci#define MIN_FILE_DENTRIES	3
43a7ce5b29Sopenharmony_ci#define MAX_NAME_DENTRIES	17
44a7ce5b29Sopenharmony_ci
45a7ce5b29Sopenharmony_ci/* dentry types */
46a7ce5b29Sopenharmony_ci#define MSDOS_DELETED		0xE5	/* deleted mark */
47a7ce5b29Sopenharmony_ci#define MSDOS_UNUSED		0x00	/* end of directory */
48a7ce5b29Sopenharmony_ci
49a7ce5b29Sopenharmony_ci#define EXFAT_LAST		0x00	/* end of directory */
50a7ce5b29Sopenharmony_ci#define EXFAT_DELETE		~(0x80)
51a7ce5b29Sopenharmony_ci#define IS_EXFAT_DELETED(x)	((x) < 0x80) /* deleted file (0x01~0x7F) */
52a7ce5b29Sopenharmony_ci#define EXFAT_INVAL		0x80	/* invalid value */
53a7ce5b29Sopenharmony_ci#define EXFAT_BITMAP		0x81	/* allocation bitmap */
54a7ce5b29Sopenharmony_ci#define EXFAT_UPCASE		0x82	/* upcase table */
55a7ce5b29Sopenharmony_ci#define EXFAT_VOLUME		0x83	/* volume label */
56a7ce5b29Sopenharmony_ci#define EXFAT_FILE		0x85	/* file or dir */
57a7ce5b29Sopenharmony_ci#define EXFAT_GUID		0xA0
58a7ce5b29Sopenharmony_ci#define EXFAT_PADDING		0xA1
59a7ce5b29Sopenharmony_ci#define EXFAT_ACLTAB		0xA2
60a7ce5b29Sopenharmony_ci#define EXFAT_STREAM		0xC0	/* stream entry */
61a7ce5b29Sopenharmony_ci#define EXFAT_NAME		0xC1	/* file name entry */
62a7ce5b29Sopenharmony_ci#define EXFAT_ACL		0xC2	/* stream entry */
63a7ce5b29Sopenharmony_ci
64a7ce5b29Sopenharmony_ci/* checksum types */
65a7ce5b29Sopenharmony_ci#define CS_DIR_ENTRY		0
66a7ce5b29Sopenharmony_ci#define CS_PBR_SECTOR		1
67a7ce5b29Sopenharmony_ci#define CS_DEFAULT		2
68a7ce5b29Sopenharmony_ci
69a7ce5b29Sopenharmony_ci/* file attributes */
70a7ce5b29Sopenharmony_ci#define ATTR_READONLY		0x0001
71a7ce5b29Sopenharmony_ci#define ATTR_HIDDEN		0x0002
72a7ce5b29Sopenharmony_ci#define ATTR_SYSTEM		0x0004
73a7ce5b29Sopenharmony_ci#define ATTR_VOLUME		0x0008
74a7ce5b29Sopenharmony_ci#define ATTR_SUBDIR		0x0010
75a7ce5b29Sopenharmony_ci#define ATTR_ARCHIVE		0x0020
76a7ce5b29Sopenharmony_ci#define ATTR_EXTEND		(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | \
77a7ce5b29Sopenharmony_ci				 ATTR_VOLUME) /* 0x000F */
78a7ce5b29Sopenharmony_ci
79a7ce5b29Sopenharmony_ci#define ATTR_EXTEND_MASK	(ATTR_EXTEND | ATTR_SUBDIR | ATTR_ARCHIVE)
80a7ce5b29Sopenharmony_ci#define ATTR_RWMASK		(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME | \
81a7ce5b29Sopenharmony_ci				 ATTR_SUBDIR | ATTR_ARCHIVE)
82a7ce5b29Sopenharmony_ci
83a7ce5b29Sopenharmony_ci#define ATTR_READONLY_LE	cpu_to_le16(0x0001)
84a7ce5b29Sopenharmony_ci#define ATTR_HIDDEN_LE		cpu_to_le16(0x0002)
85a7ce5b29Sopenharmony_ci#define ATTR_SYSTEM_LE		cpu_to_le16(0x0004)
86a7ce5b29Sopenharmony_ci#define ATTR_VOLUME_LE		cpu_to_le16(0x0008)
87a7ce5b29Sopenharmony_ci#define ATTR_SUBDIR_LE		cpu_to_le16(0x0010)
88a7ce5b29Sopenharmony_ci#define ATTR_ARCHIVE_LE		cpu_to_le16(0x0020)
89a7ce5b29Sopenharmony_ci
90a7ce5b29Sopenharmony_ci/* stream flags */
91a7ce5b29Sopenharmony_ci#define EXFAT_SF_CONTIGUOUS		0x02
92a7ce5b29Sopenharmony_ci
93a7ce5b29Sopenharmony_ci#define CLUSTER_32(x)			((unsigned int)((x) & 0xFFFFFFFFU))
94a7ce5b29Sopenharmony_ci#define EXFAT_EOF_CLUSTER		CLUSTER_32(~0)
95a7ce5b29Sopenharmony_ci#define EXFAT_BAD_CLUSTER		(0xFFFFFFF7U)
96a7ce5b29Sopenharmony_ci#define EXFAT_FREE_CLUSTER		(0)
97a7ce5b29Sopenharmony_ci#define EXFAT_FIRST_CLUSTER		(2)
98a7ce5b29Sopenharmony_ci#define EXFAT_RESERVED_CLUSTERS		(2)
99a7ce5b29Sopenharmony_ci
100a7ce5b29Sopenharmony_ci
101a7ce5b29Sopenharmony_ci/* EXFAT BIOS parameter block (64 bytes) */
102a7ce5b29Sopenharmony_cistruct bpb64 {
103a7ce5b29Sopenharmony_ci	__u8 jmp_boot[3];
104a7ce5b29Sopenharmony_ci	__u8 oem_name[8];
105a7ce5b29Sopenharmony_ci	__u8 res_zero[53];
106a7ce5b29Sopenharmony_ci};
107a7ce5b29Sopenharmony_ci
108a7ce5b29Sopenharmony_ci/* EXFAT EXTEND BIOS parameter block (56 bytes) */
109a7ce5b29Sopenharmony_cistruct bsx64 {
110a7ce5b29Sopenharmony_ci	__le64 vol_offset;
111a7ce5b29Sopenharmony_ci	__le64 vol_length;
112a7ce5b29Sopenharmony_ci	__le32 fat_offset;
113a7ce5b29Sopenharmony_ci	__le32 fat_length;
114a7ce5b29Sopenharmony_ci	__le32 clu_offset;
115a7ce5b29Sopenharmony_ci	__le32 clu_count;
116a7ce5b29Sopenharmony_ci	__le32 root_cluster;
117a7ce5b29Sopenharmony_ci	__le32 vol_serial;
118a7ce5b29Sopenharmony_ci	__u8 fs_version[2];
119a7ce5b29Sopenharmony_ci	__le16 vol_flags;
120a7ce5b29Sopenharmony_ci	__u8 sect_size_bits;
121a7ce5b29Sopenharmony_ci	__u8 sect_per_clus_bits;
122a7ce5b29Sopenharmony_ci	__u8 num_fats;
123a7ce5b29Sopenharmony_ci	__u8 phy_drv_no;
124a7ce5b29Sopenharmony_ci	__u8 perc_in_use;
125a7ce5b29Sopenharmony_ci	__u8 reserved2[7];
126a7ce5b29Sopenharmony_ci};
127a7ce5b29Sopenharmony_ci
128a7ce5b29Sopenharmony_ci/* Common PBR[Partition Boot Record] (512 bytes) */
129a7ce5b29Sopenharmony_cistruct pbr {
130a7ce5b29Sopenharmony_ci	struct bpb64 bpb;
131a7ce5b29Sopenharmony_ci	struct bsx64 bsx;
132a7ce5b29Sopenharmony_ci	__u8 boot_code[390];
133a7ce5b29Sopenharmony_ci	__le16 signature;
134a7ce5b29Sopenharmony_ci};
135a7ce5b29Sopenharmony_ci
136a7ce5b29Sopenharmony_ci#define VOLUME_LABEL_MAX_LEN	11
137a7ce5b29Sopenharmony_ci#define ENTRY_NAME_MAX		15
138a7ce5b29Sopenharmony_ci
139a7ce5b29Sopenharmony_cistruct exfat_dentry {
140a7ce5b29Sopenharmony_ci	__u8 type;
141a7ce5b29Sopenharmony_ci	union {
142a7ce5b29Sopenharmony_ci		struct {
143a7ce5b29Sopenharmony_ci			__u8 character_count;
144a7ce5b29Sopenharmony_ci			__le16 volume_label[VOLUME_LABEL_MAX_LEN];
145a7ce5b29Sopenharmony_ci			__u8 reserved[8];
146a7ce5b29Sopenharmony_ci		} __attribute__((packed)) vol; /* file directory entry */
147a7ce5b29Sopenharmony_ci
148a7ce5b29Sopenharmony_ci		struct {
149a7ce5b29Sopenharmony_ci			__u8 num_ext;
150a7ce5b29Sopenharmony_ci			__le16 checksum;
151a7ce5b29Sopenharmony_ci			__le16 attr;
152a7ce5b29Sopenharmony_ci			__le16 reserved1;
153a7ce5b29Sopenharmony_ci			__le16 create_time;
154a7ce5b29Sopenharmony_ci			__le16 create_date;
155a7ce5b29Sopenharmony_ci			__le16 modify_time;
156a7ce5b29Sopenharmony_ci			__le16 modify_date;
157a7ce5b29Sopenharmony_ci			__le16 access_time;
158a7ce5b29Sopenharmony_ci			__le16 access_date;
159a7ce5b29Sopenharmony_ci			__u8 create_time_ms;
160a7ce5b29Sopenharmony_ci			__u8 modify_time_ms;
161a7ce5b29Sopenharmony_ci			__u8 create_tz;
162a7ce5b29Sopenharmony_ci			__u8 modify_tz;
163a7ce5b29Sopenharmony_ci			__u8 access_tz;
164a7ce5b29Sopenharmony_ci			__u8 reserved2[7];
165a7ce5b29Sopenharmony_ci		} __attribute__((packed)) file; /* file directory entry */
166a7ce5b29Sopenharmony_ci		struct {
167a7ce5b29Sopenharmony_ci			__u8 flags;
168a7ce5b29Sopenharmony_ci			__u8 reserved1;
169a7ce5b29Sopenharmony_ci			__u8 name_len;
170a7ce5b29Sopenharmony_ci			__le16 name_hash;
171a7ce5b29Sopenharmony_ci			__le16 reserved2;
172a7ce5b29Sopenharmony_ci			__le64 valid_size;
173a7ce5b29Sopenharmony_ci			__le32 reserved3;
174a7ce5b29Sopenharmony_ci			__le32 start_clu;
175a7ce5b29Sopenharmony_ci			__le64 size;
176a7ce5b29Sopenharmony_ci		} __attribute__((packed)) stream; /* stream extension directory entry */
177a7ce5b29Sopenharmony_ci		struct {
178a7ce5b29Sopenharmony_ci			__u8 flags;
179a7ce5b29Sopenharmony_ci			__le16 unicode_0_14[15];
180a7ce5b29Sopenharmony_ci		} __attribute__((packed)) name; /* file name directory entry */
181a7ce5b29Sopenharmony_ci		struct {
182a7ce5b29Sopenharmony_ci			__u8 flags;
183a7ce5b29Sopenharmony_ci			__u8 reserved[18];
184a7ce5b29Sopenharmony_ci			__le32 start_clu;
185a7ce5b29Sopenharmony_ci			__le64 size;
186a7ce5b29Sopenharmony_ci		} __attribute__((packed)) bitmap; /* allocation bitmap directory entry */
187a7ce5b29Sopenharmony_ci		struct {
188a7ce5b29Sopenharmony_ci			__u8 reserved1[3];
189a7ce5b29Sopenharmony_ci			__le32 checksum;
190a7ce5b29Sopenharmony_ci			__u8 reserved2[12];
191a7ce5b29Sopenharmony_ci			__le32 start_clu;
192a7ce5b29Sopenharmony_ci			__le64 size;
193a7ce5b29Sopenharmony_ci		} __attribute__((packed)) upcase; /* up-case table directory entry */
194a7ce5b29Sopenharmony_ci	} __attribute__((packed)) dentry;
195a7ce5b29Sopenharmony_ci} __attribute__((packed));
196a7ce5b29Sopenharmony_ci
197a7ce5b29Sopenharmony_ci#define vol_char_cnt			dentry.vol.character_count
198a7ce5b29Sopenharmony_ci#define vol_label			dentry.vol.volume_label
199a7ce5b29Sopenharmony_ci#define file_num_ext			dentry.file.num_ext
200a7ce5b29Sopenharmony_ci#define file_checksum			dentry.file.checksum
201a7ce5b29Sopenharmony_ci#define file_attr			dentry.file.attr
202a7ce5b29Sopenharmony_ci#define file_create_time		dentry.file.create_time
203a7ce5b29Sopenharmony_ci#define file_create_date		dentry.file.create_date
204a7ce5b29Sopenharmony_ci#define file_modify_time		dentry.file.modify_time
205a7ce5b29Sopenharmony_ci#define file_modify_date		dentry.file.modify_date
206a7ce5b29Sopenharmony_ci#define file_access_time		dentry.file.access_time
207a7ce5b29Sopenharmony_ci#define file_access_date		dentry.file.access_date
208a7ce5b29Sopenharmony_ci#define file_create_time_ms		dentry.file.create_time_ms
209a7ce5b29Sopenharmony_ci#define file_modify_time_ms		dentry.file.modify_time_ms
210a7ce5b29Sopenharmony_ci#define file_access_time_ms		dentry.file.access_time_ms
211a7ce5b29Sopenharmony_ci#define stream_flags			dentry.stream.flags
212a7ce5b29Sopenharmony_ci#define stream_name_len			dentry.stream.name_len
213a7ce5b29Sopenharmony_ci#define stream_name_hash		dentry.stream.name_hash
214a7ce5b29Sopenharmony_ci#define stream_start_clu		dentry.stream.start_clu
215a7ce5b29Sopenharmony_ci#define stream_valid_size		dentry.stream.valid_size
216a7ce5b29Sopenharmony_ci#define stream_size			dentry.stream.size
217a7ce5b29Sopenharmony_ci#define name_flags			dentry.name.flags
218a7ce5b29Sopenharmony_ci#define name_unicode			dentry.name.unicode_0_14
219a7ce5b29Sopenharmony_ci#define bitmap_flags			dentry.bitmap.flags
220a7ce5b29Sopenharmony_ci#define bitmap_start_clu		dentry.bitmap.start_clu
221a7ce5b29Sopenharmony_ci#define bitmap_size			dentry.bitmap.size
222a7ce5b29Sopenharmony_ci#define upcase_start_clu		dentry.upcase.start_clu
223a7ce5b29Sopenharmony_ci#define upcase_size			dentry.upcase.size
224a7ce5b29Sopenharmony_ci#define upcase_checksum			dentry.upcase.checksum
225a7ce5b29Sopenharmony_ci
226a7ce5b29Sopenharmony_ci#endif /* !_EXFAT_H */
227