252 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0+ */
 | |
| /*
 | |
|  * R/O exFAT filesystem implementation
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifndef _EXFAT_H_
 | |
| #define _EXFAT_H_
 | |
| 
 | |
| #include <asm/byteorder.h>
 | |
| #include <fs.h>
 | |
| 
 | |
| /* Maximum Long File Name length supported here is 128 UTF-16 code units */
 | |
| #define EXFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */
 | |
| #define EXFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */
 | |
| #define EXFAT_PREFETCH_BLOCKS		2
 | |
| 
 | |
| #ifndef CONFIG_FS_EXFAT_MAX_CLUSTSIZE
 | |
| #define CONFIG_FS_EXFAT_MAX_CLUSTSIZE (256*1024)
 | |
| #endif
 | |
| #define EXFAT_MAX_CLUSTSIZE	CONFIG_FS_EXFAT_MAX_CLUSTSIZE
 | |
| 
 | |
| #define EXFAT_DIRENTSPERBLOCK	(mydata->sect_size / EXFAT_SIZE_PER_ENTRY)
 | |
| #define EXFAT_DIRENTSPERCLUST	((mydata->clust_size * mydata->sect_size) / \
 | |
| 			 EXFAT_SIZE_PER_ENTRY)
 | |
| 
 | |
| #define FATBUFBLOCKS	6
 | |
| #define FATBUFSIZE	(mydata->sect_size * FATBUFBLOCKS)
 | |
| #define EXFATBUFSIZE	(FATBUFSIZE/4)
 | |
| 
 | |
| /* Maximum number of entry for long file name according to spec */
 | |
| #define MAX_LFN_SLOT	20
 | |
| 
 | |
| /* Filesystem identifiers */
 | |
| #define EXFAT_SIGN	"EXFAT   "
 | |
| #define EXFAT_SIGNLEN		8
 | |
| 
 | |
| /* File attributes */
 | |
| #define ATTR_RO	1
 | |
| #define ATTR_HIDDEN	2
 | |
| #define ATTR_SYS	4
 | |
| #define ATTR_VOLUME	8
 | |
| #define ATTR_DIR	16
 | |
| #define ATTR_ARCH	32
 | |
| 
 | |
| #define ATTR_EXFAT	(ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
 | |
| 
 | |
| /*
 | |
|  * Indicates that the entry is the last long entry in a set of long
 | |
|  * dir entries
 | |
|  */
 | |
| #define LAST_LONG_ENTRY_MASK	0x40
 | |
| 
 | |
| /* Flags telling whether we should read a file or list a directory */
 | |
| #define LS_NO		0
 | |
| #define LS_YES		1
 | |
| #define LS_DIR		1
 | |
| #define LS_ROOT		2
 | |
| 
 | |
| #define ISDIRDELIM(c)	((c) == '/' || (c) == '\\')
 | |
| 
 | |
| //#define FSTYPE_NONE	(-1)
 | |
| 
 | |
| #if defined(__linux__) && defined(__KERNEL__)
 | |
| #define FAT2CPU16	le16_to_cpu
 | |
| #define FAT2CPU32	le32_to_cpu
 | |
| #else
 | |
| #if __LITTLE_ENDIAN
 | |
| #define FAT2CPU16(x)	(x)
 | |
| #define FAT2CPU32(x)	(x)
 | |
| #else
 | |
| #define FAT2CPU16(x)	((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
 | |
| #define FAT2CPU32(x)	((((x) & 0x000000ff) << 24)  |	\
 | |
| 			 (((x) & 0x0000ff00) << 8)  |	\
 | |
| 			 (((x) & 0x00ff0000) >> 8)  |	\
 | |
| 			 (((x) & 0xff000000) >> 24))
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
| #define EXFAT_START(strmptr) (FAT2CPU32((strmptr)->first_clus))
 | |
| #define EXFAT_SIZE(strmptr) ((unsigned long long)FAT2CPU32((strmptr)->valid_data_len[0]) \
 | |
| 						+ FAT2CPU32((unsigned long long)(strmptr)->valid_data_len[1] << 32))
 | |
| #define EXFAT_IS_CONTIGUOUS(strmptr) ((strmptr)->flags & EXFAT_ENTRY_CONTIGUOUS ? 1 : 0)
 | |
| #define EXFAT_CHECK_CLUST(x, fatsize) ((x) <= 1 || (x) >= (0xffffff0))
 | |
| 
 | |
| #define START(dent)	(FAT2CPU16((dent)->start) \
 | |
| 			+ (mydata->fatsize != 32 ? 0 : \
 | |
| 			  (FAT2CPU16((dent)->starthi) << 16)))
 | |
| #define IS_LAST_CLUST(x, fatsize) ((x) >= ((fatsize) != 32 ? \
 | |
| 					((fatsize) != 16 ? 0xff8 : 0xfff8) : \
 | |
| 					0xffffff8))
 | |
| #define CHECK_CLUST(x, fatsize) ((x) <= 1 || \
 | |
| 				(x) >= ((fatsize) != 32 ? \
 | |
| 					((fatsize) != 16 ? 0xff0 : 0xfff0) : \
 | |
| 					0xffffff0))
 | |
| 
 | |
| typedef struct exfat_boot_sector {
 | |
| 	__u8	ignored[3];	/* Bootstrap code */
 | |
| 	char	file_system_name[8];	/* Name of fs */
 | |
| 	__u8	must_be_zero[53]; /* All 00h */
 | |
| 	__u32	partition_offset[2];
 | |
| 	__u32	volume_length[2];	/* Number of sectors (if sectors == 0) */
 | |
| 	__u32	fat_offset;
 | |
| 	__u32	fat_length;	/* Sectors/FAT */
 | |
| 	__u32	cluster_heap_offset;
 | |
| 	__u32	cluster_count;
 | |
| 	__u32	first_clus_of_root_dir;
 | |
| 	__u32	volume_serial_number;
 | |
| 	__u16	file_system_revision;
 | |
| 	__u16	volume_flags;
 | |
| 	__u8	byte_per_sector_shift;
 | |
| 	__u8	sector_per_clus_shift;
 | |
| 	__u8	number_of_fats;
 | |
| } exfat_boot_sector;
 | |
| 
 | |
| typedef struct exfat_volume_info
 | |
| {
 | |
| 	__u8 drive_number;	/* BIOS drive number */
 | |
| 	__u8 reserved;		/* Unused */
 | |
| 	__u8 ext_boot_sign;	/* 0x29 if fields below exist (DOS 3.3+) */
 | |
| 	__u8 volume_id[4];	/* Volume ID number */
 | |
| 	char volume_label[11];	/* Volume label */
 | |
| 	char fs_type[8];	/* Typically FAT12, FAT16, FAT32 or EXFAT */
 | |
| 	/* Boot code comes next, all but 2 bytes to fill up sector */
 | |
| 	/* Boot sign comes last, 2 bytes */
 | |
| } exfat_volume_info;
 | |
| 
 | |
| #define EXFAT_SIZE_PER_ENTRY		32
 | |
| #define EXFAT_NAME_ENTRY_MAXCHAR	15 //max characters of each name entry (15)
 | |
| #define EXFAT_NAME_ENTRY_MAXNUM		17 //the max number of name entries (17)
 | |
| #define EXFAT_FILENAME_MAXLEN		EXFAT_NAME_ENTRY_MAXCHAR*EXFAT_NAME_ENTRY_MAXNUM //255
 | |
| 
 | |
| #define EXFAT_ENTRYTYPE_INUSE		0x80
 | |
| #define EXFAT_ENTRY_CONTIGUOUS		0x2
 | |
| 
 | |
| #define EXFAT_ENTRY_TYPE_FILE		0x85
 | |
| #define EXFAT_ENTRY_TYPE_STREAM		0xC0
 | |
| #define EXFAT_ENTRY_TYPE_NAME		0xC1
 | |
| 
 | |
| #define EXFAT_ENTRY_TYPE_EMPTY		0x00
 | |
| 
 | |
| #define EXFAT_DELETED_FLAG_FILE	    0x05 /* Marks deleted files */
 | |
| #define EXFAT_DELETED_FLAG_STREAM   0x40 /* Marks deleted files */
 | |
| #define EXFAT_DELETED_FLAG_NAME	    0x41 /* Marks deleted files */
 | |
| 
 | |
| /* MS-DOS EXFAT bitmap directory entry (32 bytes) */
 | |
| typedef struct {
 | |
| 	__u8	entry_type;
 | |
| 	__u8	flags;
 | |
| 	__u16	reserved[9];
 | |
| 	__u32	first_clus;
 | |
| 	__u32	data_len[2];
 | |
| } exfat_bitmap_dentry;
 | |
| 
 | |
| /* MS-DOS EXFAT file directory entry (32 bytes) */
 | |
| typedef struct {
 | |
| 	__u8	entry_type;
 | |
| 	__u8	second_count;
 | |
| 	__u16	check_sum;
 | |
| 	__u16	attrib;
 | |
| 	__u16	reserved1;
 | |
| 	__u16	create_time;
 | |
| 	__u16	create_date;
 | |
| 	__u16	modify_time;
 | |
| 	__u16	modify_date;
 | |
| 	__u16	access_time;
 | |
| 	__u16	access_date;
 | |
| 	__u8	create_time_10ms;
 | |
| 	__u8	modify_time_10ms;
 | |
| 	__u8	create_utc_offset;
 | |
| 	__u8	modify_utc_offset;
 | |
| 	__u8	access_utc_offset;
 | |
| 	__u8	reserved2[7];
 | |
| } exfat_file_dentry;
 | |
| 
 | |
| /* MS-DOS EXFAT stream extension directory entry (32 bytes) */
 | |
| typedef struct {
 | |
| 	__u8	entry_type;
 | |
| 	__u8	flags;
 | |
| 	__u8	reserved1;
 | |
| 	__u8	name_len;
 | |
| 	__u16	name_hash;
 | |
| 	__u16	reserved2;
 | |
| 	__u32	valid_data_len[2];
 | |
| 	__u32	reserved3;
 | |
| 	__u32	first_clus;
 | |
| 	__u32	data_len[2];
 | |
| } exfat_stream_dentry;
 | |
| 
 | |
| /* MS-DOS EXFAT file name directory entry (32 bytes) */
 | |
| typedef struct {
 | |
| 	__u8	entry_type;
 | |
| 	__u8	flags;
 | |
| 	__u16	name[EXFAT_NAME_ENTRY_MAXCHAR];
 | |
| } exfat_name_dentry;
 | |
| 
 | |
| typedef struct {
 | |
| 	exfat_file_dentry    file_dentry ;
 | |
| 	exfat_stream_dentry  stream_dentry ;
 | |
| 	exfat_name_dentry    name_dentry[EXFAT_NAME_ENTRY_MAXNUM];//although this is an array, but the valid number should be calculate from Stream_Entry
 | |
| } exfat_entry_set;
 | |
| 
 | |
| /*
 | |
|  * Private filesystem parameters
 | |
|  *
 | |
|  * Note: FAT buffer has to be 32 bit aligned
 | |
|  * (see FAT32 accesses)
 | |
|  */
 | |
| typedef struct {
 | |
| 	__u8	*fatbuf;	/* Current FAT buffer */
 | |
| 	int	fatsize;	/* Size of FAT in bits */
 | |
| 	__u32	fatlength;	/* Length of FAT in sectors */
 | |
| 	__u16	fat_sect;	/* Starting sector of the FAT */
 | |
| 	__u8	fat_dirty;      /* Set if fatbuf has been modified */
 | |
| 	__u32	rootdir_sect;	/* Start sector of root directory */
 | |
| 	__u16	sect_size;	/* Size of sectors in bytes */
 | |
| 	__u16	clust_size;	/* Size of clusters in sectors */
 | |
| 	int	data_begin;	/* The sector of the first cluster, can be negative */
 | |
| 	int	fatbufnum;	/* Used by get_fatent, init to -1 */
 | |
| 	int	rootdir_size;	/* Size of root dir for non-FAT32 */
 | |
| 	__u32	root_cluster;	/* First cluster of root dir for FAT32 */
 | |
| 	u32	total_sect;	/* Number of sectors */
 | |
| 	int	fats;		/* Number of FATs */
 | |
| } exfat_fsdata;
 | |
| 
 | |
| static inline u32 exfat_clust_to_sect(exfat_fsdata *fsdata, u32 clust)
 | |
| {
 | |
| 	return fsdata->data_begin + clust * fsdata->clust_size;
 | |
| }
 | |
| 
 | |
| int file_exfat_detectfs(void);
 | |
| int exfat_ls(const char *dir);
 | |
| int exfat_exists(const char *filename);
 | |
| int exfat_size(const char *filename, loff_t *size);
 | |
| int file_exfat_read_at(const char *filename, loff_t pos, void *buffer,
 | |
| 		     loff_t maxsize, loff_t *actread);
 | |
| int file_exfat_read(const char *filename, void *buffer, int maxsize);
 | |
| int exfat_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info);
 | |
| int exfat_register_device(struct blk_desc *dev_desc, int part_no);
 | |
| 
 | |
| int file_exfat_write(const char *filename, void *buf, loff_t offset, loff_t len,
 | |
| 		   loff_t *actwrite);
 | |
| int exfat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
 | |
| 		  loff_t *actread);
 | |
| int exfat_opendir(const char *filename, struct fs_dir_stream **dirsp);
 | |
| int exfat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
 | |
| void exfat_closedir(struct fs_dir_stream *dirs);
 | |
| int exfat_unlink(const char *filename);
 | |
| int exfat_mkdir(const char *dirname);
 | |
| void exfat_close(void);
 | |
| #endif /* _EXFAT_H_ */
 | 
