blob: 4973c9edc26ec2630cb90dfacae90c24a41b8b06 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
#ifndef _EXFAT_H
#define _EXFAT_H
#include <linux/types.h>
#include <linux/buffer_head.h>
#ifdef CONFIG_EXFAT_KERNEL_DEBUG
/* For Debugging Purpose */
/* IOCTL code 'f' used by
* - file systems typically #0~0x1F
* - embedded terminal devices #128~
* - exts for debugging purpose #99
* number 100 and 101 is available now but has possible conflicts
*/
#define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long)
#define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long)
#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01
#define EXFAT_DEBUGFLAGS_ERROR_RW 0x02
#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
#ifdef CONFIG_EXFAT_DEBUG_MSG
#define DEBUG 1
#else
#undef DEBUG
#endif
#define DENTRY_SIZE 32 /* dir entry size */
#define DENTRY_SIZE_BITS 5
/* PBR entries */
#define PBR_SIGNATURE 0xAA55
#define EXT_SIGNATURE 0xAA550000
#define VOL_LABEL "NO NAME " /* size should be 11 */
#define OEM_NAME "MSWIN4.1" /* size should be 8 */
#define STR_FAT12 "FAT12 " /* size should be 8 */
#define STR_FAT16 "FAT16 " /* size should be 8 */
#define STR_FAT32 "FAT32 " /* size should be 8 */
#define STR_EXFAT "EXFAT " /* size should be 8 */
#define VOL_CLEAN 0x0000
#define VOL_DIRTY 0x0002
/* max number of clusters */
#define FAT12_THRESHOLD 4087 /* 2^12 - 1 + 2 (clu 0 & 1) */
#define FAT16_THRESHOLD 65527 /* 2^16 - 1 + 2 */
#define FAT32_THRESHOLD 268435457 /* 2^28 - 1 + 2 */
#define EXFAT_THRESHOLD 268435457 /* 2^28 - 1 + 2 */
/* file types */
#define TYPE_UNUSED 0x0000
#define TYPE_DELETED 0x0001
#define TYPE_INVALID 0x0002
#define TYPE_CRITICAL_PRI 0x0100
#define TYPE_BITMAP 0x0101
#define TYPE_UPCASE 0x0102
#define TYPE_VOLUME 0x0103
#define TYPE_DIR 0x0104
#define TYPE_FILE 0x011F
#define TYPE_SYMLINK 0x015F
#define TYPE_CRITICAL_SEC 0x0200
#define TYPE_STREAM 0x0201
#define TYPE_EXTEND 0x0202
#define TYPE_ACL 0x0203
#define TYPE_BENIGN_PRI 0x0400
#define TYPE_GUID 0x0401
#define TYPE_PADDING 0x0402
#define TYPE_ACLTAB 0x0403
#define TYPE_BENIGN_SEC 0x0800
#define TYPE_ALL 0x0FFF
/* time modes */
#define TM_CREATE 0
#define TM_MODIFY 1
#define TM_ACCESS 2
/* checksum types */
#define CS_DIR_ENTRY 0
#define CS_PBR_SECTOR 1
#define CS_DEFAULT 2
#define CLUSTER_16(x) ((u16)(x))
#define CLUSTER_32(x) ((u32)(x))
#define START_SECTOR(x) \
((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) + \
p_fs->data_start_sector)
#define IS_LAST_SECTOR_IN_CLUSTER(sec) \
((((sec) - p_fs->data_start_sector + 1) & \
((1 << p_fs->sectors_per_clu_bits) - 1)) == 0)
#define GET_CLUSTER_FROM_SECTOR(sec) \
((u32)((((sec) - p_fs->data_start_sector) >> \
p_fs->sectors_per_clu_bits) + 2))
#define GET16(p_src) \
(((u16)(p_src)[0]) | (((u16)(p_src)[1]) << 8))
#define GET32(p_src) \
(((u32)(p_src)[0]) | (((u32)(p_src)[1]) << 8) | \
(((u32)(p_src)[2]) << 16) | (((u32)(p_src)[3]) << 24))
#define GET64(p_src) \
(((u64)(p_src)[0]) | (((u64)(p_src)[1]) << 8) | \
(((u64)(p_src)[2]) << 16) | (((u64)(p_src)[3]) << 24) | \
(((u64)(p_src)[4]) << 32) | (((u64)(p_src)[5]) << 40) | \
(((u64)(p_src)[6]) << 48) | (((u64)(p_src)[7]) << 56))
#define SET16(p_dst, src) \
do { \
(p_dst)[0] = (u8)(src); \
(p_dst)[1] = (u8)(((u16)(src)) >> 8); \
} while (0)
#define SET32(p_dst, src) \
do { \
(p_dst)[0] = (u8)(src); \
(p_dst)[1] = (u8)(((u32)(src)) >> 8); \
(p_dst)[2] = (u8)(((u32)(src)) >> 16); \
(p_dst)[3] = (u8)(((u32)(src)) >> 24); \
} while (0)
#define SET64(p_dst, src) \
do { \
(p_dst)[0] = (u8)(src); \
(p_dst)[1] = (u8)(((u64)(src)) >> 8); \
(p_dst)[2] = (u8)(((u64)(src)) >> 16); \
(p_dst)[3] = (u8)(((u64)(src)) >> 24); \
(p_dst)[4] = (u8)(((u64)(src)) >> 32); \
(p_dst)[5] = (u8)(((u64)(src)) >> 40); \
(p_dst)[6] = (u8)(((u64)(src)) >> 48); \
(p_dst)[7] = (u8)(((u64)(src)) >> 56); \
} while (0)
#ifdef __LITTLE_ENDIAN
#define GET16_A(p_src) (*((u16 *)(p_src)))
#define GET32_A(p_src) (*((u32 *)(p_src)))
#define GET64_A(p_src) (*((u64 *)(p_src)))
#define SET16_A(p_dst, src) (*((u16 *)(p_dst)) = (u16)(src))
#define SET32_A(p_dst, src) (*((u32 *)(p_dst)) = (u32)(src))
#define SET64_A(p_dst, src) (*((u64 *)(p_dst)) = (u64)(src))
#else /* BIG_ENDIAN */
#define GET16_A(p_src) GET16(p_src)
#define GET32_A(p_src) GET32(p_src)
#define GET64_A(p_src) GET64(p_src)
#define SET16_A(p_dst, src) SET16(p_dst, src)
#define SET32_A(p_dst, src) SET32(p_dst, src)
#define SET64_A(p_dst, src) SET64(p_dst, src)
#endif
/* cache size (in number of sectors) */
/* (should be an exponential value of 2) */
#define FAT_CACHE_SIZE 128
#define FAT_CACHE_HASH_SIZE 64
#define BUF_CACHE_SIZE 256
#define BUF_CACHE_HASH_SIZE 64
/* Upcase table macro */
#define HIGH_INDEX_BIT (8)
#define HIGH_INDEX_MASK (0xFF00)
#define LOW_INDEX_BIT (16 - HIGH_INDEX_BIT)
#define UTBL_ROW_COUNT BIT(LOW_INDEX_BIT)
#define UTBL_COL_COUNT BIT(HIGH_INDEX_BIT)
static inline u16 get_col_index(u16 i)
{
return i >> LOW_INDEX_BIT;
}
static inline u16 get_row_index(u16 i)
{
return i & ~HIGH_INDEX_MASK;
}
#define EXFAT_SUPER_MAGIC (0x2011BAB0L)
#define EXFAT_ROOT_INO 1
/* FAT types */
#define FAT12 0x01 /* FAT12 */
#define FAT16 0x0E /* Win95 FAT16 (LBA) */
#define FAT32 0x0C /* Win95 FAT32 (LBA) */
#define EXFAT 0x07 /* exFAT */
/* file name lengths */
#define MAX_CHARSET_SIZE 3 /* max size of multi-byte character */
#define MAX_PATH_DEPTH 15 /* max depth of path name */
#define MAX_NAME_LENGTH 256 /* max len of filename including NULL */
#define MAX_PATH_LENGTH 260 /* max len of pathname including NULL */
#define DOS_NAME_LENGTH 11 /* DOS filename length excluding NULL */
#define DOS_PATH_LENGTH 80 /* DOS pathname length excluding NULL */
/* file attributes */
#define ATTR_NORMAL 0x0000
#define ATTR_READONLY 0x0001
#define ATTR_HIDDEN 0x0002
#define ATTR_SYSTEM 0x0004
#define ATTR_VOLUME 0x0008
#define ATTR_SUBDIR 0x0010
#define ATTR_ARCHIVE 0x0020
#define ATTR_SYMLINK 0x0040
#define ATTR_EXTEND 0x000F
#define ATTR_RWMASK 0x007E
/* file creation modes */
#define FM_REGULAR 0x00
#define FM_SYMLINK 0x40
/* return values */
#define FFS_SUCCESS 0
#define FFS_MEDIAERR 1
#define FFS_FORMATERR 2
#define FFS_MOUNTED 3
#define FFS_NOTMOUNTED 4
#define FFS_ALIGNMENTERR 5
#define FFS_SEMAPHOREERR 6
#define FFS_INVALIDPATH 7
#define FFS_INVALIDFID 8
#define FFS_NOTFOUND 9
#define FFS_FILEEXIST 10
#define FFS_PERMISSIONERR 11
#define FFS_NOTOPENED 12
#define FFS_MAXOPENED 13
#define FFS_FULL 14
#define FFS_EOF 15
#define FFS_DIRBUSY 16
#define FFS_MEMORYERR 17
#define FFS_NAMETOOLONG 18
#define FFS_ERROR 19
#define NUM_UPCASE 2918
#define DOS_CUR_DIR_NAME ". "
#define DOS_PAR_DIR_NAME ".. "
#ifdef __LITTLE_ENDIAN
#define UNI_CUR_DIR_NAME ".\0"
#define UNI_PAR_DIR_NAME ".\0.\0"
#else
#define UNI_CUR_DIR_NAME "\0."
#define UNI_PAR_DIR_NAME "\0.\0."
#endif
struct date_time_t {
u16 Year;
u16 Month;
u16 Day;
u16 Hour;
u16 Minute;
u16 Second;
u16 MilliSecond;
};
struct part_info_t {
u32 Offset; /* start sector number of the partition */
u32 Size; /* in sectors */
};
struct dev_info_t {
u32 SecSize; /* sector size in bytes */
u32 DevSize; /* block device size in sectors */
};
struct vol_info_t {
u32 FatType;
u32 ClusterSize;
u32 NumClusters;
u32 FreeClusters;
u32 UsedClusters;
};
/* directory structure */
struct chain_t {
u32 dir;
s32 size;
u8 flags;
};
struct file_id_t {
struct chain_t dir;
s32 entry;
u32 type;
u32 attr;
u32 start_clu;
u64 size;
u8 flags;
s64 rwoffset;
s32 hint_last_off;
u32 hint_last_clu;
};
struct dir_entry_t {
char Name[MAX_NAME_LENGTH * MAX_CHARSET_SIZE];
/* used only for FAT12/16/32, not used for exFAT */
char ShortName[DOS_NAME_LENGTH + 2];
u32 Attr;
u64 Size;
u32 NumSubdirs;
struct date_time_t CreateTimestamp;
struct date_time_t ModifyTimestamp;
struct date_time_t AccessTimestamp;
};
struct timestamp_t {
u16 sec; /* 0 ~ 59 */
u16 min; /* 0 ~ 59 */
u16 hour; /* 0 ~ 23 */
u16 day; /* 1 ~ 31 */
u16 mon; /* 1 ~ 12 */
u16 year; /* 0 ~ 127 (since 1980) */
};
/* MS_DOS FAT partition boot record (512 bytes) */
struct pbr_sector_t {
u8 jmp_boot[3];
u8 oem_name[8];
u8 bpb[109];
u8 boot_code[390];
u8 signature[2];
};
/* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */
struct bpb16_t {
u8 sector_size[2];
u8 sectors_per_clu;
u8 num_reserved[2];
u8 num_fats;
u8 num_root_entries[2];
u8 num_sectors[2];
u8 media_type;
u8 num_fat_sectors[2];
u8 sectors_in_track[2];
u8 num_heads[2];
u8 num_hid_sectors[4];
u8 num_huge_sectors[4];
u8 phy_drv_no;
u8 reserved;
u8 ext_signature;
u8 vol_serial[4];
u8 vol_label[11];
u8 vol_type[8];
};
/* MS-DOS FAT32 BIOS parameter block (79 bytes) */
struct bpb32_t {
u8 sector_size[2];
u8 sectors_per_clu;
u8 num_reserved[2];
u8 num_fats;
u8 num_root_entries[2];
u8 num_sectors[2];
u8 media_type;
u8 num_fat_sectors[2];
u8 sectors_in_track[2];
u8 num_heads[2];
u8 num_hid_sectors[4];
u8 num_huge_sectors[4];
u8 num_fat32_sectors[4];
u8 ext_flags[2];
u8 fs_version[2];
u8 root_cluster[4];
u8 fsinfo_sector[2];
u8 backup_sector[2];
u8 reserved[12];
u8 phy_drv_no;
u8 ext_reserved;
u8 ext_signature;
u8 vol_serial[4];
u8 vol_label[11];
u8 vol_type[8];
};
/* MS-DOS EXFAT BIOS parameter block (109 bytes) */
struct bpbex_t {
u8 reserved1[53];
u8 vol_offset[8];
u8 vol_length[8];
u8 fat_offset[4];
u8 fat_length[4];
u8 clu_offset[4];
u8 clu_count[4];
u8 root_cluster[4];
u8 vol_serial[4];
u8 fs_version[2];
u8 vol_flags[2];
u8 sector_size_bits;
u8 sectors_per_clu_bits;
u8 num_fats;
u8 phy_drv_no;
u8 perc_in_use;
u8 reserved2[7];
};
/* MS-DOS FAT file system information sector (512 bytes) */
struct fsi_sector_t {
u8 signature1[4];
u8 reserved1[480];
u8 signature2[4];
u8 free_cluster[4];
u8 next_cluster[4];
u8 reserved2[14];
u8 signature3[2];
};
/* MS-DOS FAT directory entry (32 bytes) */
struct dentry_t {
u8 dummy[32];
};
struct dos_dentry_t {
u8 name[DOS_NAME_LENGTH];
u8 attr;
u8 lcase;
u8 create_time_ms;
u8 create_time[2];
u8 create_date[2];
u8 access_date[2];
u8 start_clu_hi[2];
u8 modify_time[2];
u8 modify_date[2];
u8 start_clu_lo[2];
u8 size[4];
};
/* MS-DOS FAT extended directory entry (32 bytes) */
struct ext_dentry_t {
u8 order;
u8 unicode_0_4[10];
u8 attr;
u8 sysid;
u8 checksum;
u8 unicode_5_10[12];
u8 start_clu[2];
u8 unicode_11_12[4];
};
/* MS-DOS EXFAT file directory entry (32 bytes) */
struct file_dentry_t {
u8 type;
u8 num_ext;
u8 checksum[2];
u8 attr[2];
u8 reserved1[2];
u8 create_time[2];
u8 create_date[2];
u8 modify_time[2];
u8 modify_date[2];
u8 access_time[2];
u8 access_date[2];
u8 create_time_ms;
u8 modify_time_ms;
u8 access_time_ms;
u8 reserved2[9];
};
/* MS-DOS EXFAT stream extension directory entry (32 bytes) */
struct strm_dentry_t {
u8 type;
u8 flags;
u8 reserved1;
u8 name_len;
u8 name_hash[2];
u8 reserved2[2];
u8 valid_size[8];
u8 reserved3[4];
u8 start_clu[4];
u8 size[8];
};
/* MS-DOS EXFAT file name directory entry (32 bytes) */
struct name_dentry_t {
u8 type;
u8 flags;
u8 unicode_0_14[30];
};
/* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */
struct bmap_dentry_t {
u8 type;
u8 flags;
u8 reserved[18];
u8 start_clu[4];
u8 size[8];
};
/* MS-DOS EXFAT up-case table directory entry (32 bytes) */
struct case_dentry_t {
u8 type;
u8 reserved1[3];
u8 checksum[4];
u8 reserved2[12];
u8 start_clu[4];
u8 size[8];
};
/* MS-DOS EXFAT volume label directory entry (32 bytes) */
struct volm_dentry_t {
u8 type;
u8 label_len;
u8 unicode_0_10[22];
u8 reserved[8];
};
/* unused entry hint information */
struct uentry_t {
u32 dir;
s32 entry;
struct chain_t clu;
};
/* DOS name structure */
struct dos_name_t {
u8 name[DOS_NAME_LENGTH];
u8 name_case;
};
/* unicode name structure */
struct uni_name_t {
u16 name[MAX_NAME_LENGTH];
u16 name_hash;
u8 name_len;
};
struct buf_cache_t {
struct buf_cache_t *next;
struct buf_cache_t *prev;
struct buf_cache_t *hash_next;
struct buf_cache_t *hash_prev;
s32 drv;
sector_t sec;
u32 flag;
struct buffer_head *buf_bh;
};
struct fs_func {
s32 (*alloc_cluster)(struct super_block *sb, s32 num_alloc,
struct chain_t *p_chain);
void (*free_cluster)(struct super_block *sb, struct chain_t *p_chain,
s32 do_relse);
s32 (*count_used_clusters)(struct super_block *sb);
s32 (*init_dir_entry)(struct super_block *sb, struct chain_t *p_dir,
s32 entry, u32 type, u32 start_clu, u64 size);
s32 (*init_ext_entry)(struct super_block *sb, struct chain_t *p_dir,
s32 entry, s32 num_entries,
struct uni_name_t *p_uniname,
struct dos_name_t *p_dosname);
s32 (*find_dir_entry)(struct super_block *sb, struct chain_t *p_dir,
struct uni_name_t *p_uniname, s32 num_entries,
struct dos_name_t *p_dosname, u32 type);
void (*delete_dir_entry)(struct super_block *sb,
struct chain_t *p_dir, s32 entry,
s32 offset, s32 num_entries);
void (*get_uni_name_from_ext_entry)(struct super_block *sb,
struct chain_t *p_dir, s32 entry,
u16 *uniname);
s32 (*count_ext_entries)(struct super_block *sb,
struct chain_t *p_dir, s32 entry,
struct dentry_t *p_entry);
s32 (*calc_num_entries)(struct uni_name_t *p_uniname);
u32 (*get_entry_type)(struct dentry_t *p_entry);
void (*set_entry_type)(struct dentry_t *p_entry, u32 type);
u32 (*get_entry_attr)(struct dentry_t *p_entry);
void (*set_entry_attr)(struct dentry_t *p_entry, u32 attr);
u8 (*get_entry_flag)(struct dentry_t *p_entry);
void (*set_entry_flag)(struct dentry_t *p_entry, u8 flag);
u32 (*get_entry_clu0)(struct dentry_t *p_entry);
void (*set_entry_clu0)(struct dentry_t *p_entry, u32 clu0);
u64 (*get_entry_size)(struct dentry_t *p_entry);
void (*set_entry_size)(struct dentry_t *p_entry, u64 size);
void (*get_entry_time)(struct dentry_t *p_entry,
struct timestamp_t *tp, u8 mode);
void (*set_entry_time)(struct dentry_t *p_entry,
struct timestamp_t *tp, u8 mode);
};
struct fs_info_t {
u32 drv; /* drive ID */
u32 vol_type; /* volume FAT type */
u32 vol_id; /* volume serial number */
u64 num_sectors; /* num of sectors in volume */
u32 num_clusters; /* num of clusters in volume */
u32 cluster_size; /* cluster size in bytes */
u32 cluster_size_bits;
u32 sectors_per_clu; /* cluster size in sectors */
u32 sectors_per_clu_bits;
u32 PBR_sector; /* PBR sector */
u32 FAT1_start_sector; /* FAT1 start sector */
u32 FAT2_start_sector; /* FAT2 start sector */
u32 root_start_sector; /* root dir start sector */
u32 data_start_sector; /* data area start sector */
u32 num_FAT_sectors; /* num of FAT sectors */
u32 root_dir; /* root dir cluster */
u32 dentries_in_root; /* num of dentries in root dir */
u32 dentries_per_clu; /* num of dentries per cluster */
u32 vol_flag; /* volume dirty flag */
struct buffer_head *pbr_bh; /* PBR sector */
u32 map_clu; /* allocation bitmap start cluster */
u32 map_sectors; /* num of allocation bitmap sectors */
struct buffer_head **vol_amap; /* allocation bitmap */
u16 **vol_utbl; /* upcase table */
u32 clu_srch_ptr; /* cluster search pointer */
u32 used_clusters; /* number of used clusters */
struct uentry_t hint_uentry; /* unused entry hint information */
u32 dev_ejected; /* block device operation error flag */
struct fs_func *fs_func;
struct semaphore v_sem;
/* FAT cache */
struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE];
struct buf_cache_t FAT_cache_lru_list;
struct buf_cache_t FAT_cache_hash_list[FAT_CACHE_HASH_SIZE];
/* buf cache */
struct buf_cache_t buf_cache_array[BUF_CACHE_SIZE];
struct buf_cache_t buf_cache_lru_list;
struct buf_cache_t buf_cache_hash_list[BUF_CACHE_HASH_SIZE];
};
#define ES_2_ENTRIES 2
#define ES_3_ENTRIES 3
#define ES_ALL_ENTRIES 0
struct entry_set_cache_t {
/* sector number that contains file_entry */
sector_t sector;
/* byte offset in the sector */
s32 offset;
/*
* flag in stream entry.
* 01 for cluster chain,
* 03 for contig. clusteres.
*/
s32 alloc_flag;
u32 num_entries;
/* __buf should be the last member */
void *__buf;
};
#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */
#define EXFAT_ERRORS_PANIC 2 /* panic on error */
#define EXFAT_ERRORS_RO 3 /* remount r/o on error */
/* ioctl command */
#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32)
struct exfat_mount_options {
kuid_t fs_uid;
kgid_t fs_gid;
unsigned short fs_fmask;
unsigned short fs_dmask;
/* permission for setting the [am]time */
unsigned short allow_utime;
/* codepage for shortname conversions */
unsigned short codepage;
/* charset for filename input/display */
char *iocharset;
unsigned char casesensitive;
/* on error: continue, panic, remount-ro */
unsigned char errors;
#ifdef CONFIG_EXFAT_DISCARD
/* flag on if -o dicard specified and device support discard() */
unsigned char discard;
#endif /* CONFIG_EXFAT_DISCARD */
};
#define EXFAT_HASH_BITS 8
#define EXFAT_HASH_SIZE BIT(EXFAT_HASH_BITS)
/*
* EXFAT file system in-core superblock data
*/
struct bd_info_t {
s32 sector_size; /* in bytes */
s32 sector_size_bits;
s32 sector_size_mask;
/* total number of sectors in this block device */
s32 num_sectors;
/* opened or not */
bool opened;
};
struct exfat_sb_info {
struct fs_info_t fs_info;
struct bd_info_t bd_info;
struct exfat_mount_options options;
int s_dirt;
struct mutex s_lock;
struct nls_table *nls_disk; /* Codepage used on disk */
struct nls_table *nls_io; /* Charset used for input and display */
struct inode *fat_inode;
spinlock_t inode_hash_lock;
struct hlist_head inode_hashtable[EXFAT_HASH_SIZE];
#ifdef CONFIG_EXFAT_KERNEL_DEBUG
long debug_flags;
#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
};
/*
* EXFAT file system inode data in memory
*/
struct exfat_inode_info {
struct file_id_t fid;
char *target;
/* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */
loff_t mmu_private; /* physically allocated size */
loff_t i_pos; /* on-disk position of directory entry or 0 */
struct hlist_node i_hash_fat; /* hash by i_location */
struct rw_semaphore truncate_lock;
struct inode vfs_inode;
struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */
};
#define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info))
static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
{
return container_of(inode, struct exfat_inode_info, vfs_inode);
}
/* NLS management function */
u16 nls_upper(struct super_block *sb, u16 a);
int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b);
int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b);
void nls_uniname_to_dosname(struct super_block *sb,
struct dos_name_t *p_dosname,
struct uni_name_t *p_uniname, bool *p_lossy);
void nls_dosname_to_uniname(struct super_block *sb,
struct uni_name_t *p_uniname,
struct dos_name_t *p_dosname);
void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
struct uni_name_t *p_uniname);
void nls_cstring_to_uniname(struct super_block *sb,
struct uni_name_t *p_uniname, u8 *p_cstring,
bool *p_lossy);
/* buffer cache management */
void buf_init(struct super_block *sb);
void buf_shutdown(struct super_block *sb);
int FAT_read(struct super_block *sb, u32 loc, u32 *content);
s32 FAT_write(struct super_block *sb, u32 loc, u32 content);
u8 *FAT_getblk(struct super_block *sb, sector_t sec);
void FAT_modify(struct super_block *sb, sector_t sec);
void FAT_release_all(struct super_block *sb);
void FAT_sync(struct super_block *sb);
u8 *buf_getblk(struct super_block *sb, sector_t sec);
void buf_modify(struct super_block *sb, sector_t sec);
void buf_lock(struct super_block *sb, sector_t sec);
void buf_unlock(struct super_block *sb, sector_t sec);
void buf_release(struct super_block *sb, sector_t sec);
void buf_release_all(struct super_block *sb);
void buf_sync(struct super_block *sb);
/* fs management functions */
void fs_set_vol_flags(struct super_block *sb, u32 new_flag);
void fs_error(struct super_block *sb);
/* cluster management functions */
s32 clear_cluster(struct super_block *sb, u32 clu);
s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc,
struct chain_t *p_chain);
s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
struct chain_t *p_chain);
void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
s32 do_relse);
void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
s32 do_relse);
u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain);
s32 count_num_clusters(struct super_block *sb, struct chain_t *dir);
s32 fat_count_used_clusters(struct super_block *sb);
s32 exfat_count_used_clusters(struct super_block *sb);
void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
/* allocation bitmap management functions */
s32 load_alloc_bitmap(struct super_block *sb);
void free_alloc_bitmap(struct super_block *sb);
s32 set_alloc_bitmap(struct super_block *sb, u32 clu);
s32 clr_alloc_bitmap(struct super_block *sb, u32 clu);
u32 test_alloc_bitmap(struct super_block *sb, u32 clu);
void sync_alloc_bitmap(struct super_block *sb);
/* upcase table management functions */
s32 load_upcase_table(struct super_block *sb);
void free_upcase_table(struct super_block *sb);
/* dir entry management functions */
u32 fat_get_entry_type(struct dentry_t *p_entry);
u32 exfat_get_entry_type(struct dentry_t *p_entry);
void fat_set_entry_type(struct dentry_t *p_entry, u32 type);
void exfat_set_entry_type(struct dentry_t *p_entry, u32 type);
u32 fat_get_entry_attr(struct dentry_t *p_entry);
u32 exfat_get_entry_attr(struct dentry_t *p_entry);
void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
u8 fat_get_entry_flag(struct dentry_t *p_entry);
u8 exfat_get_entry_flag(struct dentry_t *p_entry);
void fat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
u32 fat_get_entry_clu0(struct dentry_t *p_entry);
u32 exfat_get_entry_clu0(struct dentry_t *p_entry);
void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
u64 fat_get_entry_size(struct dentry_t *p_entry);
u64 exfat_get_entry_size(struct dentry_t *p_entry);
void fat_set_entry_size(struct dentry_t *p_entry, u64 size);
void exfat_set_entry_size(struct dentry_t *p_entry, u64 size);
struct timestamp_t *tm_current(struct timestamp_t *tm);
void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
u8 mode);
void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
u8 mode);
void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
u8 mode);
void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
u8 mode);
s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
u32 type, u32 start_clu, u64 size);
s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
s32 entry, u32 type, u32 start_clu, u64 size);
s32 fat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
s32 entry, s32 num_entries,
struct uni_name_t *p_uniname,
struct dos_name_t *p_dosname);
s32 exfat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
s32 entry, s32 num_entries,
struct uni_name_t *p_uniname,
struct dos_name_t *p_dosname);
void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu);
void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum,
u16 *uniname);
void init_file_entry(struct file_dentry_t *ep, u32 type);
void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
u64 size);
void init_name_entry(struct name_dentry_t *ep, u16 *uniname);
void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
s32 entry, s32 order, s32 num_entries);
void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
s32 entry, s32 order, s32 num_entries);
s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
sector_t *sector, s32 *offset);
struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
s32 offset);
struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
s32 entry, sector_t *sector);
struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
struct chain_t *p_dir, s32 entry,
u32 type,
struct dentry_t **file_ep);
void release_entry_set(struct entry_set_cache_t *es);
s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es);
s32 write_partial_entries_in_entry_set(struct super_block *sb,
struct entry_set_cache_t *es,
struct dentry_t *ep, u32 count);
s32 search_deleted_or_unused_entry(struct super_block *sb,
struct chain_t *p_dir, s32 num_entries);
s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir,
s32 num_entries);
s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
struct uni_name_t *p_uniname, s32 num_entries,
struct dos_name_t *p_dosname, u32 type);
s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
struct uni_name_t *p_uniname, s32 num_entries,
struct dos_name_t *p_dosname, u32 type);
s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
s32 entry, struct dentry_t *p_entry);
s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
s32 entry, struct dentry_t *p_entry);
s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
u32 type);
void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
s32 entry);
void update_dir_checksum_with_entry_set(struct super_block *sb,
struct entry_set_cache_t *es);
bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir);
/* name conversion functions */
s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
struct uni_name_t *p_uniname, s32 *entries,
struct dos_name_t *p_dosname);
void get_uni_name_from_dos_entry(struct super_block *sb,
struct dos_dentry_t *ep,
struct uni_name_t *p_uniname, u8 mode);
void fat_get_uni_name_from_ext_entry(struct super_block *sb,
struct chain_t *p_dir, s32 entry,
u16 *uniname);
void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
struct chain_t *p_dir, s32 entry,
u16 *uniname);
s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep,
u16 *uniname, s32 order);
s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep,
u16 *uniname, s32 order);
s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
struct dos_name_t *p_dosname);
void fat_attach_count_to_dos_name(u8 *dosname, s32 count);
s32 fat_calc_num_entries(struct uni_name_t *p_uniname);
s32 exfat_calc_num_entries(struct uni_name_t *p_uniname);
u8 calc_checksum_1byte(void *data, s32 len, u8 chksum);
u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type);
/* name resolution functions */
s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
struct uni_name_t *p_uniname);
s32 resolve_name(u8 *name, u8 **arg);
/* file operation functions */
s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
s32 create_dir(struct inode *inode, struct chain_t *p_dir,
struct uni_name_t *p_uniname, struct file_id_t *fid);
s32 create_file(struct inode *inode, struct chain_t *p_dir,
struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid);
void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry);
s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry,
struct uni_name_t *p_uniname, struct file_id_t *fid);
s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
struct chain_t *p_newdir, struct uni_name_t *p_uniname,
struct file_id_t *fid);
/* sector read/write functions */
int sector_read(struct super_block *sb, sector_t sec,
struct buffer_head **bh, bool read);
int sector_write(struct super_block *sb, sector_t sec,
struct buffer_head *bh, bool sync);
int multi_sector_read(struct super_block *sb, sector_t sec,
struct buffer_head **bh, s32 num_secs, bool read);
int multi_sector_write(struct super_block *sb, sector_t sec,
struct buffer_head *bh, s32 num_secs, bool sync);
void bdev_open(struct super_block *sb);
void bdev_close(struct super_block *sb);
int bdev_read(struct super_block *sb, sector_t secno,
struct buffer_head **bh, u32 num_secs, bool read);
int bdev_write(struct super_block *sb, sector_t secno,
struct buffer_head *bh, u32 num_secs, bool sync);
int bdev_sync(struct super_block *sb);
extern const u8 uni_upcase[];
#endif /* _EXFAT_H */