xref: /OK3568_Linux_fs/u-boot/include/fat.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
5*4882a593Smuzhiyun  * 2003-03-10 - kharris@nexus-tech.net - ported to u-boot
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #ifndef _FAT_H_
11*4882a593Smuzhiyun #define _FAT_H_
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <asm/byteorder.h>
14*4882a593Smuzhiyun #include <fs.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define CONFIG_SUPPORT_VFAT
17*4882a593Smuzhiyun /* Maximum Long File Name length supported here is 128 UTF-16 code units */
18*4882a593Smuzhiyun #define VFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */
19*4882a593Smuzhiyun #define VFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */
20*4882a593Smuzhiyun #define PREFETCH_BLOCKS		2
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define MAX_CLUSTSIZE	CONFIG_FS_FAT_MAX_CLUSTSIZE
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define DIRENTSPERBLOCK	(mydata->sect_size / sizeof(dir_entry))
25*4882a593Smuzhiyun #define DIRENTSPERCLUST	((mydata->clust_size * mydata->sect_size) / \
26*4882a593Smuzhiyun 			 sizeof(dir_entry))
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define FATBUFBLOCKS	6
29*4882a593Smuzhiyun #define FATBUFSIZE	(mydata->sect_size * FATBUFBLOCKS)
30*4882a593Smuzhiyun #define FAT12BUFSIZE	((FATBUFSIZE*2)/3)
31*4882a593Smuzhiyun #define FAT16BUFSIZE	(FATBUFSIZE/2)
32*4882a593Smuzhiyun #define FAT32BUFSIZE	(FATBUFSIZE/4)
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /* Maximum number of entry for long file name according to spec */
35*4882a593Smuzhiyun #define MAX_LFN_SLOT	20
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /* Filesystem identifiers */
38*4882a593Smuzhiyun #define FAT12_SIGN	"FAT12   "
39*4882a593Smuzhiyun #define FAT16_SIGN	"FAT16   "
40*4882a593Smuzhiyun #define FAT32_SIGN	"FAT32   "
41*4882a593Smuzhiyun #define SIGNLEN		8
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /* File attributes */
44*4882a593Smuzhiyun #define ATTR_RO	1
45*4882a593Smuzhiyun #define ATTR_HIDDEN	2
46*4882a593Smuzhiyun #define ATTR_SYS	4
47*4882a593Smuzhiyun #define ATTR_VOLUME	8
48*4882a593Smuzhiyun #define ATTR_DIR	16
49*4882a593Smuzhiyun #define ATTR_ARCH	32
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define ATTR_VFAT	(ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #define DELETED_FLAG	((char)0xe5) /* Marks deleted files when in name[0] */
54*4882a593Smuzhiyun #define aRING		0x05	     /* Used as special character in name[0] */
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun  * Indicates that the entry is the last long entry in a set of long
58*4882a593Smuzhiyun  * dir entries
59*4882a593Smuzhiyun  */
60*4882a593Smuzhiyun #define LAST_LONG_ENTRY_MASK	0x40
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define ISDIRDELIM(c)	((c) == '/' || (c) == '\\')
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun #define FSTYPE_NONE	(-1)
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #if defined(__linux__) && defined(__KERNEL__)
67*4882a593Smuzhiyun #define FAT2CPU16	le16_to_cpu
68*4882a593Smuzhiyun #define FAT2CPU32	le32_to_cpu
69*4882a593Smuzhiyun #else
70*4882a593Smuzhiyun #if __LITTLE_ENDIAN
71*4882a593Smuzhiyun #define FAT2CPU16(x)	(x)
72*4882a593Smuzhiyun #define FAT2CPU32(x)	(x)
73*4882a593Smuzhiyun #else
74*4882a593Smuzhiyun #define FAT2CPU16(x)	((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
75*4882a593Smuzhiyun #define FAT2CPU32(x)	((((x) & 0x000000ff) << 24)  |	\
76*4882a593Smuzhiyun 			 (((x) & 0x0000ff00) << 8)  |	\
77*4882a593Smuzhiyun 			 (((x) & 0x00ff0000) >> 8)  |	\
78*4882a593Smuzhiyun 			 (((x) & 0xff000000) >> 24))
79*4882a593Smuzhiyun #endif
80*4882a593Smuzhiyun #endif
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun #define START(dent)	(FAT2CPU16((dent)->start) \
83*4882a593Smuzhiyun 			+ (mydata->fatsize != 32 ? 0 : \
84*4882a593Smuzhiyun 			  (FAT2CPU16((dent)->starthi) << 16)))
85*4882a593Smuzhiyun #define IS_LAST_CLUST(x, fatsize) ((x) >= ((fatsize) != 32 ? \
86*4882a593Smuzhiyun 					((fatsize) != 16 ? 0xff8 : 0xfff8) : \
87*4882a593Smuzhiyun 					0xffffff8))
88*4882a593Smuzhiyun #define CHECK_CLUST(x, fatsize) ((x) <= 1 || \
89*4882a593Smuzhiyun 				(x) >= ((fatsize) != 32 ? \
90*4882a593Smuzhiyun 					((fatsize) != 16 ? 0xff0 : 0xfff0) : \
91*4882a593Smuzhiyun 					0xffffff0))
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun typedef struct boot_sector {
94*4882a593Smuzhiyun 	__u8	ignored[3];	/* Bootstrap code */
95*4882a593Smuzhiyun 	char	system_id[8];	/* Name of fs */
96*4882a593Smuzhiyun 	__u8	sector_size[2];	/* Bytes/sector */
97*4882a593Smuzhiyun 	__u8	cluster_size;	/* Sectors/cluster */
98*4882a593Smuzhiyun 	__u16	reserved;	/* Number of reserved sectors */
99*4882a593Smuzhiyun 	__u8	fats;		/* Number of FATs */
100*4882a593Smuzhiyun 	__u8	dir_entries[2];	/* Number of root directory entries */
101*4882a593Smuzhiyun 	__u8	sectors[2];	/* Number of sectors */
102*4882a593Smuzhiyun 	__u8	media;		/* Media code */
103*4882a593Smuzhiyun 	__u16	fat_length;	/* Sectors/FAT */
104*4882a593Smuzhiyun 	__u16	secs_track;	/* Sectors/track */
105*4882a593Smuzhiyun 	__u16	heads;		/* Number of heads */
106*4882a593Smuzhiyun 	__u32	hidden;		/* Number of hidden sectors */
107*4882a593Smuzhiyun 	__u32	total_sect;	/* Number of sectors (if sectors == 0) */
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	/* FAT32 only */
110*4882a593Smuzhiyun 	__u32	fat32_length;	/* Sectors/FAT */
111*4882a593Smuzhiyun 	__u16	flags;		/* Bit 8: fat mirroring, low 4: active fat */
112*4882a593Smuzhiyun 	__u8	version[2];	/* Filesystem version */
113*4882a593Smuzhiyun 	__u32	root_cluster;	/* First cluster in root directory */
114*4882a593Smuzhiyun 	__u16	info_sector;	/* Filesystem info sector */
115*4882a593Smuzhiyun 	__u16	backup_boot;	/* Backup boot sector */
116*4882a593Smuzhiyun 	__u16	reserved2[6];	/* Unused */
117*4882a593Smuzhiyun } boot_sector;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun typedef struct volume_info
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	__u8 drive_number;	/* BIOS drive number */
122*4882a593Smuzhiyun 	__u8 reserved;		/* Unused */
123*4882a593Smuzhiyun 	__u8 ext_boot_sign;	/* 0x29 if fields below exist (DOS 3.3+) */
124*4882a593Smuzhiyun 	__u8 volume_id[4];	/* Volume ID number */
125*4882a593Smuzhiyun 	char volume_label[11];	/* Volume label */
126*4882a593Smuzhiyun 	char fs_type[8];	/* Typically FAT12, FAT16, or FAT32 */
127*4882a593Smuzhiyun 	/* Boot code comes next, all but 2 bytes to fill up sector */
128*4882a593Smuzhiyun 	/* Boot sign comes last, 2 bytes */
129*4882a593Smuzhiyun } volume_info;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun /* see dir_entry::lcase: */
132*4882a593Smuzhiyun #define CASE_LOWER_BASE	8	/* base (name) is lower case */
133*4882a593Smuzhiyun #define CASE_LOWER_EXT	16	/* extension is lower case */
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun typedef struct dir_entry {
136*4882a593Smuzhiyun 	char	name[8],ext[3];	/* Name and extension */
137*4882a593Smuzhiyun 	__u8	attr;		/* Attribute bits */
138*4882a593Smuzhiyun 	__u8	lcase;		/* Case for name and ext (CASE_LOWER_x) */
139*4882a593Smuzhiyun 	__u8	ctime_ms;	/* Creation time, milliseconds */
140*4882a593Smuzhiyun 	__u16	ctime;		/* Creation time */
141*4882a593Smuzhiyun 	__u16	cdate;		/* Creation date */
142*4882a593Smuzhiyun 	__u16	adate;		/* Last access date */
143*4882a593Smuzhiyun 	__u16	starthi;	/* High 16 bits of cluster in FAT32 */
144*4882a593Smuzhiyun 	__u16	time,date,start;/* Time, date and first cluster */
145*4882a593Smuzhiyun 	__u32	size;		/* File size in bytes */
146*4882a593Smuzhiyun } dir_entry;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun typedef struct dir_slot {
149*4882a593Smuzhiyun 	__u8	id;		/* Sequence number for slot */
150*4882a593Smuzhiyun 	__u8	name0_4[10];	/* First 5 characters in name */
151*4882a593Smuzhiyun 	__u8	attr;		/* Attribute byte */
152*4882a593Smuzhiyun 	__u8	reserved;	/* Unused */
153*4882a593Smuzhiyun 	__u8	alias_checksum;/* Checksum for 8.3 alias */
154*4882a593Smuzhiyun 	__u8	name5_10[12];	/* 6 more characters in name */
155*4882a593Smuzhiyun 	__u16	start;		/* Unused */
156*4882a593Smuzhiyun 	__u8	name11_12[4];	/* Last 2 characters in name */
157*4882a593Smuzhiyun } dir_slot;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /*
160*4882a593Smuzhiyun  * Private filesystem parameters
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  * Note: FAT buffer has to be 32 bit aligned
163*4882a593Smuzhiyun  * (see FAT32 accesses)
164*4882a593Smuzhiyun  */
165*4882a593Smuzhiyun typedef struct {
166*4882a593Smuzhiyun 	__u8	*fatbuf;	/* Current FAT buffer */
167*4882a593Smuzhiyun 	int	fatsize;	/* Size of FAT in bits */
168*4882a593Smuzhiyun 	__u32	fatlength;	/* Length of FAT in sectors */
169*4882a593Smuzhiyun 	__u16	fat_sect;	/* Starting sector of the FAT */
170*4882a593Smuzhiyun 	__u8	fat_dirty;      /* Set if fatbuf has been modified */
171*4882a593Smuzhiyun 	__u32	rootdir_sect;	/* Start sector of root directory */
172*4882a593Smuzhiyun 	__u16	sect_size;	/* Size of sectors in bytes */
173*4882a593Smuzhiyun 	__u16	clust_size;	/* Size of clusters in sectors */
174*4882a593Smuzhiyun 	int	data_begin;	/* The sector of the first cluster, can be negative */
175*4882a593Smuzhiyun 	int	fatbufnum;	/* Used by get_fatent, init to -1 */
176*4882a593Smuzhiyun 	int	rootdir_size;	/* Size of root dir for non-FAT32 */
177*4882a593Smuzhiyun 	__u32	root_cluster;	/* First cluster of root dir for FAT32 */
178*4882a593Smuzhiyun } fsdata;
179*4882a593Smuzhiyun 
clust_to_sect(fsdata * fsdata,u32 clust)180*4882a593Smuzhiyun static inline u32 clust_to_sect(fsdata *fsdata, u32 clust)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	return fsdata->data_begin + clust * fsdata->clust_size;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
sect_to_clust(fsdata * fsdata,u32 sect)185*4882a593Smuzhiyun static inline u32 sect_to_clust(fsdata *fsdata, u32 sect)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	return (sect - fsdata->data_begin) / fsdata->clust_size;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun int file_fat_detectfs(void);
191*4882a593Smuzhiyun int fat_exists(const char *filename);
192*4882a593Smuzhiyun int fat_size(const char *filename, loff_t *size);
193*4882a593Smuzhiyun int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
194*4882a593Smuzhiyun 		     loff_t maxsize, loff_t *actread);
195*4882a593Smuzhiyun int file_fat_read(const char *filename, void *buffer, int maxsize);
196*4882a593Smuzhiyun int fat_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info);
197*4882a593Smuzhiyun int fat_register_device(struct blk_desc *dev_desc, int part_no);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len,
200*4882a593Smuzhiyun 		   loff_t *actwrite);
201*4882a593Smuzhiyun int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
202*4882a593Smuzhiyun 		  loff_t *actread);
203*4882a593Smuzhiyun int fat_opendir(const char *filename, struct fs_dir_stream **dirsp);
204*4882a593Smuzhiyun int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
205*4882a593Smuzhiyun void fat_closedir(struct fs_dir_stream *dirs);
206*4882a593Smuzhiyun void fat_close(void);
207*4882a593Smuzhiyun #endif /* _FAT_H_ */
208