Commit | Line | Data |
---|---|---|
a358eea0 | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
c48c9f7f VK |
2 | /* |
3 | * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. | |
4 | */ | |
5 | ||
6 | #ifndef _EXFAT_H | |
7 | #define _EXFAT_H | |
8 | ||
9 | #include <linux/types.h> | |
10 | #include <linux/buffer_head.h> | |
11 | ||
5f33771f | 12 | #ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG |
c48c9f7f VK |
13 | /* For Debugging Purpose */ |
14 | /* IOCTL code 'f' used by | |
15 | * - file systems typically #0~0x1F | |
16 | * - embedded terminal devices #128~ | |
17 | * - exts for debugging purpose #99 | |
18 | * number 100 and 101 is available now but has possible conflicts | |
19 | */ | |
20 | #define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) | |
21 | #define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) | |
22 | ||
23 | #define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 | |
24 | #define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 | |
5f33771f | 25 | #endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ |
c48c9f7f | 26 | |
5f33771f | 27 | #ifdef CONFIG_STAGING_EXFAT_DEBUG_MSG |
c48c9f7f VK |
28 | #define DEBUG 1 |
29 | #else | |
30 | #undef DEBUG | |
31 | #endif | |
32 | ||
133c8874 VK |
33 | #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ |
34 | ||
c48c9f7f VK |
35 | #define DENTRY_SIZE 32 /* dir entry size */ |
36 | #define DENTRY_SIZE_BITS 5 | |
37 | ||
38 | /* PBR entries */ | |
39 | #define PBR_SIGNATURE 0xAA55 | |
40 | #define EXT_SIGNATURE 0xAA550000 | |
41 | #define VOL_LABEL "NO NAME " /* size should be 11 */ | |
42 | #define OEM_NAME "MSWIN4.1" /* size should be 8 */ | |
43 | #define STR_FAT12 "FAT12 " /* size should be 8 */ | |
44 | #define STR_FAT16 "FAT16 " /* size should be 8 */ | |
45 | #define STR_FAT32 "FAT32 " /* size should be 8 */ | |
46 | #define STR_EXFAT "EXFAT " /* size should be 8 */ | |
47 | #define VOL_CLEAN 0x0000 | |
48 | #define VOL_DIRTY 0x0002 | |
49 | ||
50 | /* max number of clusters */ | |
51 | #define FAT12_THRESHOLD 4087 /* 2^12 - 1 + 2 (clu 0 & 1) */ | |
52 | #define FAT16_THRESHOLD 65527 /* 2^16 - 1 + 2 */ | |
53 | #define FAT32_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ | |
54 | #define EXFAT_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ | |
55 | ||
56 | /* file types */ | |
57 | #define TYPE_UNUSED 0x0000 | |
58 | #define TYPE_DELETED 0x0001 | |
59 | #define TYPE_INVALID 0x0002 | |
60 | #define TYPE_CRITICAL_PRI 0x0100 | |
61 | #define TYPE_BITMAP 0x0101 | |
62 | #define TYPE_UPCASE 0x0102 | |
63 | #define TYPE_VOLUME 0x0103 | |
64 | #define TYPE_DIR 0x0104 | |
65 | #define TYPE_FILE 0x011F | |
66 | #define TYPE_SYMLINK 0x015F | |
67 | #define TYPE_CRITICAL_SEC 0x0200 | |
68 | #define TYPE_STREAM 0x0201 | |
69 | #define TYPE_EXTEND 0x0202 | |
70 | #define TYPE_ACL 0x0203 | |
71 | #define TYPE_BENIGN_PRI 0x0400 | |
72 | #define TYPE_GUID 0x0401 | |
73 | #define TYPE_PADDING 0x0402 | |
74 | #define TYPE_ACLTAB 0x0403 | |
75 | #define TYPE_BENIGN_SEC 0x0800 | |
76 | #define TYPE_ALL 0x0FFF | |
77 | ||
78 | /* time modes */ | |
79 | #define TM_CREATE 0 | |
80 | #define TM_MODIFY 1 | |
81 | #define TM_ACCESS 2 | |
82 | ||
83 | /* checksum types */ | |
84 | #define CS_DIR_ENTRY 0 | |
85 | #define CS_PBR_SECTOR 1 | |
86 | #define CS_DEFAULT 2 | |
87 | ||
88 | #define CLUSTER_16(x) ((u16)(x)) | |
89 | #define CLUSTER_32(x) ((u32)(x)) | |
90 | ||
c48c9f7f VK |
91 | #define START_SECTOR(x) \ |
92 | ((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) + \ | |
93 | p_fs->data_start_sector) | |
94 | ||
95 | #define IS_LAST_SECTOR_IN_CLUSTER(sec) \ | |
96 | ((((sec) - p_fs->data_start_sector + 1) & \ | |
97 | ((1 << p_fs->sectors_per_clu_bits) - 1)) == 0) | |
98 | ||
99 | #define GET_CLUSTER_FROM_SECTOR(sec) \ | |
100 | ((u32)((((sec) - p_fs->data_start_sector) >> \ | |
101 | p_fs->sectors_per_clu_bits) + 2)) | |
102 | ||
103 | #define GET16(p_src) \ | |
104 | (((u16)(p_src)[0]) | (((u16)(p_src)[1]) << 8)) | |
105 | #define GET32(p_src) \ | |
106 | (((u32)(p_src)[0]) | (((u32)(p_src)[1]) << 8) | \ | |
107 | (((u32)(p_src)[2]) << 16) | (((u32)(p_src)[3]) << 24)) | |
108 | #define GET64(p_src) \ | |
109 | (((u64)(p_src)[0]) | (((u64)(p_src)[1]) << 8) | \ | |
110 | (((u64)(p_src)[2]) << 16) | (((u64)(p_src)[3]) << 24) | \ | |
111 | (((u64)(p_src)[4]) << 32) | (((u64)(p_src)[5]) << 40) | \ | |
112 | (((u64)(p_src)[6]) << 48) | (((u64)(p_src)[7]) << 56)) | |
113 | ||
114 | #define SET16(p_dst, src) \ | |
115 | do { \ | |
116 | (p_dst)[0] = (u8)(src); \ | |
117 | (p_dst)[1] = (u8)(((u16)(src)) >> 8); \ | |
118 | } while (0) | |
119 | #define SET32(p_dst, src) \ | |
120 | do { \ | |
121 | (p_dst)[0] = (u8)(src); \ | |
122 | (p_dst)[1] = (u8)(((u32)(src)) >> 8); \ | |
123 | (p_dst)[2] = (u8)(((u32)(src)) >> 16); \ | |
124 | (p_dst)[3] = (u8)(((u32)(src)) >> 24); \ | |
125 | } while (0) | |
126 | #define SET64(p_dst, src) \ | |
127 | do { \ | |
128 | (p_dst)[0] = (u8)(src); \ | |
129 | (p_dst)[1] = (u8)(((u64)(src)) >> 8); \ | |
130 | (p_dst)[2] = (u8)(((u64)(src)) >> 16); \ | |
131 | (p_dst)[3] = (u8)(((u64)(src)) >> 24); \ | |
132 | (p_dst)[4] = (u8)(((u64)(src)) >> 32); \ | |
133 | (p_dst)[5] = (u8)(((u64)(src)) >> 40); \ | |
134 | (p_dst)[6] = (u8)(((u64)(src)) >> 48); \ | |
135 | (p_dst)[7] = (u8)(((u64)(src)) >> 56); \ | |
136 | } while (0) | |
137 | ||
138 | #ifdef __LITTLE_ENDIAN | |
139 | #define GET16_A(p_src) (*((u16 *)(p_src))) | |
140 | #define GET32_A(p_src) (*((u32 *)(p_src))) | |
141 | #define GET64_A(p_src) (*((u64 *)(p_src))) | |
142 | #define SET16_A(p_dst, src) (*((u16 *)(p_dst)) = (u16)(src)) | |
143 | #define SET32_A(p_dst, src) (*((u32 *)(p_dst)) = (u32)(src)) | |
144 | #define SET64_A(p_dst, src) (*((u64 *)(p_dst)) = (u64)(src)) | |
145 | #else /* BIG_ENDIAN */ | |
146 | #define GET16_A(p_src) GET16(p_src) | |
147 | #define GET32_A(p_src) GET32(p_src) | |
148 | #define GET64_A(p_src) GET64(p_src) | |
149 | #define SET16_A(p_dst, src) SET16(p_dst, src) | |
150 | #define SET32_A(p_dst, src) SET32(p_dst, src) | |
151 | #define SET64_A(p_dst, src) SET64(p_dst, src) | |
152 | #endif | |
153 | ||
154 | /* cache size (in number of sectors) */ | |
155 | /* (should be an exponential value of 2) */ | |
156 | #define FAT_CACHE_SIZE 128 | |
157 | #define FAT_CACHE_HASH_SIZE 64 | |
158 | #define BUF_CACHE_SIZE 256 | |
159 | #define BUF_CACHE_HASH_SIZE 64 | |
160 | ||
161 | /* Upcase table macro */ | |
162 | #define HIGH_INDEX_BIT (8) | |
163 | #define HIGH_INDEX_MASK (0xFF00) | |
179e14c8 | 164 | #define LOW_INDEX_BIT (16 - HIGH_INDEX_BIT) |
ef16b89c VV |
165 | #define UTBL_ROW_COUNT BIT(LOW_INDEX_BIT) |
166 | #define UTBL_COL_COUNT BIT(HIGH_INDEX_BIT) | |
c48c9f7f VK |
167 | |
168 | static inline u16 get_col_index(u16 i) | |
169 | { | |
170 | return i >> LOW_INDEX_BIT; | |
171 | } | |
5b489e2f | 172 | |
c48c9f7f VK |
173 | static inline u16 get_row_index(u16 i) |
174 | { | |
175 | return i & ~HIGH_INDEX_MASK; | |
176 | } | |
177 | ||
178 | #define EXFAT_SUPER_MAGIC (0x2011BAB0L) | |
179 | #define EXFAT_ROOT_INO 1 | |
180 | ||
181 | /* FAT types */ | |
182 | #define FAT12 0x01 /* FAT12 */ | |
183 | #define FAT16 0x0E /* Win95 FAT16 (LBA) */ | |
184 | #define FAT32 0x0C /* Win95 FAT32 (LBA) */ | |
185 | #define EXFAT 0x07 /* exFAT */ | |
186 | ||
187 | /* file name lengths */ | |
188 | #define MAX_CHARSET_SIZE 3 /* max size of multi-byte character */ | |
189 | #define MAX_PATH_DEPTH 15 /* max depth of path name */ | |
190 | #define MAX_NAME_LENGTH 256 /* max len of filename including NULL */ | |
191 | #define MAX_PATH_LENGTH 260 /* max len of pathname including NULL */ | |
192 | #define DOS_NAME_LENGTH 11 /* DOS filename length excluding NULL */ | |
193 | #define DOS_PATH_LENGTH 80 /* DOS pathname length excluding NULL */ | |
194 | ||
195 | /* file attributes */ | |
196 | #define ATTR_NORMAL 0x0000 | |
197 | #define ATTR_READONLY 0x0001 | |
198 | #define ATTR_HIDDEN 0x0002 | |
199 | #define ATTR_SYSTEM 0x0004 | |
200 | #define ATTR_VOLUME 0x0008 | |
201 | #define ATTR_SUBDIR 0x0010 | |
202 | #define ATTR_ARCHIVE 0x0020 | |
203 | #define ATTR_SYMLINK 0x0040 | |
204 | #define ATTR_EXTEND 0x000F | |
205 | #define ATTR_RWMASK 0x007E | |
206 | ||
207 | /* file creation modes */ | |
208 | #define FM_REGULAR 0x00 | |
209 | #define FM_SYMLINK 0x40 | |
210 | ||
c48c9f7f VK |
211 | #define NUM_UPCASE 2918 |
212 | ||
213 | #define DOS_CUR_DIR_NAME ". " | |
214 | #define DOS_PAR_DIR_NAME ".. " | |
215 | ||
216 | #ifdef __LITTLE_ENDIAN | |
217 | #define UNI_CUR_DIR_NAME ".\0" | |
218 | #define UNI_PAR_DIR_NAME ".\0.\0" | |
219 | #else | |
220 | #define UNI_CUR_DIR_NAME "\0." | |
221 | #define UNI_PAR_DIR_NAME "\0.\0." | |
222 | #endif | |
223 | ||
224 | struct date_time_t { | |
225 | u16 Year; | |
226 | u16 Month; | |
227 | u16 Day; | |
228 | u16 Hour; | |
229 | u16 Minute; | |
230 | u16 Second; | |
231 | u16 MilliSecond; | |
232 | }; | |
233 | ||
234 | struct part_info_t { | |
235 | u32 Offset; /* start sector number of the partition */ | |
236 | u32 Size; /* in sectors */ | |
237 | }; | |
238 | ||
239 | struct dev_info_t { | |
240 | u32 SecSize; /* sector size in bytes */ | |
241 | u32 DevSize; /* block device size in sectors */ | |
242 | }; | |
243 | ||
244 | struct vol_info_t { | |
245 | u32 FatType; | |
246 | u32 ClusterSize; | |
247 | u32 NumClusters; | |
248 | u32 FreeClusters; | |
249 | u32 UsedClusters; | |
250 | }; | |
251 | ||
252 | /* directory structure */ | |
253 | struct chain_t { | |
254 | u32 dir; | |
255 | s32 size; | |
256 | u8 flags; | |
257 | }; | |
258 | ||
259 | struct file_id_t { | |
260 | struct chain_t dir; | |
261 | s32 entry; | |
262 | u32 type; | |
263 | u32 attr; | |
264 | u32 start_clu; | |
265 | u64 size; | |
266 | u8 flags; | |
267 | s64 rwoffset; | |
268 | s32 hint_last_off; | |
269 | u32 hint_last_clu; | |
270 | }; | |
271 | ||
272 | struct dir_entry_t { | |
273 | char Name[MAX_NAME_LENGTH * MAX_CHARSET_SIZE]; | |
274 | ||
275 | /* used only for FAT12/16/32, not used for exFAT */ | |
276 | char ShortName[DOS_NAME_LENGTH + 2]; | |
277 | ||
278 | u32 Attr; | |
279 | u64 Size; | |
280 | u32 NumSubdirs; | |
281 | struct date_time_t CreateTimestamp; | |
282 | struct date_time_t ModifyTimestamp; | |
283 | struct date_time_t AccessTimestamp; | |
284 | }; | |
285 | ||
286 | struct timestamp_t { | |
287 | u16 sec; /* 0 ~ 59 */ | |
288 | u16 min; /* 0 ~ 59 */ | |
289 | u16 hour; /* 0 ~ 23 */ | |
290 | u16 day; /* 1 ~ 31 */ | |
291 | u16 mon; /* 1 ~ 12 */ | |
292 | u16 year; /* 0 ~ 127 (since 1980) */ | |
293 | }; | |
294 | ||
295 | /* MS_DOS FAT partition boot record (512 bytes) */ | |
296 | struct pbr_sector_t { | |
297 | u8 jmp_boot[3]; | |
298 | u8 oem_name[8]; | |
299 | u8 bpb[109]; | |
300 | u8 boot_code[390]; | |
301 | u8 signature[2]; | |
302 | }; | |
303 | ||
304 | /* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */ | |
305 | struct bpb16_t { | |
306 | u8 sector_size[2]; | |
307 | u8 sectors_per_clu; | |
308 | u8 num_reserved[2]; | |
309 | u8 num_fats; | |
310 | u8 num_root_entries[2]; | |
311 | u8 num_sectors[2]; | |
312 | u8 media_type; | |
313 | u8 num_fat_sectors[2]; | |
314 | u8 sectors_in_track[2]; | |
315 | u8 num_heads[2]; | |
316 | u8 num_hid_sectors[4]; | |
317 | u8 num_huge_sectors[4]; | |
318 | ||
319 | u8 phy_drv_no; | |
320 | u8 reserved; | |
321 | u8 ext_signature; | |
322 | u8 vol_serial[4]; | |
323 | u8 vol_label[11]; | |
324 | u8 vol_type[8]; | |
325 | }; | |
326 | ||
327 | /* MS-DOS FAT32 BIOS parameter block (79 bytes) */ | |
328 | struct bpb32_t { | |
329 | u8 sector_size[2]; | |
330 | u8 sectors_per_clu; | |
331 | u8 num_reserved[2]; | |
332 | u8 num_fats; | |
333 | u8 num_root_entries[2]; | |
334 | u8 num_sectors[2]; | |
335 | u8 media_type; | |
336 | u8 num_fat_sectors[2]; | |
337 | u8 sectors_in_track[2]; | |
338 | u8 num_heads[2]; | |
339 | u8 num_hid_sectors[4]; | |
340 | u8 num_huge_sectors[4]; | |
341 | u8 num_fat32_sectors[4]; | |
342 | u8 ext_flags[2]; | |
343 | u8 fs_version[2]; | |
344 | u8 root_cluster[4]; | |
345 | u8 fsinfo_sector[2]; | |
346 | u8 backup_sector[2]; | |
347 | u8 reserved[12]; | |
348 | ||
349 | u8 phy_drv_no; | |
350 | u8 ext_reserved; | |
351 | u8 ext_signature; | |
352 | u8 vol_serial[4]; | |
353 | u8 vol_label[11]; | |
354 | u8 vol_type[8]; | |
355 | }; | |
356 | ||
357 | /* MS-DOS EXFAT BIOS parameter block (109 bytes) */ | |
358 | struct bpbex_t { | |
359 | u8 reserved1[53]; | |
360 | u8 vol_offset[8]; | |
361 | u8 vol_length[8]; | |
362 | u8 fat_offset[4]; | |
363 | u8 fat_length[4]; | |
364 | u8 clu_offset[4]; | |
365 | u8 clu_count[4]; | |
366 | u8 root_cluster[4]; | |
367 | u8 vol_serial[4]; | |
368 | u8 fs_version[2]; | |
369 | u8 vol_flags[2]; | |
370 | u8 sector_size_bits; | |
371 | u8 sectors_per_clu_bits; | |
372 | u8 num_fats; | |
373 | u8 phy_drv_no; | |
374 | u8 perc_in_use; | |
375 | u8 reserved2[7]; | |
376 | }; | |
377 | ||
378 | /* MS-DOS FAT file system information sector (512 bytes) */ | |
379 | struct fsi_sector_t { | |
380 | u8 signature1[4]; | |
381 | u8 reserved1[480]; | |
382 | u8 signature2[4]; | |
383 | u8 free_cluster[4]; | |
384 | u8 next_cluster[4]; | |
385 | u8 reserved2[14]; | |
386 | u8 signature3[2]; | |
387 | }; | |
388 | ||
389 | /* MS-DOS FAT directory entry (32 bytes) */ | |
390 | struct dentry_t { | |
391 | u8 dummy[32]; | |
392 | }; | |
393 | ||
394 | struct dos_dentry_t { | |
395 | u8 name[DOS_NAME_LENGTH]; | |
396 | u8 attr; | |
397 | u8 lcase; | |
398 | u8 create_time_ms; | |
399 | u8 create_time[2]; | |
400 | u8 create_date[2]; | |
401 | u8 access_date[2]; | |
402 | u8 start_clu_hi[2]; | |
403 | u8 modify_time[2]; | |
404 | u8 modify_date[2]; | |
405 | u8 start_clu_lo[2]; | |
406 | u8 size[4]; | |
407 | }; | |
408 | ||
409 | /* MS-DOS FAT extended directory entry (32 bytes) */ | |
410 | struct ext_dentry_t { | |
411 | u8 order; | |
412 | u8 unicode_0_4[10]; | |
413 | u8 attr; | |
414 | u8 sysid; | |
415 | u8 checksum; | |
416 | u8 unicode_5_10[12]; | |
417 | u8 start_clu[2]; | |
418 | u8 unicode_11_12[4]; | |
419 | }; | |
420 | ||
421 | /* MS-DOS EXFAT file directory entry (32 bytes) */ | |
422 | struct file_dentry_t { | |
423 | u8 type; | |
424 | u8 num_ext; | |
425 | u8 checksum[2]; | |
426 | u8 attr[2]; | |
427 | u8 reserved1[2]; | |
428 | u8 create_time[2]; | |
429 | u8 create_date[2]; | |
430 | u8 modify_time[2]; | |
431 | u8 modify_date[2]; | |
432 | u8 access_time[2]; | |
433 | u8 access_date[2]; | |
434 | u8 create_time_ms; | |
435 | u8 modify_time_ms; | |
436 | u8 access_time_ms; | |
437 | u8 reserved2[9]; | |
438 | }; | |
439 | ||
440 | /* MS-DOS EXFAT stream extension directory entry (32 bytes) */ | |
441 | struct strm_dentry_t { | |
442 | u8 type; | |
443 | u8 flags; | |
444 | u8 reserved1; | |
445 | u8 name_len; | |
446 | u8 name_hash[2]; | |
447 | u8 reserved2[2]; | |
448 | u8 valid_size[8]; | |
449 | u8 reserved3[4]; | |
450 | u8 start_clu[4]; | |
451 | u8 size[8]; | |
452 | }; | |
453 | ||
454 | /* MS-DOS EXFAT file name directory entry (32 bytes) */ | |
455 | struct name_dentry_t { | |
456 | u8 type; | |
457 | u8 flags; | |
458 | u8 unicode_0_14[30]; | |
459 | }; | |
460 | ||
461 | /* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */ | |
462 | struct bmap_dentry_t { | |
463 | u8 type; | |
464 | u8 flags; | |
465 | u8 reserved[18]; | |
466 | u8 start_clu[4]; | |
467 | u8 size[8]; | |
468 | }; | |
469 | ||
470 | /* MS-DOS EXFAT up-case table directory entry (32 bytes) */ | |
471 | struct case_dentry_t { | |
472 | u8 type; | |
473 | u8 reserved1[3]; | |
474 | u8 checksum[4]; | |
475 | u8 reserved2[12]; | |
476 | u8 start_clu[4]; | |
477 | u8 size[8]; | |
478 | }; | |
479 | ||
480 | /* MS-DOS EXFAT volume label directory entry (32 bytes) */ | |
481 | struct volm_dentry_t { | |
482 | u8 type; | |
483 | u8 label_len; | |
484 | u8 unicode_0_10[22]; | |
485 | u8 reserved[8]; | |
486 | }; | |
487 | ||
488 | /* unused entry hint information */ | |
489 | struct uentry_t { | |
490 | u32 dir; | |
491 | s32 entry; | |
492 | struct chain_t clu; | |
493 | }; | |
494 | ||
495 | /* DOS name structure */ | |
496 | struct dos_name_t { | |
497 | u8 name[DOS_NAME_LENGTH]; | |
498 | u8 name_case; | |
499 | }; | |
500 | ||
501 | /* unicode name structure */ | |
502 | struct uni_name_t { | |
503 | u16 name[MAX_NAME_LENGTH]; | |
504 | u16 name_hash; | |
505 | u8 name_len; | |
506 | }; | |
507 | ||
508 | struct buf_cache_t { | |
509 | struct buf_cache_t *next; | |
510 | struct buf_cache_t *prev; | |
511 | struct buf_cache_t *hash_next; | |
512 | struct buf_cache_t *hash_prev; | |
513 | s32 drv; | |
514 | sector_t sec; | |
515 | u32 flag; | |
516 | struct buffer_head *buf_bh; | |
517 | }; | |
518 | ||
c48c9f7f VK |
519 | struct fs_info_t { |
520 | u32 drv; /* drive ID */ | |
521 | u32 vol_type; /* volume FAT type */ | |
522 | u32 vol_id; /* volume serial number */ | |
523 | ||
524 | u64 num_sectors; /* num of sectors in volume */ | |
525 | u32 num_clusters; /* num of clusters in volume */ | |
526 | u32 cluster_size; /* cluster size in bytes */ | |
527 | u32 cluster_size_bits; | |
528 | u32 sectors_per_clu; /* cluster size in sectors */ | |
529 | u32 sectors_per_clu_bits; | |
530 | ||
531 | u32 PBR_sector; /* PBR sector */ | |
532 | u32 FAT1_start_sector; /* FAT1 start sector */ | |
533 | u32 FAT2_start_sector; /* FAT2 start sector */ | |
534 | u32 root_start_sector; /* root dir start sector */ | |
535 | u32 data_start_sector; /* data area start sector */ | |
536 | u32 num_FAT_sectors; /* num of FAT sectors */ | |
537 | ||
538 | u32 root_dir; /* root dir cluster */ | |
539 | u32 dentries_in_root; /* num of dentries in root dir */ | |
540 | u32 dentries_per_clu; /* num of dentries per cluster */ | |
541 | ||
542 | u32 vol_flag; /* volume dirty flag */ | |
543 | struct buffer_head *pbr_bh; /* PBR sector */ | |
544 | ||
545 | u32 map_clu; /* allocation bitmap start cluster */ | |
546 | u32 map_sectors; /* num of allocation bitmap sectors */ | |
547 | struct buffer_head **vol_amap; /* allocation bitmap */ | |
548 | ||
549 | u16 **vol_utbl; /* upcase table */ | |
550 | ||
551 | u32 clu_srch_ptr; /* cluster search pointer */ | |
552 | u32 used_clusters; /* number of used clusters */ | |
553 | struct uentry_t hint_uentry; /* unused entry hint information */ | |
554 | ||
555 | u32 dev_ejected; /* block device operation error flag */ | |
556 | ||
3ae82f44 | 557 | struct mutex v_mutex; |
c48c9f7f VK |
558 | |
559 | /* FAT cache */ | |
560 | struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE]; | |
561 | struct buf_cache_t FAT_cache_lru_list; | |
562 | struct buf_cache_t FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; | |
563 | ||
564 | /* buf cache */ | |
565 | struct buf_cache_t buf_cache_array[BUF_CACHE_SIZE]; | |
566 | struct buf_cache_t buf_cache_lru_list; | |
567 | struct buf_cache_t buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; | |
568 | }; | |
569 | ||
570 | #define ES_2_ENTRIES 2 | |
571 | #define ES_3_ENTRIES 3 | |
572 | #define ES_ALL_ENTRIES 0 | |
573 | ||
574 | struct entry_set_cache_t { | |
575 | /* sector number that contains file_entry */ | |
576 | sector_t sector; | |
577 | ||
578 | /* byte offset in the sector */ | |
579 | s32 offset; | |
580 | ||
581 | /* | |
582 | * flag in stream entry. | |
583 | * 01 for cluster chain, | |
584 | * 03 for contig. clusteres. | |
585 | */ | |
586 | s32 alloc_flag; | |
587 | ||
588 | u32 num_entries; | |
589 | ||
590 | /* __buf should be the last member */ | |
591 | void *__buf; | |
592 | }; | |
593 | ||
594 | #define EXFAT_ERRORS_CONT 1 /* ignore error and continue */ | |
595 | #define EXFAT_ERRORS_PANIC 2 /* panic on error */ | |
596 | #define EXFAT_ERRORS_RO 3 /* remount r/o on error */ | |
597 | ||
598 | /* ioctl command */ | |
599 | #define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) | |
600 | ||
601 | struct exfat_mount_options { | |
602 | kuid_t fs_uid; | |
603 | kgid_t fs_gid; | |
604 | unsigned short fs_fmask; | |
605 | unsigned short fs_dmask; | |
606 | ||
607 | /* permission for setting the [am]time */ | |
608 | unsigned short allow_utime; | |
609 | ||
610 | /* codepage for shortname conversions */ | |
611 | unsigned short codepage; | |
612 | ||
613 | /* charset for filename input/display */ | |
614 | char *iocharset; | |
615 | ||
616 | unsigned char casesensitive; | |
617 | ||
618 | /* on error: continue, panic, remount-ro */ | |
619 | unsigned char errors; | |
5f33771f | 620 | #ifdef CONFIG_STAGING_EXFAT_DISCARD |
c48c9f7f VK |
621 | /* flag on if -o dicard specified and device support discard() */ |
622 | unsigned char discard; | |
5f33771f | 623 | #endif /* CONFIG_STAGING_EXFAT_DISCARD */ |
c48c9f7f VK |
624 | }; |
625 | ||
626 | #define EXFAT_HASH_BITS 8 | |
ef16b89c | 627 | #define EXFAT_HASH_SIZE BIT(EXFAT_HASH_BITS) |
c48c9f7f VK |
628 | |
629 | /* | |
630 | * EXFAT file system in-core superblock data | |
631 | */ | |
632 | struct bd_info_t { | |
633 | s32 sector_size; /* in bytes */ | |
634 | s32 sector_size_bits; | |
635 | s32 sector_size_mask; | |
636 | ||
637 | /* total number of sectors in this block device */ | |
638 | s32 num_sectors; | |
639 | ||
640 | /* opened or not */ | |
641 | bool opened; | |
642 | }; | |
643 | ||
644 | struct exfat_sb_info { | |
645 | struct fs_info_t fs_info; | |
646 | struct bd_info_t bd_info; | |
647 | ||
648 | struct exfat_mount_options options; | |
649 | ||
650 | int s_dirt; | |
651 | struct mutex s_lock; | |
652 | struct nls_table *nls_disk; /* Codepage used on disk */ | |
653 | struct nls_table *nls_io; /* Charset used for input and display */ | |
654 | ||
655 | struct inode *fat_inode; | |
656 | ||
657 | spinlock_t inode_hash_lock; | |
658 | struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; | |
5f33771f | 659 | #ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG |
c48c9f7f | 660 | long debug_flags; |
5f33771f | 661 | #endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ |
c48c9f7f VK |
662 | }; |
663 | ||
664 | /* | |
665 | * EXFAT file system inode data in memory | |
666 | */ | |
667 | struct exfat_inode_info { | |
668 | struct file_id_t fid; | |
669 | char *target; | |
670 | /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ | |
671 | loff_t mmu_private; /* physically allocated size */ | |
672 | loff_t i_pos; /* on-disk position of directory entry or 0 */ | |
673 | struct hlist_node i_hash_fat; /* hash by i_location */ | |
674 | struct rw_semaphore truncate_lock; | |
675 | struct inode vfs_inode; | |
676 | struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */ | |
677 | }; | |
678 | ||
679 | #define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info)) | |
680 | ||
681 | static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) | |
682 | { | |
683 | return container_of(inode, struct exfat_inode_info, vfs_inode); | |
684 | } | |
685 | ||
686 | /* NLS management function */ | |
687 | u16 nls_upper(struct super_block *sb, u16 a); | |
c48c9f7f | 688 | int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b); |
c48c9f7f VK |
689 | void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, |
690 | struct uni_name_t *p_uniname); | |
691 | void nls_cstring_to_uniname(struct super_block *sb, | |
692 | struct uni_name_t *p_uniname, u8 *p_cstring, | |
693 | bool *p_lossy); | |
694 | ||
695 | /* buffer cache management */ | |
99a4b135 VK |
696 | void exfat_buf_init(struct super_block *sb); |
697 | void exfat_buf_shutdown(struct super_block *sb); | |
65b88d81 VK |
698 | int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content); |
699 | s32 exfat_fat_write(struct super_block *sb, u32 loc, u32 content); | |
700 | u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec); | |
701 | void exfat_fat_modify(struct super_block *sb, sector_t sec); | |
702 | void exfat_fat_release_all(struct super_block *sb); | |
703 | void exfat_fat_sync(struct super_block *sb); | |
99a4b135 VK |
704 | u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec); |
705 | void exfat_buf_modify(struct super_block *sb, sector_t sec); | |
706 | void exfat_buf_lock(struct super_block *sb, sector_t sec); | |
707 | void exfat_buf_unlock(struct super_block *sb, sector_t sec); | |
708 | void exfat_buf_release(struct super_block *sb, sector_t sec); | |
709 | void exfat_buf_release_all(struct super_block *sb); | |
710 | void exfat_buf_sync(struct super_block *sb); | |
c48c9f7f VK |
711 | |
712 | /* fs management functions */ | |
713 | void fs_set_vol_flags(struct super_block *sb, u32 new_flag); | |
714 | void fs_error(struct super_block *sb); | |
715 | ||
716 | /* cluster management functions */ | |
c48c9f7f | 717 | s32 count_num_clusters(struct super_block *sb, struct chain_t *dir); |
c48c9f7f VK |
718 | void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len); |
719 | ||
720 | /* allocation bitmap management functions */ | |
721 | s32 load_alloc_bitmap(struct super_block *sb); | |
722 | void free_alloc_bitmap(struct super_block *sb); | |
c48c9f7f VK |
723 | void sync_alloc_bitmap(struct super_block *sb); |
724 | ||
725 | /* upcase table management functions */ | |
726 | s32 load_upcase_table(struct super_block *sb); | |
727 | void free_upcase_table(struct super_block *sb); | |
728 | ||
729 | /* dir entry management functions */ | |
c48c9f7f | 730 | struct timestamp_t *tm_current(struct timestamp_t *tm); |
c48c9f7f | 731 | |
c48c9f7f VK |
732 | struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, |
733 | s32 entry, sector_t *sector); | |
734 | struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, | |
735 | struct chain_t *p_dir, s32 entry, | |
736 | u32 type, | |
737 | struct dentry_t **file_ep); | |
738 | void release_entry_set(struct entry_set_cache_t *es); | |
c48c9f7f VK |
739 | s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir, |
740 | u32 type); | |
741 | void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, | |
742 | s32 entry); | |
743 | void update_dir_checksum_with_entry_set(struct super_block *sb, | |
744 | struct entry_set_cache_t *es); | |
745 | bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir); | |
746 | ||
747 | /* name conversion functions */ | |
748 | s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, | |
749 | struct uni_name_t *p_uniname, s32 *entries, | |
750 | struct dos_name_t *p_dosname); | |
c48c9f7f | 751 | u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type); |
c48c9f7f VK |
752 | |
753 | /* name resolution functions */ | |
754 | s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, | |
755 | struct uni_name_t *p_uniname); | |
c48c9f7f VK |
756 | |
757 | /* file operation functions */ | |
c48c9f7f VK |
758 | s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); |
759 | s32 create_dir(struct inode *inode, struct chain_t *p_dir, | |
760 | struct uni_name_t *p_uniname, struct file_id_t *fid); | |
761 | s32 create_file(struct inode *inode, struct chain_t *p_dir, | |
762 | struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid); | |
763 | void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry); | |
1af73a25 BH |
764 | s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry, |
765 | struct uni_name_t *p_uniname, struct file_id_t *fid); | |
c48c9f7f VK |
766 | s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, |
767 | struct chain_t *p_newdir, struct uni_name_t *p_uniname, | |
768 | struct file_id_t *fid); | |
769 | ||
770 | /* sector read/write functions */ | |
771 | int sector_read(struct super_block *sb, sector_t sec, | |
772 | struct buffer_head **bh, bool read); | |
773 | int sector_write(struct super_block *sb, sector_t sec, | |
774 | struct buffer_head *bh, bool sync); | |
775 | int multi_sector_read(struct super_block *sb, sector_t sec, | |
776 | struct buffer_head **bh, s32 num_secs, bool read); | |
777 | int multi_sector_write(struct super_block *sb, sector_t sec, | |
778 | struct buffer_head *bh, s32 num_secs, bool sync); | |
779 | ||
ed5916c1 VK |
780 | void exfat_bdev_open(struct super_block *sb); |
781 | void exfat_bdev_close(struct super_block *sb); | |
782 | int exfat_bdev_read(struct super_block *sb, sector_t secno, | |
c48c9f7f | 783 | struct buffer_head **bh, u32 num_secs, bool read); |
ed5916c1 | 784 | int exfat_bdev_write(struct super_block *sb, sector_t secno, |
c48c9f7f | 785 | struct buffer_head *bh, u32 num_secs, bool sync); |
ed5916c1 | 786 | int exfat_bdev_sync(struct super_block *sb); |
c48c9f7f | 787 | |
52b0c470 TK |
788 | /* cluster operation functions */ |
789 | s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, | |
790 | struct chain_t *p_chain); | |
791 | void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, | |
792 | s32 do_relse); | |
793 | s32 exfat_count_used_clusters(struct super_block *sb); | |
794 | ||
795 | /* dir operation functions */ | |
796 | s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, | |
797 | struct uni_name_t *p_uniname, s32 num_entries, | |
798 | struct dos_name_t *p_dosname, u32 type); | |
799 | void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, | |
800 | s32 entry, s32 order, s32 num_entries); | |
801 | void exfat_get_uni_name_from_ext_entry(struct super_block *sb, | |
802 | struct chain_t *p_dir, s32 entry, | |
803 | u16 *uniname); | |
804 | s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, | |
805 | s32 entry, struct dentry_t *p_entry); | |
806 | s32 exfat_calc_num_entries(struct uni_name_t *p_uniname); | |
807 | ||
808 | /* dir entry getter/setter */ | |
809 | u32 exfat_get_entry_type(struct dentry_t *p_entry); | |
810 | u32 exfat_get_entry_attr(struct dentry_t *p_entry); | |
811 | void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr); | |
812 | u8 exfat_get_entry_flag(struct dentry_t *p_entry); | |
813 | void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags); | |
814 | u32 exfat_get_entry_clu0(struct dentry_t *p_entry); | |
815 | void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu); | |
816 | u64 exfat_get_entry_size(struct dentry_t *p_entry); | |
817 | void exfat_set_entry_size(struct dentry_t *p_entry, u64 size); | |
818 | void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, | |
819 | u8 mode); | |
820 | void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, | |
821 | u8 mode); | |
822 | ||
c48c9f7f VK |
823 | extern const u8 uni_upcase[]; |
824 | #endif /* _EXFAT_H */ |