288 lines
8.9 KiB
C
288 lines
8.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0+ */
|
|||
|
|
|
||
|
|
#ifndef _EXFAT_H_
|
||
|
|
#define _EXFAT_H_
|
||
|
|
|
||
|
|
#include <asm/byteorder.h>
|
||
|
|
#include <blk.h>
|
||
|
|
#include <asm/cache.h>
|
||
|
|
|
||
|
|
#define _uswap_64(x, sfx) \
|
||
|
|
((((x) & 0xff00000000000000##sfx) >> 56) | \
|
||
|
|
(((x) & 0x00ff000000000000##sfx) >> 40) | \
|
||
|
|
(((x) & 0x0000ff0000000000##sfx) >> 24) | \
|
||
|
|
(((x) & 0x000000ff00000000##sfx) >> 8) | \
|
||
|
|
(((x) & 0x00000000ff000000##sfx) << 8) | \
|
||
|
|
(((x) & 0x0000000000ff0000##sfx) << 24) | \
|
||
|
|
(((x) & 0x000000000000ff00##sfx) << 40) | \
|
||
|
|
(((x) & 0x00000000000000ff##sfx) << 56))
|
||
|
|
|
||
|
|
#define uswap_64(x) _uswap_64(x, ull)
|
||
|
|
#if defined(__linux__) && defined(__KERNEL__)
|
||
|
|
#define EXFAT2CPU16 le16_to_cpu
|
||
|
|
#define EXFAT2CPU32 le32_to_cpu
|
||
|
|
#define EXFAT2CPU64 le64_to_cpu
|
||
|
|
#else
|
||
|
|
#if __LITTLE_ENDIAN
|
||
|
|
#define EXFAT2CPU16(x) (x)
|
||
|
|
#define EXFAT2CPU32(x) (x)
|
||
|
|
#define EXFAT2CPU64(x) (x)
|
||
|
|
#else
|
||
|
|
#define EXFAT2CPU16(x) ((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
|
||
|
|
#define EXFAT2CPU32(x) ((((x) & 0x000000ff) << 24) | \
|
||
|
|
(((x) & 0x0000ff00) << 8) | \
|
||
|
|
(((x) & 0x00ff0000) >> 8) | \
|
||
|
|
(((x) & 0xff000000) >> 24))
|
||
|
|
#define EXFAT2CPU64(x) uswap_64(x)
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||
|
|
#define ROUND_UP(x, d) (DIV_ROUND_UP(x, d) * (d))
|
||
|
|
|
||
|
|
#define FNAME_MAXLEN_BYTES 256 /* Maximum LFN buffer in bytes */
|
||
|
|
#define MAX_RD_BLK_SIZE 65536
|
||
|
|
#define EXFAT_FAT_ENTRY_SIZE 4
|
||
|
|
|
||
|
|
#define EXFAT_ATTR_RDONLY 0x01
|
||
|
|
#define EXFAT_ATTR_HIDDEN 0x02
|
||
|
|
#define EXFAT_ATTR_SYSTEM 0x04
|
||
|
|
#define EXFAT_ATTR_DIR 0x10
|
||
|
|
#define EXFAT_ATTR_FILE 0x20
|
||
|
|
|
||
|
|
#define EXFAT_ENAME_MAX 15
|
||
|
|
#define EXFAT_FIRST_DATA_CLUSTER 2
|
||
|
|
#define EXFAT_LAST_DATA_CLUSTER 0xfffffff6
|
||
|
|
|
||
|
|
#define EXFAT_CLUSTER_FREE 0 /* free cluster */
|
||
|
|
#define EXFAT_CLUSTER_BAD 0xfffffff7 /* cluster contains bad sector */
|
||
|
|
#define EXFAT_CLUSTER_END 0xffffffff /* final cluster of file or directory */
|
||
|
|
#define CHAR_BIT 8 /* number of bits in a char */
|
||
|
|
|
||
|
|
#define FSOK 0 /* Check was OK */
|
||
|
|
#define FSBOOTMOD 1 /* Boot block was modified */
|
||
|
|
#define FSDIRMOD 2 /* Some directory was modified */
|
||
|
|
#define FSFATMOD 4 /* The FAT was modified */
|
||
|
|
#define FSERROR 8 /* Some unrecovered error remains */
|
||
|
|
#define FSFATAL 16 /* Some unrecoverable error occurred */
|
||
|
|
#define FSDIRTY 32 /* File system is dirty */
|
||
|
|
#define FSFIXFAT 64 /* Fix file system FAT */
|
||
|
|
#define FSNOSPACE 128 /* SD have no space for sysdump */
|
||
|
|
#define FSSMSIZE 256 /* SD card volume size is smaller than sysdump size */
|
||
|
|
|
||
|
|
enum {
|
||
|
|
EXFAT_DTYPE_BM = 0x01, // bitmap entry
|
||
|
|
EXFAT_DTYPE_UC = 0x02, // up-case table entry
|
||
|
|
EXFAT_DTYPE_LABLE = 0x03, // label
|
||
|
|
EXFAT_DTYPE_FILE = 0x05, // regular file or directory
|
||
|
|
EXFAT_DTYPE_STREXT = 0x40, // stream extension entry
|
||
|
|
EXFAT_DTYPE_FNEXT = 0x41, // file name extension entry
|
||
|
|
EXFAT_DTYPE_MASK = 0x7f, // entry type mask
|
||
|
|
EXFAT_DTYPE_USED = 0x80, // flag bit of whether entry is in used or not
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_super_block {
|
||
|
|
__u8 jump[3]; /* 0x00 jmp and nop instructions */
|
||
|
|
__u8 oem_name[8]; /* 0x03 "EXFAT " */
|
||
|
|
__u8 __unused1[53]; /* 0x0B always 0 */
|
||
|
|
__u64 sector_start; /* 0x40 partition first sector */
|
||
|
|
__u64 sector_count; /* 0x48 partition sectors count */
|
||
|
|
__u32 fat_sector_start; /* 0x50 FAT first sector */
|
||
|
|
__u32 fat_sector_count; /* 0x54 FAT sectors count */
|
||
|
|
__u32 cluster_sector_start; /* 0x58 first cluster sector */
|
||
|
|
__u32 cluster_count; /* 0x5C total clusters count */
|
||
|
|
__u32 rootdir_cluster; /* 0x60 first cluster of the root dir */
|
||
|
|
__u32 volume_serial; /* 0x64 volume serial number */
|
||
|
|
struct /* 0x68 FS version */
|
||
|
|
{
|
||
|
|
__u8 minor;
|
||
|
|
__u8 major;
|
||
|
|
}
|
||
|
|
version;
|
||
|
|
__u16 volume_state; /* 0x6A volume state flags */
|
||
|
|
__u8 sector_bits; /* 0x6C sector size as (1 << n) */
|
||
|
|
__u8 spc_bits; /* 0x6D sectors per cluster as (1 << n) */
|
||
|
|
__u8 fat_count; /* 0x6E always 1 */
|
||
|
|
__u8 drive_no; /* 0x6F always 0x80 */
|
||
|
|
__u8 allocated_percent; /* 0x70 percentage of allocated space */
|
||
|
|
__u8 __unused2[397]; /* 0x71 always 0 */
|
||
|
|
__u16 boot_signature; /* the value of 0xAA55 */
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_boot_sector {
|
||
|
|
__u8 ignored[3]; /* Bootstrap code */
|
||
|
|
char fs_name[8]; /* Name of fs, should be "EXFAT " */
|
||
|
|
__u8 zero_bytes[53]; /* Must be zero bytes */
|
||
|
|
__u64 part_off; /* Partition offset (in sector) */
|
||
|
|
__u64 vol_len; /* Volume length (in sector) */
|
||
|
|
__u32 fat_off; /* FATs start sector */
|
||
|
|
__u32 fat_len; /* FATs length */
|
||
|
|
__u32 cluster_heap_off; /* Cluster heap */
|
||
|
|
__u32 cluster_cnt; /* Cluster count */
|
||
|
|
__u32 root_cluster; /* first cluster of root dir */
|
||
|
|
__u32 vol_serial;
|
||
|
|
__u16 fs_version;
|
||
|
|
__u16 vol_flags;
|
||
|
|
__u8 sector_size_bits;
|
||
|
|
__u8 sectors_per_clu_bits;
|
||
|
|
__u8 num_fats;
|
||
|
|
__u8 phy_drv_no;
|
||
|
|
__u8 perc_in_use;
|
||
|
|
__u8 reserved[7];
|
||
|
|
__u8 boot_code[390];
|
||
|
|
__u8 boot_signature[2];
|
||
|
|
};
|
||
|
|
|
||
|
|
struct timestamp {
|
||
|
|
__u16 sec;
|
||
|
|
__u16 min;
|
||
|
|
__u16 hour;
|
||
|
|
__u16 day;
|
||
|
|
__u16 mon;
|
||
|
|
__u16 year;
|
||
|
|
};
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Private filesystem parameters
|
||
|
|
*
|
||
|
|
* Note: exFAT buffer has to be 32 bit aligned
|
||
|
|
* (see exFAT accesses)
|
||
|
|
*/
|
||
|
|
struct exfsdata {
|
||
|
|
__u8 *fatbuf; /* Current FAT buffer */
|
||
|
|
__u8 *bitmap; /* Current bitmap buffer */
|
||
|
|
__u8 *bitmap_fatbuf; /* FAT buffer for bitmap file */
|
||
|
|
__u16 *uptab_buf; /* upcase-table buffer */
|
||
|
|
__u32 fat_num;
|
||
|
|
__u32 fatlength; /* Length of FAT in sectors */
|
||
|
|
__u32 bitmaplen; /* Length of bitmap in bytes */
|
||
|
|
__u32 cluster_cnt; /* Total cluster count */
|
||
|
|
__u32 fat_sect; /* Starting sector of the FAT */
|
||
|
|
__u32 bitmap_sect; /* Starting sector of the FAT */
|
||
|
|
__u32 bitmap_fatbuf_size; /* size in sector of FAT buffer for bitmap file */
|
||
|
|
__u32 cur_bitmap_cluster; /* current read in bitmap file cluster */
|
||
|
|
__u32 rootdir_sect; /* Start sector of root directory */
|
||
|
|
__u16 sect_size; /* Size of sectors in bytes */
|
||
|
|
__u16 clust_size; /* Size of clusters in sectors */
|
||
|
|
__u32 rd_sectors; /* read sectors once */
|
||
|
|
__u32 fatbuf_idx; /* got fat table buffer index */
|
||
|
|
__u32 bitmap_idx; /* got bitmap buffer index */
|
||
|
|
__u32 avail_clusters; /* free clusters can be used */
|
||
|
|
__s32 data_begin; /* The sector of the first cluster, can be negative */
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_entry_label { /* volume label */
|
||
|
|
__u8 entry_type; /* EXFAT_ENTRY_LABEL */
|
||
|
|
__u8 length; /* number of characters */
|
||
|
|
__u16 name[EXFAT_ENAME_MAX]; /* in UTF-16LE */
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_bitmap_entry {
|
||
|
|
__u8 entry_type; /*entry type */
|
||
|
|
__u8 bitmap_flags;
|
||
|
|
__u8 reserved[18];
|
||
|
|
__u32 start_clu;
|
||
|
|
__u64 data_len;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_entry_upcase { /* upper case translation table */
|
||
|
|
__u8 entry_type; /* EXFAT_ENTRY_UPCASE */
|
||
|
|
__u8 __unknown1[3];
|
||
|
|
__u32 checksum;
|
||
|
|
__u8 __unknown2[12];
|
||
|
|
__u32 start_cluster;
|
||
|
|
__u64 size; /* in bytes */
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_strext_entry {
|
||
|
|
__u8 entry_type;
|
||
|
|
__u8 secondary_flags;
|
||
|
|
__u8 reserved0;
|
||
|
|
__u8 name_len;
|
||
|
|
__u16 name_hash;
|
||
|
|
__u8 reserved1[2];
|
||
|
|
__u64 val_data_len;
|
||
|
|
__u8 reserved2[4];
|
||
|
|
__u32 first_cluster;
|
||
|
|
__u64 data_len;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_file_entry {
|
||
|
|
__u8 entry_type;
|
||
|
|
__u8 secondary_cnt;
|
||
|
|
__u16 checksum;
|
||
|
|
__u16 attr;
|
||
|
|
__u8 reserved0[2];
|
||
|
|
__u32 creat_time;
|
||
|
|
__u32 mod_time;
|
||
|
|
__u32 access_time;
|
||
|
|
__u8 creat_ms_inc;
|
||
|
|
__u8 mod_ms_inc;
|
||
|
|
__u8 creat_utc_off;
|
||
|
|
__u8 mod_utc_off;
|
||
|
|
struct exfat_strext_entry *str_dent;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_fnext_entry {
|
||
|
|
__u8 entry_type;
|
||
|
|
__u8 secondary_flags;
|
||
|
|
__u16 uniname[15];
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_dentry {
|
||
|
|
__u8 entry_type;
|
||
|
|
__u8 secondary_flags;
|
||
|
|
__u8 bytes[30];
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_buf_info {
|
||
|
|
__u8 *pbuf;
|
||
|
|
__u32 cluster;
|
||
|
|
__u32 start_sec;
|
||
|
|
__u32 sectors;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_whole_dentry {
|
||
|
|
struct exfat_buf_info bf0;
|
||
|
|
struct exfat_buf_info bf1;
|
||
|
|
struct exfat_file_entry *empty;
|
||
|
|
struct exfat_file_entry *prim;
|
||
|
|
struct exfat_strext_entry *strext;
|
||
|
|
struct exfat_fnext_entry *fname_dent[17];
|
||
|
|
void *parent;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct exfat_buf_array {
|
||
|
|
struct exfat_buf_info bf0;
|
||
|
|
struct exfat_buf_info bf1;
|
||
|
|
};
|
||
|
|
|
||
|
|
extern __u8 bitmap_mask[9];
|
||
|
|
extern __u8 bitmap_clr_mask[8];
|
||
|
|
extern __u8 bits_num_table[256];
|
||
|
|
extern __u8 bitmap_avail[256];
|
||
|
|
extern __u8 upcase_table[5836];
|
||
|
|
|
||
|
|
int exfat_disk_read(__u32 block, __u32 nr_blocks, void *buf);
|
||
|
|
int exfat_disk_write(__u32 block, __u32 nr_blocks, void *buf);
|
||
|
|
int read_exfat_bootsec(struct exfat_boot_sector *bs);
|
||
|
|
void *exfat_malloc_aligned(size_t align, size_t bytes);
|
||
|
|
int exfat_mfree(void *ptr);
|
||
|
|
void downcase(char *str);
|
||
|
|
|
||
|
|
int exfat_register_device(struct blk_desc *dev_desc, int part_no);
|
||
|
|
int file_exfat_detectfs(void);
|
||
|
|
int get_exfat_blocks(struct exfsdata *mydata, __u32 start_sec, __u8 *buffer, __u32 rd_sec);
|
||
|
|
int check_bitmap_fatbuf(struct exfsdata *mydata);
|
||
|
|
int check_available_size(struct exfsdata *mydata, __u64 size);
|
||
|
|
|
||
|
|
int file_exfat_write(const char *filename, void *buffer, unsigned long maxsize);
|
||
|
|
int dir_exfat_create(const char *dirname);
|
||
|
|
int dir_exfat_rename(const char *scr, const char *dest);
|
||
|
|
int dir_exfat_remove(const char *dirname);
|
||
|
|
int dir_exfat_check(const char *dirname);
|
||
|
|
int exfat_checksys(size_t ram_size);
|
||
|
|
int exfat_format(void);
|
||
|
|
#endif /* _EXFAT_H_ */
|