📄 fatfs.cpp
字号:
#include "fatFs.h"
#include <cbio.h>
#include <rtx.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* defines */
/* File System Information Sector number */
#define FSINFO_SEC_NUM 1
/* Offset of free clusters count field in the File System Information Sector */
#define FSINFO_SIGN 484
#define FSINFO_FREE_CLUSTS 488
#define FSINFO_NEXT_FREE 492
#define CLUST_TO_SEC(pVolDesc, clustNum) \
(((clustNum) - DOS_MIN_CLUST) * (pVolDesc)->secPerClust + (pVolDesc)->dataStartSec)
#define SEC_TO_CLUST(pVolDesc, secNum) (((secNum) - (pVolDesc)->dataStartSec) / (pVolDesc)->secPerClust + DOS_MIN_CLUST)
#define DOT "."//本层目录
#define DOTDOT ".."//上一层目录
#define IS_DOT(s) (strcmp(s, DOT) == 0)
#define IS_DOTDOT(s) (strcmp(s, DOTDOT) == 0)
_VOL_DESC volDesc[PART_MAX_ENTRIES];
_FS_DEV fsDev = { 0 };
BOOL fsStart(void)//
{
char mbrSec[BYTES_PER_SEC];
if (cbioRead(0, 0, 1, mbrSec) != NOERROR)
{
TRACE0("ERROR reading device MBR sector\r\n");
return (ERROR);
}
if (mbrSec[510] != 0x55 || mbrSec[511] != 0xaa)/*偏移量为510和511的地方包含标记0XAA55
{
TRACE0("ERROR no signature word at end of boot sector\r\n");
return (ERROR);
}
int idVol = 0;
for (int i = 0; i < 4; i++)
{
_FS_PART_TBL fsPart;
const int nOffset = (i * 16) + DOS_BOOT_PART_TBL;
fsPart.startHead = mbrSec[nOffset + 0x1];
short work = mbrSec[nOffset + 0x2];
fsPart.startSector = work & 0x3f;
fsPart.startCylinder = ((work & 0xC0) << 2) + mbrSec[nOffset + 0x3];
fsPart.type = mbrSec[nOffset + 0x4];
fsPart.endHead = mbrSec[nOffset + 0x5];
work = mbrSec[nOffset + 0x6];
fsPart.endSector = work & 0x3f;
fsPart.endCylinder = ((work & 0xC0) << 2) + mbrSec[nOffset + 0x7];
fsPart.absSector = DISK_TO_LONG(mbrSec + nOffset + 0x8);
fsPart.totalSecs = DISK_TO_LONG(mbrSec + nOffset + 0xc);
if (fsPart.type == 0xb || fsPart.type == 0xc)
// FAT32
{
_VOL_DESC *pVolDesc = &volDesc[idVol];
if (volMount(&fsPart, pVolDesc))
{
pVolDesc->volOk = TRUE;
idVol++;
}
}
}
if (HeapCreate(sizeof(_FIND_DESC), 8, &fsDev.hFind) != NOERROR)
{
TRACE0("ERROR alloc _FIND_DESC\r\n");
return (ERROR);
}
if (HeapCreate(sizeof(_FILE_DESC), DOS_NFILES_DEFAULT, &fsDev.hFile) != NOERROR)
{
TRACE0("ERROR alloc _FILE_DESC\r\n");
return (ERROR);
}
return (NOERROR);
}
BOOL volMount(_FS_PART_TBL *pFs, _VOL_DESC *pVolDesc)//挂载卷
{
char bootSec[BYTES_PER_SEC];
long work;
pVolDesc->volOk = FALSE;
if (cbioRead(0, pFs->absSector, 1, bootSec) != NOERROR)
{
TRACE0("ERROR reading device boot sector\r\n");
return (FALSE);
}
if (bootSec[DOS_BOOT_JMP] != 0xe9 && bootSec[DOS_BOOT_JMP] != 0xeb)
{
TRACE0("ERROR check for both acceptable Intel 80x86 `jmp' opcodes\r\n");
return (FALSE);
}
work = DISK_TO_SHORT(bootSec + DOS_BOOT_BYTES_PER_SEC);
if (work == 0 || work != BYTES_PER_SEC)
{
TRACE0("ERROR bytesPerSec\r\n");
return (FALSE);
}
pVolDesc->bytesPerSec = work;
work = DISK_TO_SHORT(bootSec + DOS_BOOT_NSECTORS);
if (work == 0)
{
work = DISK_TO_LONG(bootSec + DOS_BOOT_LONG_NSECTORS);
if (work == 0)
{
TRACE0("ERROR totalSecs\r\n");
return (FALSE);
}
}
pVolDesc->totalSecs = work;
pVolDesc->secPerClust = bootSec[DOS_BOOT_SEC_PER_CLUST];
if (pVolDesc->secPerClust == 0)
{
TRACE0("ERROR secPerClust\r\n");
return (FALSE);
}
pVolDesc->nFats = bootSec[DOS_BOOT_NFATS];
if (pVolDesc->nFats == 0)
{
TRACE0("ERROR nFats\r\n");
return (FALSE);
}
pVolDesc->nHiddenSecs = DISK_TO_SHORT(bootSec + DOS_BOOT_NHIDDEN_SECS);
/* evaluate the number of reserved sectors */
pVolDesc->nReservedSecs = DISK_TO_SHORT(bootSec + DOS_BOOT_NRESRVD_SECS);
if (pVolDesc->nReservedSecs == 0)
{
TRACE0("ERROR nReservedSecs\r\n");
return (FALSE);
}
/* evaluate the number of sectors alloted to FAT table */
pVolDesc->secPerFat = DISK_TO_SHORT(bootSec + DOS_BOOT_SEC_PER_FAT);
if (pVolDesc->secPerFat != 0)
{
TRACE0("ERROR secPerFat\r\n");
return (FALSE);
}
pVolDesc->fatType = FAT32;
pVolDesc->secPerFat = DISK_TO_LONG(bootSec + DOS32_BOOT_SEC_PER_FAT);
if (pVolDesc->secPerFat == 0)
{
TRACE0("ERROR secPerFat32\r\n");
return (FALSE);
}
pVolDesc->volIdOff = DOS32_BOOT_VOL_ID;
pVolDesc->volLabOff = DOS32_BOOT_VOL_LABEL;
pVolDesc->fatStartSec = pFs->absSector + pVolDesc->nReservedSecs;
pVolDesc->dataStartSec = pFs->absSector + pVolDesc->nReservedSecs + pVolDesc->secPerFat * pVolDesc->nFats;
pVolDesc->dirStartClust = DISK_TO_LONG(bootSec + DOS32_BOOT_ROOT_START_CLUST);
pVolDesc->volId = DISK_TO_LONG(bootSec + pVolDesc->volIdOff);
memcpy(pVolDesc->bootVolLab, bootSec + pVolDesc->volLabOff, DOS_VOL_LABEL_LEN);
*(pVolDesc->bootVolLab + DOS_VOL_LABEL_LEN) = '\0';
pVolDesc->bootSecNum = pFs->absSector;
pVolDesc->volOk = TRUE;
_FAT_DESC *pFat = &pVolDesc->fatDesc;
pFat->buffer = (ULONG *)malloc(BYTES_PER_SEC);
pFat->sector = 0;
return (TRUE);
}
ULONG fatGetNext(_VOL_DESC *pVolDesc, ULONG deNum)
{
_FAT_DESC *pFat = &pVolDesc->fatDesc;
ULONG startSec = pVolDesc->fatStartSec + (deNum * sizeof(ULONG) / BYTES_PER_SEC);
if (startSec != pFat->sector)
{
if (ataRead(0, startSec, 1, pFat->buffer) != NOERROR)
{
TRACE1("ERROR reading fat sector %d\r\n", startSec);
return (ULONG(-1));
}
pFat->sector = startSec;
}
return (pFat->buffer[deNum % (BYTES_PER_SEC / sizeof(ULONG))]);
}
void dirLongName(const char *dirEnt, char *pName)
{
}
void dirShortName(const char *dirEnt, char *pName)
{
const char chNULL = '\0';
const char chWs = ' ';
char szName[DOS_STDNAME_LEN + 1];
char *dst = szName;
const char *src = dirEnt + 0;
for (int i = 0; i < DOS_STDNAME_LEN; i++)
{
char ch = *src++;
if (ch != chWs)
{
*dst++ = ch;
}
else
{
*dst = chNULL;
break;
}
}
*dst = chNULL;
if (IS_DOT(szName) || IS_DOTDOT(szName))
{
strcpy(pName, szName);
return;
}
char szExt[DOS_STDEXT_LEN + 1];
dst = szExt;
src = dirEnt + DOS_STDNAME_LEN;
for (int i = 0; i < DOS_STDEXT_LEN; i++)
{
char ch = *src++;
if (ch != chWs)
{
*dst++ = ch;
}
else
{
*dst = chNULL;
break;
}
}
*dst = chNULL;
strcpy(pName, szName);
if (*szExt != chNULL)
{
strcat(pName, DOT);
strcat(pName, szExt);
}
}
BOOL dirRead(_VOL_DESC *pVolDesc, _DIRENT *pDirEnt, _FILE_DESC *pFd)
{
for (;;)
{
const char chNULL = '\0';
char dirSec[BYTES_PER_SEC];
char shortName[DOS_STDNAME_LEN + DOS_STDEXT_LEN + 2] = { 0 };
char longName[_MAX_PATH] = { 0 };
if (ataRead(0, CLUST_TO_SEC(pVolDesc, pDirEnt->deNum) + pDirEnt->sector, 1, dirSec) != NOERROR)
{
TRACE0("ERROR dirRead\r\n");
return (FALSE);
}
while (pDirEnt->offset < BYTES_PER_SEC / DOS_DIRENT_STD_LEN)
{
char *dirEnt = dirSec + (pDirEnt->offset * DOS_DIRENT_STD_LEN);
pDirEnt->offset++;
DWORD attr = dirEnt[DOS_ATTRIB_OFF];
if (attr == ATTR_VOLUME_ID)
{
TRACE1("ATTR_VOLUME_ID(%08s)\r\n", dirEnt);
continue;
}
const int dirName0 = dirEnt[0];
if (dirName0 == 0)
{
return (FALSE);
}
if (dirName0 == 0xE5)
{
continue;
}
if ((attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME)
{
if (dirName0 & LAST_LONG_ENTRY)
{
longName[0] = chNULL;
}
dirLongName(dirEnt, longName);
}
else
{
dirShortName(dirEnt, shortName);
if (!longName[0])
{
strcpy(longName, shortName);
}
if (pFd != NULL)
{
strcpy(pFd->cFileName, longName);
strcpy(pFd->cAlternateName, shortName);
pFd->attrib = attr;
pFd->size = DISK_TO_LONG(dirEnt + DOS_FILE_SIZE_OFF);
pFd->pos = 0;
pFd->startClust = START_CLUST_DECODE(pVolDesc, dirEnt);
pFd->nSecs = pVolDesc->secPerClust;
pFd->curSec = CLUST_TO_SEC(pVolDesc, pFd->startClust);
}
shortName[0] = chNULL;
longName[0] = chNULL;
return (TRUE);
}
}
pDirEnt->sector++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -