📄 fatfs.c
字号:
#include <avt.h>
#include "Defs.h"
#include "44b0x.h"
#include "usb.h"
#include "sl811.h"
//
// 最多打开文件数
//
#define FILE_MAX 8
//
// 文件标志
//
#define F_EOF 0x1 // 文件结束标志
#define F_OPEN 0x2 // 文件已打开标志
#define F_MODIF 0x4 // 文件内容被修改标志
#define F_SZCHG 0x8 // 文件大小被修改标志
#define F_SHARE 0x10 // 文件被共享
//
// 文件类型(FAT系统相关)
//
#define ATTR_NORMAL 0x00
#define ATTR_READONLY 0x01 // 只读文件
#define ATTR_HIDDEN 0x02 // 隐藏文件
#define ATTR_SYSTEM 0x04 // 系统文件
#define ATTR_VOLUMENAME 0x08 // 卷标
#define ATTR_DIRECTORY 0x10 // 目录
#define ATTR_ARCHIVE 0x20 // 普通文件
#define ATTR_LONG_NAME (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMENAME)
//
// FAT特殊值
//
#define FAT_FREE 0x0000
// 文件标志(调试用)
#define FILE_MAGIC 0xDEEDFEE1
//
// 分区表项
//
typedef __packed struct {
UCHAR BootIndicator; // 是否可引导
UCHAR StartHead; // 起始磁头
UCHAR StartSector; // 起始扇区
UCHAR StartCylinder; // 起始柱面
UCHAR SystemIndicator;// 文件系统类型
UCHAR EndHead; // 结束磁头
UCHAR EndSector; // 结束扇区
UCHAR EndCylinder; // 结束柱面
ULONG SectorCountBeforePartition;//分区起始扇区
ULONG PartitionSectorCount; // 分区扇区数
} PART_ENTRY;
//
// FAT12/16/32文件系统结构
//
typedef __packed struct {
UCHAR JumpBoot[3]; // Jump instruction to boot code
UCHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
USHORT BytesPerSector; // Bytes per sector
UCHAR SectorsPerCluster;// Number of sectors in a cluster
USHORT ReservedSectors;// Reserved sectors, usually 1 (the bootsector)
UCHAR NumberOfFats; // Number of FAT tables
USHORT RootDirEntries; // Number of root directory entries (fat12/16)
USHORT TotalSectors; // Number of total sectors on the drive, 16-bit
UCHAR MediaDescriptor;// Media descriptor byte
USHORT SectorsPerFat; // Sectors per FAT table (fat12/16)
USHORT SectorsPerTrack;// Number of sectors in a track
USHORT NumberOfHeads; // Number of heads on the disk
ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
ULONG TotalSectorsBig;// This field is the new 32-bit total count of sectors on the volume
ULONG SectorsPerFatBig;// This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
USHORT ExtendedFlags; // Extended flags (fat32)
USHORT FileSystemVersion;// File system version (fat32)
ULONG RootDirStartCluster;// Starting cluster of the root directory (fat32)
USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
USHORT BackupBootSector;// If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6.
UCHAR Reserved[12]; // Reserved for future expansion
UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80)
UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
ULONG VolumeSerialNumber;// Volume serial number
UCHAR VolumeLabel[11];// Volume label. This field matches the 11-byte volume label recorded in the root directory
UCHAR FileSystemType[8];// Always set to the string "FAT32 "
UCHAR BootCodeAndData[420];// The remainder of the boot sector
UCHAR BootSectorMagic[2];// 0xAA55
} BOOTSECTOR;
//
// 主引导扇区结构
//
typedef __packed struct {
UCHAR Misc[0x1be];
PART_ENTRY List[4]; // 分区表项
UCHAR BootSectorMagic[2]; // 0xAA55
} MBR;
/*
* FAT文件目录项
*/
typedef __packed struct {
char FileName[11]; /* 文件名 */
UCHAR Attr; /* 文件属性 */
UCHAR ReservedNT; /* 保留 */
UCHAR TimeInTenths; /* 文件创建时间世纪 */
USHORT CreateTime; /* 文件创建时间 */
USHORT CreateDate; /* 文件创建日期 */
USHORT LastAccessDate; /* 文件访问时间 */
USHORT ClusterHigh; /* 文件第一个簇的高16位 */
USHORT Time; /* 文件修改时间 */
USHORT Date; /* 文件创建日期 */
USHORT ClusterLow; /* 文件第一个簇的低16位 */
ULONG Size; /* 文件大小 */
} DIRENTRY;
//
// 文件结构(自定义)
//
typedef struct _FILE {
char Name[12];// 文件名
DRIVE *Drive; // 驱动器
ULONG Size; // 文件大小
int Blks; // 文件簇数
int Blk; // 文件当前簇
ULONG Pos; // 文件读写位置
ULONG Flags; // 文件标志
ULONG Time; // 文件时间
CLNO Start; // 起始簇号
CLNO *Clus; // 簇数组
UCHAR *Buffer;// 簇缓冲区
ULONG DEOffst;// 文件目录项扇区内偏移
ULONG DESt; // 文件目录项扇区
UINT Ref; // 文件引用计数
UINT sm; // 文件访问信号量
UINT Magic; // 标志
struct _FILE *sf; // 共享文件
} FATFILE;
//
// 打开文件数组
//
static FATFILE Files[FILE_MAX];
static int FlushBuffer(FATFILE *);
static int FillBuffer(FATFILE *f, UINT lblk, int New);
UINT mylog2(ULONG x);
ULONG mktime(USHORT year, USHORT mon, USHORT day, USHORT hour, USHORT min, USHORT sec);
//void WriteFileCallback(int fd, UINT pos);
// 簇号转换为扇区号
#define Clus2Sect(d, c) d->DataStart + ((c - 2) << d->SectorsPerClusterShift)
// 锁驱动器(调试用)
void
LockDrive(DRIVE *d) {
CHECK_PTR(d);
CHECK_PTR(d->sm);
//sm_p(d->sm, FOREVER);
}
// 解锁驱动器(调试用)
void
UnlockDrive(DRIVE *d) {
CHECK_PTR(d);
CHECK_PTR(d->sm);
//sm_v(d->sm);
}
// 读簇
//
// d: 驱动器
// st: 簇起始扇区
// buf: 数据指针
//
static int
ReadCluster(DRIVE *d, ULONG st, UCHAR *buf) {
UINT i;
int rc = TRUE;
CHECK_PTR(d);
CHECK_PTR(buf);
ASSERT(st < d->Sectors);
LockDrive(d);
//if(d->ms != NULL)
// DBG1("ReadCluster(%u)...\n", st);
// 每簇扇区数:1,2,4,8,16...
for(i = 0; i < d->SectorsPerCluster; i++) {
if(!(*d->ReadSector)(d, st, buf)) {
rc = FALSE;
break;
}
st++;
buf += d->BytesPerSector;
}
UnlockDrive(d);
return rc;
}
// 写簇
//
// d: 驱动器
// st: 簇起始扇区
// buf: 数据指针
static int
WriteCluster(DRIVE *d, ULONG st, UCHAR *buf) {
UINT i;
int rc = TRUE;
CHECK_PTR(d);
CHECK_PTR(buf);
ASSERT(st < d->Sectors);
LockDrive(d);
//if(d->ms != NULL)
// DBG1("WriteCluster(%u)...\n", st);
// 每簇扇区数:1,2,4,8,16...
for(i = 0; i < d->SectorsPerCluster; i++) {
if(!(*d->WriteSector)(d, st, buf)) {
rc = FALSE;
break;
}
st++;
buf += d->BytesPerSector;
}
UnlockDrive(d);
return rc;
}
// 获取某簇的下一簇
//
// d: 驱动器
// cl: 簇号
//
static CLNO
GetNextCluster(DRIVE *d, CLNO cl) {
UCHAR *b;
ULONG off;
UINT st;
CLNO rc = 0xFFFFFFFF;
CHECK_PTR(d);
ASSERT(cl < d->NumClusters);
//if(d->ms != NULL)
// DBG1("GetNextCluster(%u)...\n", cl);
LockDrive(d);
// 每个FAT项大小
// FAT32: 4字节
// FAT16: 2字节
//
off = cl * (d->Fat32 ? 4 : 2);
st = off / 512;
if(st != d->fatst) {
// FAT缓冲失败
d->fatst = st;
if(!(*d->ReadSector)(d, d->Fat1 + st, d->fatbuf))
goto ret;
}
// 下一个簇的簇号
b = d->fatbuf + (off & 511);
if(d->Fat32)
rc = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
else
rc = (b[1] << 8) | b[0];
ret:
UnlockDrive(d);
return rc;
}
// 设置某簇的下一簇
//
// d: 驱动器
// cl: 簇号
// val: 下一簇的簇号
//
static int
SetNextCluster(DRIVE *d, CLNO cl, CLNO val) {
UCHAR *b;
ULONG off;
UCHAR *fatbuf;
int rc;
CHECK_PTR(d);
ASSERT(cl < d->NumClusters);
LockDrive(d);
fatbuf = d->fatbuf;
// 每个FAT项大小
// FAT32: 4字节
// FAT16: 2字节
//
off = cl * (d->Fat32 ? 4 : 2);
d->fatst = off / 512;
//if(d->ms != NULL)
// DBG2("SetNextCluster(%u, %u)@", (UINT)cl, (UINT)val);
//if(d->ms != NULL)
// DBG3("%u, FAT1: %u, FAT2:%u\n", d->fatst, d->Fat1, d->Fat2);
if(!(*d->ReadSector)(d, d->Fat1 + d->fatst, fatbuf)) {
DBG("ReadSector FAILED!\n");
rc = FALSE;
goto ret;
}
// 下一个簇的簇号
b = fatbuf + (off & 511);
if(d->Fat32) {
//
// FAT32文件系统
//
b[0] = val;
b[1] = val >> 8;
b[2] = val >> 16;
b[3] = val >> 24;
if(!(*d->WriteSector)(d, d->Fat1 + d->fatst, fatbuf)) {
DBG("WriteSector FAILED!\n");
rc = FALSE;
goto ret;
}
// 更新FAT2
if(d->Fat2 != 0) {
//DBG1("Rewrite FAT2(%u)...\n", d->Fat2 + d->fatst);
if(!(*d->ReadSector)(d, d->Fat2 + d->fatst, fatbuf)) {
DBG("ReadSector FAILED!\n");
rc = FALSE;
goto ret;
}
b[0] = val;
b[1] = val >> 8;
b[2] = val >> 16;
b[3] = val >> 24;
if(!(*d->WriteSector)(d, d->Fat2 + d->fatst, fatbuf)) {
DBG("WriteSector FAILED!\n");
rc = FALSE;
goto ret;
}
}
}
else {
//
// FAT16文件系统
//
b[0] = val;
b[1] = val >> 8;
if(!(*d->WriteSector)(d, d->Fat1 + d->fatst, fatbuf)) {
DBG("WriteSector FAILED!\n");
rc = FALSE;
goto ret;
}
// 更新FAT2
if(d->Fat2 != 0) {
//DBG1("Rewrite FAT2(%u)...\n", d->Fat2 + d->fatst);
if(!(*d->ReadSector)(d, d->Fat2 + d->fatst, fatbuf)) {
DBG("ReadSector FAILED!\n");
rc = FALSE;
goto ret;
}
b[0] = val;
b[1] = val >> 8;
if(!(*d->WriteSector)(d, d->Fat2 + d->fatst, fatbuf)) {
DBG("WriteSector FAILED!\n");
rc = FALSE;
goto ret;
}
}
}
rc = TRUE;
ret:
UnlockDrive(d);
return rc;
}
//
// 分配簇
//
// drv: 驱动器
// nr: 簇数
// arr: 簇数组
//
static int
AllocCluster(DRIVE *drv, int nr, CLNO *arr) {
CLNO new, c, i;
CHECK_PTR(drv);
CHECK_PTR(arr);
i = 0;
for(c = drv->fatgoal; c < drv->NumClusters; c++) {
new = GetNextCluster(drv, c);
// 磁盘满
if(new == 0xFFFFFFFF)
return 0;
// 簇空闲
if(new == FAT_FREE) {
arr[i++] = c;
if(i == nr) {
drv->fatgoal = c + 1;
return 1; // OK!
}
}
}
drv->fatgoal = c;
return 0; // DISK FULL
}
// 字符大写
static __inline char
UPPER(char c) {
return c >= 'a' && c <= 'z' ? c ^ 0x20 : c;
}
// 文件名转换成8.3格式
//
// in: 输入参数
// out: 输出参数
//
// 例如:
//
// foo.bar --> "FOO BAR"
//
static void
Convert (const char * in, char * out) {
int len;
char * str = out;
for(len = 0; len < 8 && *in && *in != '.'; len++)
*str++ = UPPER(*in++);
for(; len < 8; len++)
*str++ = ' ';
if(*in == '.') in++;
for(; *in && len < 11; len++)
*str++ = UPPER(*in++);
for(; len < 11; len++)
*str++ = ' ';
*str = '\0';
}
//
// 分配一个文件结构
//
static int
allocf(void) {
int i;
int psw;
psw = interrupts_disable();
for(i = 0; i < FILE_MAX; i++)
if(!Files[i].Drive)
break;
interrupts_enable(psw);
return i == FILE_MAX ? -1 : i;
}
//
// 取得当前时间
//
ULONG
GetTm(void) {
//struct tm t;
//GetTime(&t);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -