fat.h 6.68 KB
Newer Older
1 2 3 4 5 6
/*
 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
 *
 * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
 * 2003-03-10 - kharris@nexus-tech.net - ported to u-boot
 *
7
 * SPDX-License-Identifier:	GPL-2.0+
8 9 10 11 12
 */

#ifndef _FAT_H_
#define _FAT_H_

13 14
#include <asm/byteorder.h>

15
#define CONFIG_SUPPORT_VFAT
16 17 18
/* Maximum Long File Name length supported here is 128 UTF-16 code units */
#define VFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */
#define VFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */
19
#define PREFETCH_BLOCKS		2
20

21 22 23 24 25
#ifndef CONFIG_FS_FAT_MAX_CLUSTSIZE
#define CONFIG_FS_FAT_MAX_CLUSTSIZE 65536
#endif
#define MAX_CLUSTSIZE	CONFIG_FS_FAT_MAX_CLUSTSIZE

26 27 28
#define DIRENTSPERBLOCK	(mydata->sect_size / sizeof(dir_entry))
#define DIRENTSPERCLUST	((mydata->clust_size * mydata->sect_size) / \
			 sizeof(dir_entry))
29 30

#define FATBUFBLOCKS	6
31
#define FATBUFSIZE	(mydata->sect_size * FATBUFBLOCKS)
32
#define FAT12BUFSIZE	((FATBUFSIZE*2)/3)
33 34 35 36 37 38 39 40 41 42 43
#define FAT16BUFSIZE	(FATBUFSIZE/2)
#define FAT32BUFSIZE	(FATBUFSIZE/4)


/* Filesystem identifiers */
#define FAT12_SIGN	"FAT12   "
#define FAT16_SIGN	"FAT16   "
#define FAT32_SIGN	"FAT32   "
#define SIGNLEN		8

/* File attributes */
44 45 46 47 48 49
#define ATTR_RO	1
#define ATTR_HIDDEN	2
#define ATTR_SYS	4
#define ATTR_VOLUME	8
#define ATTR_DIR	16
#define ATTR_ARCH	32
50

51
#define ATTR_VFAT	(ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
52 53

#define DELETED_FLAG	((char)0xe5) /* Marks deleted files when in name[0] */
54
#define aRING		0x05	     /* Used as special character in name[0] */
55

56 57
/*
 * Indicates that the entry is the last long entry in a set of long
58 59 60
 * dir entries
 */
#define LAST_LONG_ENTRY_MASK	0x40
61 62

/* Flags telling whether we should read a file or list a directory */
63 64 65 66
#define LS_NO		0
#define LS_YES		1
#define LS_DIR		1
#define LS_ROOT		2
67

68
#define ISDIRDELIM(c)	((c) == '/' || (c) == '\\')
69 70 71 72 73 74 75

#define FSTYPE_NONE	(-1)

#if defined(__linux__) && defined(__KERNEL__)
#define FAT2CPU16	le16_to_cpu
#define FAT2CPU32	le32_to_cpu
#else
76
#if __LITTLE_ENDIAN
77 78 79 80 81
#define FAT2CPU16(x)	(x)
#define FAT2CPU32(x)	(x)
#else
#define FAT2CPU16(x)	((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
#define FAT2CPU32(x)	((((x) & 0x000000ff) << 24)  |	\
Wolfgang Denk's avatar
Wolfgang Denk committed
82
			 (((x) & 0x0000ff00) << 8)  |	\
83 84 85 86 87 88 89 90
			 (((x) & 0x00ff0000) >> 8)  |	\
			 (((x) & 0xff000000) >> 24))
#endif
#endif

#define START(dent)	(FAT2CPU16((dent)->start) \
			+ (mydata->fatsize != 32 ? 0 : \
			  (FAT2CPU16((dent)->starthi) << 16)))
91 92 93
#define IS_LAST_CLUST(x, fatsize) ((x) >= ((fatsize) != 32 ? \
					((fatsize) != 16 ? 0xff8 : 0xfff8) : \
					0xffffff8))
94
#define CHECK_CLUST(x, fatsize) ((x) <= 1 || \
95 96 97
				(x) >= ((fatsize) != 32 ? \
					((fatsize) != 16 ? 0xff0 : 0xfff0) : \
					0xffffff0))
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

typedef struct boot_sector {
	__u8	ignored[3];	/* Bootstrap code */
	char	system_id[8];	/* Name of fs */
	__u8	sector_size[2];	/* Bytes/sector */
	__u8	cluster_size;	/* Sectors/cluster */
	__u16	reserved;	/* Number of reserved sectors */
	__u8	fats;		/* Number of FATs */
	__u8	dir_entries[2];	/* Number of root directory entries */
	__u8	sectors[2];	/* Number of sectors */
	__u8	media;		/* Media code */
	__u16	fat_length;	/* Sectors/FAT */
	__u16	secs_track;	/* Sectors/track */
	__u16	heads;		/* Number of heads */
	__u32	hidden;		/* Number of hidden sectors */
	__u32	total_sect;	/* Number of sectors (if sectors == 0) */

	/* FAT32 only */
	__u32	fat32_length;	/* Sectors/FAT */
	__u16	flags;		/* Bit 8: fat mirroring, low 4: active fat */
	__u8	version[2];	/* Filesystem version */
	__u32	root_cluster;	/* First cluster in root directory */
	__u16	info_sector;	/* Filesystem info sector */
	__u16	backup_boot;	/* Backup boot sector */
	__u16	reserved2[6];	/* Unused */
} boot_sector;

typedef struct 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, or FAT32 */
	/* Boot code comes next, all but 2 bytes to fill up sector */
	/* Boot sign comes last, 2 bytes */
} volume_info;

typedef struct dir_entry {
	char	name[8],ext[3];	/* Name and extension */
	__u8	attr;		/* Attribute bits */
	__u8	lcase;		/* Case for base and extension */
	__u8	ctime_ms;	/* Creation time, milliseconds */
	__u16	ctime;		/* Creation time */
	__u16	cdate;		/* Creation date */
	__u16	adate;		/* Last access date */
	__u16	starthi;	/* High 16 bits of cluster in FAT32 */
	__u16	time,date,start;/* Time, date and first cluster */
	__u32	size;		/* File size in bytes */
} dir_entry;

typedef struct dir_slot {
151 152 153 154 155 156 157 158
	__u8	id;		/* Sequence number for slot */
	__u8	name0_4[10];	/* First 5 characters in name */
	__u8	attr;		/* Attribute byte */
	__u8	reserved;	/* Unused */
	__u8	alias_checksum;/* Checksum for 8.3 alias */
	__u8	name5_10[12];	/* 6 more characters in name */
	__u16	start;		/* Unused */
	__u8	name11_12[4];	/* Last 2 characters in name */
159 160
} dir_slot;

161 162
/*
 * Private filesystem parameters
163 164 165 166
 *
 * Note: FAT buffer has to be 32 bit aligned
 * (see FAT32 accesses)
 */
167
typedef struct {
168
	__u8	*fatbuf;	/* Current FAT buffer */
169
	int	fatsize;	/* Size of FAT in bits */
170
	__u32	fatlength;	/* Length of FAT in sectors */
171
	__u16	fat_sect;	/* Starting sector of the FAT */
172
	__u32	rootdir_sect;	/* Start sector of root directory */
173
	__u16	sect_size;	/* Size of sectors in bytes */
174
	__u16	clust_size;	/* Size of clusters in sectors */
175
	int	data_begin;	/* The sector of the first cluster, can be negative */
176 177 178 179 180
	int	fatbufnum;	/* Used by get_fatent, init to -1 */
} fsdata;

typedef int	(file_detectfs_func)(void);
typedef int	(file_ls_func)(const char *dir);
181 182
typedef int	(file_read_func)(const char *filename, void *buffer,
				 int maxsize);
183 184

struct filesystem {
185 186 187 188
	file_detectfs_func	*detect;
	file_ls_func		*ls;
	file_read_func		*read;
	const char		name[12];
189 190 191 192 193 194 195 196 197 198 199
};

/* FAT tables */
file_detectfs_func	file_fat_detectfs;
file_ls_func		file_fat_ls;
file_read_func		file_fat_read;

/* Currently this doesn't check if the dir exists or is valid... */
int file_cd(const char *path);
int file_fat_detectfs(void);
int file_fat_ls(const char *dir);
200
int fat_exists(const char *filename);
201
int fat_size(const char *filename, loff_t *size);
202 203 204
int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
		     loff_t maxsize, loff_t *actread);
int file_fat_read(const char *filename, void *buffer, int maxsize);
205
const char *file_getfsname(int idx);
206 207
int fat_set_blk_dev(struct blk_desc *rbdd, disk_partition_t *info);
int fat_register_device(struct blk_desc *dev_desc, int part_no);
208

209 210
int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len,
		   loff_t *actwrite);
211 212
int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
		  loff_t *actread);
213
void fat_close(void);
214
#endif /* _FAT_H_ */