Convert all __u8, __u16, and __u32 types to their u8, u16, u32 equivalents throughout the FAT filesystem code. Series-to: u-boot Series-cc: heinrich Cover-letter: fat: Some code improvements This is an attempt to improve the structure of the FAT code, since it doesn't fully follow the U-Boot conventions: - fat_write.c includes fat.c which is odd - use of __u32 and its ilk - use of typedef - old-style struct comments This series resolves these problems, making it easier to take on other improvements in future. END Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com>
443 lines
12 KiB
C
443 lines
12 KiB
C
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
/*
|
|
* 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
|
|
*/
|
|
|
|
#ifndef _FAT_H_
|
|
#define _FAT_H_
|
|
|
|
#include <fs_legacy.h>
|
|
#include <asm/byteorder.h>
|
|
#include <asm/cache.h>
|
|
|
|
struct disk_partition;
|
|
|
|
/* 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 */
|
|
#define PREFETCH_BLOCKS 2
|
|
|
|
#define MAX_CLUSTSIZE CONFIG_FS_FAT_MAX_CLUSTSIZE
|
|
|
|
#define DIRENTSPERCLUST ((mydata->clust_size * mydata->sect_size) / \
|
|
sizeof(dir_entry))
|
|
|
|
#define FATBUFBLOCKS 6
|
|
#define FATBUFSIZE (mydata->sect_size * FATBUFBLOCKS)
|
|
#define FAT12BUFSIZE ((FATBUFSIZE*2)/3)
|
|
#define FAT16BUFSIZE (FATBUFSIZE/2)
|
|
#define FAT32BUFSIZE (FATBUFSIZE/4)
|
|
|
|
/* Maximum number of entry for long file name according to spec */
|
|
#define MAX_LFN_SLOT 20
|
|
|
|
/* 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_VFAT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
|
|
|
|
#define DELETED_FLAG ((char)0xe5) /* Marks deleted files when in name[0] */
|
|
#define aRING 0x05 /* Used as special character in name[0] */
|
|
|
|
/*
|
|
* Indicates that the entry is the last long entry in a set of long
|
|
* dir entries
|
|
*/
|
|
#define LAST_LONG_ENTRY_MASK 0x40
|
|
|
|
#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 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))
|
|
|
|
/**
|
|
* struct boot_sector - FAT boot sector structure
|
|
* @ignored: bootstrap code (first 3 bytes)
|
|
* @system_id: name of filesystem (8 bytes)
|
|
* @sector_size: bytes per sector
|
|
* @cluster_size: sectors per cluster
|
|
* @reserved: number of reserved sectors
|
|
* @fats: number of FAT copies
|
|
* @dir_entries: number of root directory entries
|
|
* @sectors: number of sectors (for small disks)
|
|
* @media: media descriptor code
|
|
* @fat_length: sectors per FAT (for FAT12/16)
|
|
* @secs_track: sectors per track
|
|
* @heads: number of heads
|
|
* @hidden: number of hidden sectors
|
|
* @total_sect: total number of sectors (for larger disks)
|
|
* @fat32_length: sectors per FAT (FAT32 only)
|
|
* @flags: flags (bit 8: fat mirroring, low 4: active fat)
|
|
* @version: filesystem version (FAT32 only)
|
|
* @root_cluster: first cluster of root directory (FAT32 only)
|
|
* @info_sector: filesystem info sector (FAT32 only)
|
|
* @backup_boot: backup boot sector location (FAT32 only)
|
|
* @reserved2: unused (FAT32 only)
|
|
*/
|
|
struct boot_sector {
|
|
u8 ignored[3];
|
|
char system_id[8];
|
|
u8 sector_size[2];
|
|
u8 cluster_size;
|
|
u16 reserved;
|
|
u8 fats;
|
|
u8 dir_entries[2];
|
|
u8 sectors[2];
|
|
u8 media;
|
|
u16 fat_length;
|
|
u16 secs_track;
|
|
u16 heads;
|
|
u32 hidden;
|
|
u32 total_sect;
|
|
|
|
/* FAT32 only */
|
|
u32 fat32_length;
|
|
u16 flags;
|
|
u8 version[2];
|
|
u32 root_cluster;
|
|
u16 info_sector;
|
|
u16 backup_boot;
|
|
u16 reserved2[6];
|
|
};
|
|
|
|
/**
|
|
* struct volume_info - FAT volume information structure
|
|
* @drive_number: BIOS drive number
|
|
* @reserved: unused field
|
|
* @ext_boot_sign: extended boot signature (0x29 if fields below exist)
|
|
* @volume_id: volume serial number (4 bytes)
|
|
* @volume_label: volume label (11 bytes, padded with spaces)
|
|
* @fs_type: filesystem type string (typically "FAT12", "FAT16", or "FAT32")
|
|
*
|
|
* This structure is part of the boot sector, located after the common fields.
|
|
* Boot code follows this structure, with boot signature at the end of sector.
|
|
*/
|
|
struct volume_info {
|
|
u8 drive_number;
|
|
u8 reserved;
|
|
u8 ext_boot_sign;
|
|
u8 volume_id[4];
|
|
char volume_label[11];
|
|
char fs_type[8];
|
|
};
|
|
|
|
/* see dir_entry::lcase: */
|
|
#define CASE_LOWER_BASE 8 /* base (name) is lower case */
|
|
#define CASE_LOWER_EXT 16 /* extension is lower case */
|
|
|
|
/**
|
|
* struct nameext - 8.3 filename components
|
|
* @name: filename (8 bytes)
|
|
* @ext: extension (3 bytes)
|
|
*/
|
|
struct nameext {
|
|
char name[8];
|
|
char ext[3];
|
|
};
|
|
|
|
/**
|
|
* struct dir_entry - FAT directory entry
|
|
* @nameext: filename and extension (8.3 format)
|
|
* @attr: file attributes (ATTR_* flags)
|
|
* @lcase: case flags for name and extension (CASE_LOWER_* flags)
|
|
* @ctime_ms: creation time (milliseconds)
|
|
* @ctime: creation time (hours, minutes, seconds)
|
|
* @cdate: creation date
|
|
* @adate: last access date
|
|
* @starthi: high 16 bits of cluster number (FAT32 only)
|
|
* @time: modification time
|
|
* @date: modification date
|
|
* @start: low 16 bits of cluster number
|
|
* @size: file size in bytes
|
|
*/
|
|
struct dir_entry {
|
|
struct nameext nameext;
|
|
u8 attr;
|
|
u8 lcase;
|
|
u8 ctime_ms;
|
|
u16 ctime;
|
|
u16 cdate;
|
|
u16 adate;
|
|
u16 starthi;
|
|
u16 time;
|
|
u16 date;
|
|
u16 start;
|
|
u32 size;
|
|
};
|
|
|
|
/**
|
|
* struct dir_slot - VFAT long filename entry
|
|
* @id: sequence number (bit 6 = last entry, bits 0-4 = sequence)
|
|
* @name0_4: characters 0-4 of long filename (UTF-16LE)
|
|
* @attr: must be ATTR_VFAT (0x0F)
|
|
* @reserved: unused field
|
|
* @alias_checksum: checksum of 8.3 alias for this long name
|
|
* @name5_10: characters 5-10 of long filename (UTF-16LE)
|
|
* @start: unused (always 0)
|
|
* @name11_12: characters 11-12 of long filename (UTF-16LE)
|
|
*
|
|
* Long filename entries precede the corresponding short entry in directory.
|
|
* Multiple entries may be used to store names longer than 13 characters.
|
|
*/
|
|
struct dir_slot {
|
|
u8 id;
|
|
u8 name0_4[10];
|
|
u8 attr;
|
|
u8 reserved;
|
|
u8 alias_checksum;
|
|
u8 name5_10[12];
|
|
u16 start;
|
|
u8 name11_12[4];
|
|
};
|
|
|
|
/**
|
|
* struct fsdata - FAT filesystem instance data
|
|
* @fatbuf: buffer for reading/writing FAT (must be 32-bit aligned for FAT32)
|
|
* @fatsize: size of FAT in bits (12, 16, or 32)
|
|
* @fatlength: length of FAT in sectors
|
|
* @fat_sect: starting sector of the FAT
|
|
* @fat_dirty: flag indicating if fatbuf has been modified
|
|
* @rootdir_sect: starting sector of root directory
|
|
* @sect_size: size of sectors in bytes
|
|
* @clust_size: size of clusters in sectors
|
|
* @data_begin: sector offset of first data cluster (can be negative)
|
|
* @fatbufnum: currently buffered FAT sector number (init to -1)
|
|
* @rootdir_size: size of root directory in entries (for non-FAT32)
|
|
* @root_cluster: first cluster of root directory (FAT32 only)
|
|
* @total_sect: total number of sectors
|
|
* @fats: number of FAT copies
|
|
*
|
|
* This structure holds the runtime state of a mounted FAT filesystem.
|
|
* The fatbuf must be 32-bit aligned due to FAT32 sector access requirements.
|
|
*/
|
|
struct fsdata {
|
|
u8 *fatbuf;
|
|
int fatsize;
|
|
u32 fatlength;
|
|
u16 fat_sect;
|
|
u8 fat_dirty;
|
|
u32 rootdir_sect;
|
|
u16 sect_size;
|
|
u16 clust_size;
|
|
int data_begin;
|
|
int fatbufnum;
|
|
int rootdir_size;
|
|
u32 root_cluster;
|
|
u32 total_sect;
|
|
int fats;
|
|
};
|
|
|
|
struct fat_itr;
|
|
|
|
/**
|
|
* clust_to_sect() - convert cluster number to sector number
|
|
* @fsdata: filesystem instance data
|
|
* @clust: cluster number
|
|
*
|
|
* Return: sector number corresponding to the given cluster
|
|
*/
|
|
static inline u32 clust_to_sect(struct fsdata *fsdata, u32 clust)
|
|
{
|
|
return fsdata->data_begin + clust * fsdata->clust_size;
|
|
}
|
|
|
|
/**
|
|
* sect_to_clust() - convert sector number to cluster number
|
|
* @fsdata: filesystem instance data
|
|
* @sect: sector number
|
|
*
|
|
* Return: cluster number corresponding to the given sector
|
|
*/
|
|
static inline u32 sect_to_clust(struct fsdata *fsdata, int sect)
|
|
{
|
|
return (sect - fsdata->data_begin) / fsdata->clust_size;
|
|
}
|
|
|
|
/**
|
|
* file_fat_detectfs() - detect and initialize the FAT filesystem
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int file_fat_detectfs(void);
|
|
|
|
/**
|
|
* fat_exists() - check if a file exists
|
|
* @filename: full path to file
|
|
*
|
|
* Return: 0 if file exists, -1 if not found or error
|
|
*/
|
|
int fat_exists(const char *filename);
|
|
|
|
/**
|
|
* fat_size() - get the size of a file
|
|
* @filename: full path to file
|
|
* @size: pointer to store file size
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_size(const char *filename, loff_t *size);
|
|
|
|
/**
|
|
* file_fat_read() - read a file from FAT filesystem
|
|
* @filename: full path to file
|
|
* @buffer: buffer to read data into
|
|
* @maxsize: maximum number of bytes to read
|
|
*
|
|
* Return: number of bytes read, -1 on error
|
|
*/
|
|
int file_fat_read(const char *filename, void *buffer, int maxsize);
|
|
|
|
/**
|
|
* fat_set_blk_dev() - set the block device and partition for FAT operations
|
|
* @rbdd: block device descriptor
|
|
* @info: partition information
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info);
|
|
|
|
/**
|
|
* fat_register_device() - register a FAT filesystem on a block device
|
|
* @dev_desc: block device descriptor
|
|
* @part_no: partition number (0 = whole device)
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_register_device(struct blk_desc *dev_desc, int part_no);
|
|
|
|
/**
|
|
* file_fat_write() - write to a file on FAT filesystem
|
|
* @filename: full path to file
|
|
* @buf: buffer containing data to write
|
|
* @offset: offset in file to start writing
|
|
* @len: number of bytes to write
|
|
* @actwrite: pointer to store actual number of bytes written
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len,
|
|
loff_t *actwrite);
|
|
|
|
/**
|
|
* fat_read_file() - read from a file on FAT filesystem
|
|
* @filename: full path to file
|
|
* @buf: buffer to read data into
|
|
* @offset: offset in file to start reading
|
|
* @len: number of bytes to read
|
|
* @actread: pointer to store actual number of bytes read
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
|
|
loff_t *actread);
|
|
|
|
/**
|
|
* fat_opendir() - open a directory for reading
|
|
* @filename: full path to directory
|
|
* @dirsp: pointer to store directory stream handle
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_opendir(const char *filename, struct fs_dir_stream **dirsp);
|
|
|
|
/**
|
|
* fat_readdir() - read next entry from directory
|
|
* @dirs: directory stream handle
|
|
* @dentp: pointer to store directory entry
|
|
*
|
|
* Return: 0 on success, -1 on error or end of directory
|
|
*/
|
|
int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
|
|
|
|
/**
|
|
* fat_closedir() - close a directory stream
|
|
* @dirs: directory stream handle
|
|
*/
|
|
void fat_closedir(struct fs_dir_stream *dirs);
|
|
|
|
/**
|
|
* fat_unlink() - delete a file or empty directory
|
|
* @filename: full path to file or directory
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_unlink(const char *filename);
|
|
|
|
/**
|
|
* fat_rename() - rename a file or directory
|
|
* @old_path: current full path
|
|
* @new_path: new full path
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_rename(const char *old_path, const char *new_path);
|
|
|
|
/**
|
|
* fat_mkdir() - create a directory
|
|
* @dirname: full path to new directory
|
|
*
|
|
* Return: 0 on success, -1 on error
|
|
*/
|
|
int fat_mkdir(const char *dirname);
|
|
|
|
/**
|
|
* fat_close() - close FAT filesystem and release resources
|
|
*/
|
|
void fat_close(void);
|
|
|
|
/**
|
|
* fat_next_cluster() - get the next cluster in a chain
|
|
* @itr: directory iterator
|
|
* @nbytes: pointer to store number of bytes in cluster
|
|
*
|
|
* Return: pointer to cluster data buffer
|
|
*/
|
|
void *fat_next_cluster(struct fat_itr *itr, unsigned int *nbytes);
|
|
|
|
/**
|
|
* fat_uuid() - get FAT volume ID
|
|
*
|
|
* The FAT volume ID returned in @uuid_str as hexadecimal number in XXXX-XXXX
|
|
* format.
|
|
*
|
|
* @uuid_str: caller allocated buffer of at least 10 bytes for the volume ID
|
|
* Return: 0 on success
|
|
*/
|
|
int fat_uuid(char *uuid_str);
|
|
|
|
#endif /* _FAT_H_ */
|