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