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