• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  *  Copyright (C) 2019 Namjae Jeon <linkinjeon@kernel.org>
4  */
5 
6 #ifndef _LIBEXFAT_H
7 
8 #include <stdbool.h>
9 #include <sys/types.h>
10 #include <wchar.h>
11 #include <limits.h>
12 
13 typedef __u32 clus_t;
14 
15 #define KB			(1024)
16 #define MB			(1024*1024)
17 #define GB			(1024UL*1024UL*1024UL)
18 
19 #define __round_mask(x, y) ((__typeof__(x))((y)-1))
20 #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
21 #define round_down(x, y) ((x) & ~__round_mask(x, y))
22 
23 #define MIN(a, b)	((a) < (b) ? (a) : (b))
24 #define MAX(a, b)	((a) > (b) ? (a) : (b))
25 
26 #define DIV_ROUND_UP(__i, __d)	(((__i) + (__d) - 1) / (__d))
27 
28 #define EXFAT_MIN_NUM_SEC_VOL		(2048)
29 #define EXFAT_MAX_NUM_SEC_VOL		((2 << 64) - 1)
30 
31 #define EXFAT_MAX_NUM_CLUSTER		(0xFFFFFFF5)
32 
33 #define DEFAULT_BOUNDARY_ALIGNMENT	(1024*1024)
34 
35 #define DEFAULT_SECTOR_SIZE	(512)
36 
37 #define VOLUME_LABEL_BUFFER_SIZE	(VOLUME_LABEL_MAX_LEN*MB_LEN_MAX+1)
38 
39 /* Upcase table macro */
40 #define EXFAT_UPCASE_TABLE_CHARS	(0x10000)
41 #define EXFAT_UPCASE_TABLE_SIZE		(5836)
42 
43 /* Flags for tune.exfat and exfatlabel */
44 #define EXFAT_GET_VOLUME_LABEL		0x01
45 #define EXFAT_SET_VOLUME_LABEL		0x02
46 #define EXFAT_GET_VOLUME_SERIAL		0x03
47 #define EXFAT_SET_VOLUME_SERIAL		0x04
48 
49 #define EXFAT_MAX_SECTOR_SIZE		4096
50 
51 #define EXFAT_CLUSTER_SIZE(pbr) (1 << ((pbr)->bsx.sect_size_bits +	\
52 					(pbr)->bsx.sect_per_clus_bits))
53 #define EXFAT_SECTOR_SIZE(pbr) (1 << (pbr)->bsx.sect_size_bits)
54 
55 enum {
56 	BOOT_SEC_IDX = 0,
57 	EXBOOT_SEC_IDX,
58 	EXBOOT_SEC_NUM = 8,
59 	OEM_SEC_IDX,
60 	RESERVED_SEC_IDX,
61 	CHECKSUM_SEC_IDX,
62 	BACKUP_BOOT_SEC_IDX,
63 };
64 
65 struct exfat_blk_dev {
66 	int dev_fd;
67 	unsigned long long offset;
68 	unsigned long long size;
69 	unsigned int sector_size;
70 	unsigned int sector_size_bits;
71 	unsigned long long num_sectors;
72 	unsigned int num_clusters;
73 	unsigned int cluster_size;
74 };
75 
76 struct exfat_user_input {
77 	char dev_name[255];
78 	bool writeable;
79 	unsigned int cluster_size;
80 	unsigned int sec_per_clu;
81 	unsigned int boundary_align;
82 	bool pack_bitmap;
83 	bool quick;
84 	__u16 volume_label[VOLUME_LABEL_MAX_LEN];
85 	int volume_label_len;
86 	unsigned int volume_serial;
87 };
88 
89 struct exfat;
90 struct exfat_inode;
91 
92 #ifdef WORDS_BIGENDIAN
93 typedef __u8	bitmap_t;
94 #else
95 typedef __u32	bitmap_t;
96 #endif
97 
98 #define BITS_PER	(sizeof(bitmap_t) * 8)
99 #define BIT_MASK(__c)	(1 << ((__c) % BITS_PER))
100 #define BIT_ENTRY(__c)	((__c) / BITS_PER)
101 
102 #define EXFAT_BITMAP_SIZE(__c_count)	\
103 	(DIV_ROUND_UP(__c_count, BITS_PER) * sizeof(bitmap_t))
104 
exfat_bitmap_get(char * bmap,clus_t c)105 static inline bool exfat_bitmap_get(char *bmap, clus_t c)
106 {
107 	clus_t cc = c - EXFAT_FIRST_CLUSTER;
108 
109 	return ((bitmap_t *)(bmap))[BIT_ENTRY(cc)] & BIT_MASK(cc);
110 }
111 
exfat_bitmap_set(char * bmap,clus_t c)112 static inline void exfat_bitmap_set(char *bmap, clus_t c)
113 {
114 	clus_t cc = c - EXFAT_FIRST_CLUSTER;
115 
116 	(((bitmap_t *)(bmap))[BIT_ENTRY(cc)] |= BIT_MASK(cc));
117 }
118 
exfat_bitmap_clear(char * bmap,clus_t c)119 static inline void exfat_bitmap_clear(char *bmap, clus_t c)
120 {
121 	clus_t cc = c - EXFAT_FIRST_CLUSTER;
122 	(((bitmap_t *)(bmap))[BIT_ENTRY(cc)] &= ~BIT_MASK(cc));
123 }
124 
125 void exfat_bitmap_set_range(struct exfat *exfat, char *bitmap,
126 			    clus_t start_clus, clus_t count);
127 int exfat_bitmap_find_zero(struct exfat *exfat, char *bmap,
128 			   clus_t start_clu, clus_t *next);
129 int exfat_bitmap_find_one(struct exfat *exfat, char *bmap,
130 			  clus_t start_clu, clus_t *next);
131 
132 void show_version(void);
133 
134 wchar_t exfat_bad_char(wchar_t w);
135 void boot_calc_checksum(unsigned char *sector, unsigned short size,
136 		bool is_boot_sec, __le32 *checksum);
137 void init_user_input(struct exfat_user_input *ui);
138 int exfat_get_blk_dev_info(struct exfat_user_input *ui,
139 		struct exfat_blk_dev *bd);
140 ssize_t exfat_read(int fd, void *buf, size_t size, off_t offset);
141 ssize_t exfat_write(int fd, void *buf, size_t size, off_t offset);
142 
143 size_t exfat_utf16_len(const __le16 *str, size_t max_size);
144 ssize_t exfat_utf16_enc(const char *in_str, __u16 *out_str, size_t out_size);
145 ssize_t exfat_utf16_dec(const __u16 *in_str, size_t in_len,
146 			char *out_str, size_t out_size);
147 off_t exfat_get_root_entry_offset(struct exfat_blk_dev *bd);
148 int exfat_read_volume_label(struct exfat *exfat);
149 int exfat_set_volume_label(struct exfat *exfat, char *label_input);
150 int exfat_read_sector(struct exfat_blk_dev *bd, void *buf,
151 		unsigned int sec_off);
152 int exfat_write_sector(struct exfat_blk_dev *bd, void *buf,
153 		unsigned int sec_off);
154 int exfat_write_checksum_sector(struct exfat_blk_dev *bd,
155 		unsigned int checksum, bool is_backup);
156 char *exfat_conv_volume_label(struct exfat_dentry *vol_entry);
157 int exfat_show_volume_serial(int fd);
158 int exfat_set_volume_serial(struct exfat_blk_dev *bd,
159 		struct exfat_user_input *ui);
160 unsigned int exfat_clus_to_blk_dev_off(struct exfat_blk_dev *bd,
161 		unsigned int clu_off, unsigned int clu);
162 int exfat_get_next_clus(struct exfat *exfat, clus_t clus, clus_t *next);
163 int exfat_get_inode_next_clus(struct exfat *exfat, struct exfat_inode *node,
164 			      clus_t clus, clus_t *next);
165 int exfat_set_fat(struct exfat *exfat, clus_t clus, clus_t next_clus);
166 off_t exfat_s2o(struct exfat *exfat, off_t sect);
167 off_t exfat_c2o(struct exfat *exfat, unsigned int clus);
168 int exfat_o2c(struct exfat *exfat, off_t device_offset,
169 	      unsigned int *clu, unsigned int *offset);
170 bool exfat_heap_clus(struct exfat *exfat, clus_t clus);
171 int exfat_root_clus_count(struct exfat *exfat);
172 int read_boot_sect(struct exfat_blk_dev *bdev, struct pbr **bs);
173 
174 /*
175  * Exfat Print
176  */
177 
178 extern unsigned int print_level;
179 
180 #define EXFAT_ERROR	(1)
181 #define EXFAT_INFO	(2)
182 #define EXFAT_DEBUG	(3)
183 
184 #define exfat_msg(level, dir, fmt, ...)					\
185 	do {								\
186 		if (print_level >= level) {				\
187 			fprintf(dir, fmt, ##__VA_ARGS__);		\
188 		}							\
189 	} while (0)							\
190 
191 #define exfat_err(fmt, ...)	exfat_msg(EXFAT_ERROR, stderr,		\
192 					fmt, ##__VA_ARGS__)
193 #define exfat_info(fmt, ...)	exfat_msg(EXFAT_INFO, stdout,		\
194 					fmt, ##__VA_ARGS__)
195 #define exfat_debug(fmt, ...)	exfat_msg(EXFAT_DEBUG, stdout,		\
196 					"[%s:%4d] " fmt, __func__, 	\
197 					__LINE__, ##__VA_ARGS__)
198 
199 #endif /* !_LIBEXFAT_H */
200