1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * Copyright (C) 2019 Namjae Jeon <linkinjeon@kernel.org>
16 #define MB (1024*1024)
17 #define GB (1024UL*1024UL*1024UL)
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))
23 #define MIN(a, b) ((a) < (b) ? (a) : (b))
24 #define MAX(a, b) ((a) > (b) ? (a) : (b))
26 #define DIV_ROUND_UP(__i, __d) (((__i) + (__d) - 1) / (__d))
28 #define EXFAT_MIN_NUM_SEC_VOL (2048)
29 #define EXFAT_MAX_NUM_SEC_VOL ((2 << 64) - 1)
31 #define EXFAT_MAX_NUM_CLUSTER (0xFFFFFFF5)
33 #define DEFAULT_BOUNDARY_ALIGNMENT (1024*1024)
35 #define DEFAULT_SECTOR_SIZE (512)
37 #define VOLUME_LABEL_BUFFER_SIZE (VOLUME_LABEL_MAX_LEN*MB_LEN_MAX+1)
39 /* Upcase table macro */
40 #define EXFAT_UPCASE_TABLE_CHARS (0x10000)
41 #define EXFAT_UPCASE_TABLE_SIZE (5836)
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 #define EXFAT_GET_VOLUME_GUID 0x05
49 #define EXFAT_SET_VOLUME_GUID 0x06
51 #define EXFAT_MAX_SECTOR_SIZE 4096
53 #define EXFAT_CLUSTER_SIZE(pbr) (1 << ((pbr)->bsx.sect_size_bits + \
54 (pbr)->bsx.sect_per_clus_bits))
55 #define EXFAT_SECTOR_SIZE(pbr) (1 << (pbr)->bsx.sect_size_bits)
57 #define EXFAT_MAX_HASH_COUNT (UINT16_MAX + 1)
69 struct exfat_blk_dev {
71 unsigned long long offset;
72 unsigned long long size;
73 unsigned int sector_size;
74 unsigned int sector_size_bits;
75 unsigned long long num_sectors;
76 unsigned int num_clusters;
77 unsigned int cluster_size;
80 struct exfat_user_input {
83 unsigned int sector_size;
84 unsigned int cluster_size;
85 unsigned int sec_per_clu;
86 unsigned int boundary_align;
89 __u16 volume_label[VOLUME_LABEL_MAX_LEN];
91 unsigned int volume_serial;
98 #ifdef WORDS_BIGENDIAN
99 typedef __u8 bitmap_t;
101 typedef __u32 bitmap_t;
104 #define BITS_PER (sizeof(bitmap_t) * 8)
105 #define BIT_MASK(__c) (1 << ((__c) % BITS_PER))
106 #define BIT_ENTRY(__c) ((__c) / BITS_PER)
108 #define EXFAT_BITMAP_SIZE(__c_count) \
109 (DIV_ROUND_UP(__c_count, BITS_PER) * sizeof(bitmap_t))
111 #define BITMAP_GET(bmap, bit) \
112 (((bitmap_t *)(bmap))[BIT_ENTRY(bit)] & BIT_MASK(bit))
114 #define BITMAP_SET(bmap, bit) \
115 (((bitmap_t *)(bmap))[BIT_ENTRY(bit)] |= BIT_MASK(bit))
117 #define BITMAP_CLEAR(bmap, bit) \
118 (((bitmap_t *)(bmap))[BIT_ENTRY(bit)] &= ~BIT_MASK(bit))
120 static inline bool exfat_bitmap_get(char *bmap, clus_t c)
122 clus_t cc = c - EXFAT_FIRST_CLUSTER;
124 return BITMAP_GET(bmap, cc);
127 static inline void exfat_bitmap_set(char *bmap, clus_t c)
129 clus_t cc = c - EXFAT_FIRST_CLUSTER;
131 BITMAP_SET(bmap, cc);
134 static inline void exfat_bitmap_clear(char *bmap, clus_t c)
136 clus_t cc = c - EXFAT_FIRST_CLUSTER;
137 (((bitmap_t *)(bmap))[BIT_ENTRY(cc)] &= ~BIT_MASK(cc));
140 void exfat_bitmap_set_range(struct exfat *exfat, char *bitmap,
141 clus_t start_clus, clus_t count);
142 int exfat_bitmap_find_zero(struct exfat *exfat, char *bmap,
143 clus_t start_clu, clus_t *next);
144 int exfat_bitmap_find_one(struct exfat *exfat, char *bmap,
145 clus_t start_clu, clus_t *next);
147 void show_version(void);
149 wchar_t exfat_bad_char(wchar_t w);
150 void boot_calc_checksum(unsigned char *sector, unsigned short size,
151 bool is_boot_sec, __le32 *checksum);
152 void init_user_input(struct exfat_user_input *ui);
153 int exfat_get_blk_dev_info(struct exfat_user_input *ui,
154 struct exfat_blk_dev *bd);
155 ssize_t exfat_read(int fd, void *buf, size_t size, off_t offset);
156 ssize_t exfat_write(int fd, void *buf, size_t size, off_t offset);
157 ssize_t exfat_write_zero(int fd, size_t size, off_t offset);
159 size_t exfat_utf16_len(const __le16 *str, size_t max_size);
160 ssize_t exfat_utf16_enc(const char *in_str, __u16 *out_str, size_t out_size);
161 ssize_t exfat_utf16_dec(const __u16 *in_str, size_t in_len,
162 char *out_str, size_t out_size);
163 off_t exfat_get_root_entry_offset(struct exfat_blk_dev *bd);
164 int exfat_read_volume_label(struct exfat *exfat);
165 int exfat_set_volume_label(struct exfat *exfat, char *label_input);
166 int __exfat_set_volume_guid(struct exfat_dentry *dentry, const char *guid);
167 int exfat_read_volume_guid(struct exfat *exfat);
168 int exfat_set_volume_guid(struct exfat *exfat, const char *guid);
169 int exfat_read_sector(struct exfat_blk_dev *bd, void *buf,
170 unsigned int sec_off);
171 int exfat_write_sector(struct exfat_blk_dev *bd, void *buf,
172 unsigned int sec_off);
173 int exfat_write_checksum_sector(struct exfat_blk_dev *bd,
174 unsigned int checksum, bool is_backup);
175 char *exfat_conv_volume_label(struct exfat_dentry *vol_entry);
176 int exfat_show_volume_serial(int fd);
177 int exfat_set_volume_serial(struct exfat_blk_dev *bd,
178 struct exfat_user_input *ui);
179 unsigned int exfat_clus_to_blk_dev_off(struct exfat_blk_dev *bd,
180 unsigned int clu_off, unsigned int clu);
181 int exfat_get_next_clus(struct exfat *exfat, clus_t clus, clus_t *next);
182 int exfat_get_inode_next_clus(struct exfat *exfat, struct exfat_inode *node,
183 clus_t clus, clus_t *next);
184 int exfat_set_fat(struct exfat *exfat, clus_t clus, clus_t next_clus);
185 off_t exfat_s2o(struct exfat *exfat, off_t sect);
186 off_t exfat_c2o(struct exfat *exfat, unsigned int clus);
187 int exfat_o2c(struct exfat *exfat, off_t device_offset,
188 unsigned int *clu, unsigned int *offset);
189 bool exfat_heap_clus(struct exfat *exfat, clus_t clus);
190 int exfat_root_clus_count(struct exfat *exfat);
191 int read_boot_sect(struct exfat_blk_dev *bdev, struct pbr **bs);
192 int exfat_parse_ulong(const char *s, unsigned long *out);
198 extern unsigned int print_level;
200 #define EXFAT_ERROR (1)
201 #define EXFAT_INFO (2)
202 #define EXFAT_DEBUG (3)
204 #define exfat_msg(level, dir, fmt, ...) \
206 if (print_level >= level) { \
207 fprintf(dir, fmt, ##__VA_ARGS__); \
211 #define exfat_err(fmt, ...) exfat_msg(EXFAT_ERROR, stderr, \
213 #define exfat_info(fmt, ...) exfat_msg(EXFAT_INFO, stdout, \
215 #define exfat_debug(fmt, ...) exfat_msg(EXFAT_DEBUG, stdout, \
216 "[%s:%4d] " fmt, __func__, \
217 __LINE__, ##__VA_ARGS__)
219 #endif /* !_LIBEXFAT_H */