📄 fat.c
字号:
return E_FILE_PATH;
}
if ((entry.attrib & FA_VOLUME) != 0) {
return E_FILE_PATH; /* not file/directory attribution */
}
if (finfo != NULL) {
EntryToInfo(&entry, finfo);
}
return E_FILE_OK;
}
/*-----------------------------------------------------------------------------*/
int FATGetDriveInfo(UCHAR driveNum, DRIVE_INFO *drvInfo)
{
FATDRIVE_RES *drive;
if (driveNum >= FAT_DRIVE_MAX) {
return E_FILE_DRIVE;
}
drive= &fatDriveRes[driveNum];
if (drive->ready_flag == 0) { /* drive not ready */
return E_FILE_NOT_READY;
}
if (drvInfo != NULL) {
drvInfo->sectorSize = SECTOR_SIZE;
drvInfo->sectorPerClu = drive->sectorPerClu;
GetTotalFreeClu(driveNum, &(drvInfo->freeClu));
drvInfo->totalClu = drive->totalSector;
}
return E_FILE_OK;
}
/*-----------------------------------------------------------------------------*/
int FATChdir(UCHAR driveNum, const UCHAR *path)
{
FATDRIVE_RES *drive;
USHORT cluster;
if (driveNum >= FAT_DRIVE_MAX) {
return E_FILE_DRIVE;
}
drive= &fatDriveRes[driveNum];
if (drive->ready_flag == 0) { /* drive not ready */
return E_FILE_NOT_READY;
}
if (PathUpper(path, workPath, PATH_LEN_MAX) < 0) {
return E_FILE_PATH_LEN;
}
if (workPath[0] != '\\') { /* relative path */
if (strlen((char*)drive->currPath) + strlen((char*)workPath) > PATH_LEN_MAX-1) { /* -1 for '\' */
return E_FILE_PATH_LEN;
}
}
/* Check path */
if (SearchPath(driveNum, workPath, &cluster) < 0) {
return E_FILE_PATH;
}
if (drive->currClu != cluster) {
drive->currClu = cluster;
ChangePath(workPath, drive->currPath);
}
return E_FILE_OK;
}
/*-----------------------------------------------------------------------------*/
int FATCwd(UCHAR driveNum, UCHAR **path)
{
FATDRIVE_RES *drive;
if (driveNum >= FAT_DRIVE_MAX) {
return E_FILE_DRIVE;
}
drive= &fatDriveRes[driveNum];
if (drive->ready_flag == 0) { /* drive not ready */
return E_FILE_NOT_READY;
}
*path = drive->currPath;
return E_FILE_OK;
}
/********************************************************************************
LOCAL FUNCTIONS
********************************************************************************/
/*-----------------------------------------------------------------------------*/
int DriveInit(UCHAR driveNum)
{
int ret;
FATDRIVE_RES *drive;
BOOT_INFO *boot;
ULONG systemSector;
drive = &fatDriveRes[driveNum];
ret = driverAPI[driveNum].init();
if (ret != 0) {
drive->ready_flag = 0;
return E_FILE_NOT_READY;
}
ret = driverAPI[driveNum].read(0, 1, workBuffer); /* read logical sector 0 */
if (ret != 0) {
drive->ready_flag = 0;
return E_FILE_NOT_READY;
}
if (workBuffer[0x1FE] == 0x55 && workBuffer[0x1FF] == 0xAA) {
/* Harddisk type */
drive->bootSector = GET_ULONG(ulong(workBuffer[0x1C6]));
driverAPI[driveNum].read(drive->bootSector, 1, workBuffer);
}
else {
/* Floppy type */
drive->bootSector = 0;
}
boot = (BOOT_INFO *)workBuffer;
if (!(
(boot->jumpcode[0] == 0xEB || boot->jumpcode[2] == 0x90) ||
boot->jumpcode[0] == 0xE9
))
{
return E_FILE_FORMAT;
}
if (GET_USHORT(boot->bytePerSector) != SECTOR_SIZE) {
return E_FILE_FORMAT;
}
if (GET_USHORT(boot->rootDirEntry) == 0) { /* FAT32 */
return E_FILE_FORMAT;
}
drive->sectorPerClu = boot->sectorPerClu;
drive->numFAT = boot->numFAT;
drive->sectorPerFAT = GET_USHORT(boot->sectorPerFAT);
if (boot->totalSector == 0) {
drive->totalSector = GET_ULONG(boot->bigTotalSector);
}
else {
drive->totalSector = GET_USHORT(boot->totalSector);
}
drive->numRootSector = (GET_USHORT(boot->rootDirEntry)*32)/SECTOR_SIZE;
drive->fatSector = drive->bootSector + GET_USHORT(boot->reservedSector);
drive->rootSector = drive->fatSector + (drive->sectorPerFAT * drive->numFAT);
systemSector = (drive->rootSector - drive->bootSector) + drive->numRootSector;
drive->maxClu = (USHORT)((drive->totalSector - systemSector)/drive->sectorPerClu+TOP_CLUSTER-1);
drive->freeClu = TOP_CLUSTER-1;
if (drive->maxClu > MAX_CLUSTER & 0xFFF) {
drive->fileType = TYPE_FAT16;
}
else {
drive->fileType = TYPE_FAT12;
}
strcpy((char*)drive->currPath, "\\"); // current path = root
drive->currClu = 0;
drive->ready_flag = 1;
driverAPI[driveNum].read(drive->fatSector, 1, workBuffer);
return E_FILE_OK;
}
/*-----------------------------------------------------------------------------*/
static void InitFileRes(void)
{
int i;
for(i = 0; i < FAT_FILE_MAX; i++) {
fatFileRes[i].use_flag = 0;
}
}
/*-----------------------------------------------------------------------------*/
static void InitDriveRes(void)
{
int i;
for(i = 0; i < FAT_DRIVE_MAX; i++) {
fatDriveRes[i].ready_flag = 0;
}
}
/*-----------------------------------------------------------------------------*/
static void InitCache(void)
{
int i;
for(i = 0; i < CFG_CACHE_NUM; i++) {
cacheRes[i].use_flag = 0;
}
useTopList = -1; // empty
}
/*-----------------------------------------------------------------------------*/
static ULONG CluToSector(UCHAR driveNum, USHORT cluster)
{
FATDRIVE_RES *drive;
drive = &fatDriveRes[driveNum];
return (drive->rootSector+drive->numRootSector+(cluster-2)*drive->sectorPerClu);
}
/*-----------------------------------------------------------------------------*/
static int PosToCluster(UCHAR driveNum, ULONG pos, USHORT topClu, USHORT *cluster, USHORT *secOffset)
{
FATDRIVE_RES *drive;
USHORT cluSize, next;
int i, listNum;
drive = &fatDriveRes[driveNum];
cluSize = SECTOR_SIZE * drive->sectorPerClu;
listNum = (int)(pos/cluSize);
*cluster = topClu;
for(i = 0; i < listNum; i++) {
if (NextFATEntry(driveNum, *cluster, &next) != 1) { /* error or end of cluster */
return -1;
}
*cluster = next;
}
*secOffset = (USHORT)((pos % cluSize)/SECTOR_SIZE);
return 0;
}
/*-----------------------------------------------------------------------------*/
static void EntryToInfo(DIR_ENT *entry, FILE_INFO *finfo)
{
finfo->year = (entry->upDate >> 9) + 1980;
finfo->month = (UCHAR)((entry->upDate >> 5) & 0x0F);
finfo->day = (UCHAR)(entry->upDate & 0x1F);
finfo->hour = (UCHAR)(entry->upTime >> 11);
finfo->minute = (UCHAR)((entry->upTime >> 5) & 0x3F);
finfo->second = (UCHAR)((entry->upTime & 0x1F)*2);
finfo->attrib = entry->attrib;
finfo->size = entry->size;
}
/*-----------------------------------------------------------------------------*/
static int ReadFATEntry(UCHAR driveNum, USHORT cluster, USHORT *value)
{
int ret;
if (fatDriveRes[driveNum].fileType == TYPE_FAT12)
ret = _ReadFATEntry12(driveNum, cluster, value);
else // TYPE_FAT16
ret = _ReadFATEntry16(driveNum, cluster, value);
return ret;
}
/*-----------------------------------------------------------------------------*/
static int _ReadFATEntry12(UCHAR driveNum, USHORT cluster, USHORT *value)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
UCHAR out[2];
USHORT offset, secOffset, byteOffset;
int ret;
if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
return -1;
}
offset = cluster*3/2;
secOffset = offset/SECTOR_SIZE;
byteOffset = offset%SECTOR_SIZE;
if (byteOffset == SECTOR_SIZE-1) { /* sector over ? */
ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
out[0] = workBuffer[byteOffset];
ret = ReadSector(driveNum, drive->fatSector+secOffset+1, workBuffer);
out[1] = workBuffer[0];
}
else {
ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
out[0] = workBuffer[byteOffset];
out[1] = workBuffer[byteOffset+1];
}
if (cluster & 0x01) { /* odd number */
*value = ((USHORT)(out[1]) << 4) + (out[0] >> 4);
}
else { /* even */
*value = ((USHORT)(out[1] & 0x0f) << 8) + out[0];
}
return 0;
}
/*-----------------------------------------------------------------------------*/
static int _ReadFATEntry16(UCHAR driveNum, USHORT cluster, USHORT *value)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
USHORT offset, secOffset, byteOffset;
int ret;
if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
return -1;
}
offset = cluster*2;
secOffset = offset/SECTOR_SIZE;
byteOffset = offset%SECTOR_SIZE;
ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
*value = GET_USHORT(ushort(workBuffer[byteOffset]));
return 0;
}
/*-----------------------------------------------------------------------------*/
static int WriteFATEntry(UCHAR driveNum, USHORT cluster, USHORT value)
{
int ret;
if (fatDriveRes[driveNum].fileType == TYPE_FAT12)
ret = _WriteFATEntry12(driveNum, cluster, value & 0xFFF);
else // TYPE_FAT16
ret = _WriteFATEntry16(driveNum, cluster, value);
return ret;
}
/*-----------------------------------------------------------------------------*/
static int _WriteFATEntry12(UCHAR driveNum, USHORT cluster, USHORT value)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
USHORT offset, secOffset, byteOffset;
int ret;
if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
return -1;
}
offset = cluster*3/2;
secOffset = offset/SECTOR_SIZE;
byteOffset = offset%SECTOR_SIZE;
if (byteOffset == SECTOR_SIZE-1) { /* sector over ? */
ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
if (cluster & 0x01) { /* odd number */
workBuffer[byteOffset] = (workBuffer[byteOffset] & 0x0F) + ((UCHAR)value << 4);
}
else { /* even */
workBuffer[byteOffset] = (UCHAR)value;
}
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
secOffset ++;
ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
if (cluster & 0x01) { /* odd number */
workBuffer[0] = (UCHAR)(value >> 4);
}
else { /* even */
workBuffer[0] = (workBuffer[byteOffset+1] & 0xF0) + (UCHAR)(value >> 8);
}
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
}
else {
ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
if (cluster & 0x01) { /* odd number */
workBuffer[byteOffset] = (workBuffer[byteOffset] & 0x0F) + ((UCHAR)value << 4);
workBuffer[byteOffset+1] = (UCHAR)(value >> 4);
}
else { /* even */
workBuffer[byteOffset] = (UCHAR)value;
workBuffer[byteOffset+1] = (workBuffer[byteOffset+1] & 0xF0) + (UCHAR)(value >> 8);
}
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
}
return 0;
}
/*-----------------------------------------------------------------------------*/
static int _WriteFATEntry16(UCHAR driveNum, USHORT cluster, USHORT value)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
USHORT offset, secOffset, byteOffset;
int ret;
if (cluster < TOP_CLUSTER || cluster > drive->maxClu) {
return -1;
}
offset = cluster*2;
secOffset = offset/SECTOR_SIZE;
byteOffset = offset%SECTOR_SIZE;
ret = ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
workBuffer[byteOffset] = (UCHAR)(value & 0xFF);
workBuffer[byteOffset+1] = (UCHAR)(value >> 8);
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
return 0;
}
/*-----------------------------------------------------------------------------*/
/*
Return value
0 : last cluster
1 : exist next cluster
*/
static int NextFATEntry(UCHAR driveNum, USHORT cluster, USHORT *next)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
if (ReadFATEntry(driveNum, cluster, next) < 0) {
return -1;
}
if (drive->fileType == TYPE_FAT12) {
if ((*next & (END_CLUSTER & 0xFFF)) == END_CLUSTER) {
return 0;
}
}
else { /* TYPE_FAT16 */
if ((*next & END_CLUSTER) == END_CLUSTER) {
return 0;
}
}
if (*next >= TOP_CLUSTER || *next <= drive->maxClu) {
return 1;
}
return -1;
}
/*-----------------------------------------------------------------------------*/
static int CopyFATSector(UCHAR driveNum, USHORT secOffset, UCHAR *buf)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i;
ULONG sector;
sector = drive->fatSector+drive->sectorPerFAT+secOffset;
for(i = 1; i < drive->numFAT; i++) {
driverAPI[driveNum].write(sector, 1, buf);
sector += drive->sectorPerFAT;
}
return 0;
}
/*-----------------------------------------------------------------------------*/
static int ReadSector(UCHAR driveNum, ULONG sector, UCHAR *buf)
{
char curr, prev;
int i, flag;
CACHE_RES *cache;
i = 0;
flag = 0;
if (useTopList != -1) {
curr = prev = useTopList;
for(i = 0; i < CFG_CACHE_NUM; i++) {
cache = &cacheRes[curr];
if (cache->drive == driveNum && cache->sector == sector) {
flag = 1;
break;
}
if (cache->next == -1) { // list end ?
break;
}
prev = curr;
curr = cache->next;
}
}
if (flag == 0) { /* not found */
if (i < CFG_CACHE_NUM-1) { // exist blank cache
curr = (char)GetBlankCache();
cache = &cacheRes[curr];
}
else { // cache full
if (cache->write_flag == 1) {
driverAPI[cache->drive].write(cache->sector, 1, cache->buffer);
cache->write_flag = 0;
}
cacheRes[prev].next = -1; // set end-mark
}
driverAPI[driveNum].read(sector, 1, cache->buffer);
cache->drive = driveNum;
cache->sector = sector;
}
memcpy(buf, cache->buffer, SECTOR_SIZE);
cache->next = useTopList;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -