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