📄 fat_misc.c
字号:
FSysType - ==1 => FAT12
==0 => FAT16
==2 => FAT32
FATSize - Size of one FAT ind sectors.
BytesPerSec - Number of bytes in each sector.
Return value:
>=0 - Link has been made.
<0 - An error has occured.
*/
static int _FS__fat_LinkCluster(int Idx, FS_u32 Unit, FS_i32 *pLastSector, FS_i32 Cluster,
FS_i32 LastClust, unsigned char *pBuffer, int FSysType,
FS_u32 FATSize, FS_i32 BytesPerSec) {
FS_i32 fatindex;
FS_i32 fatoffs;
FS_i32 fatsec;
int lexp;
int err;
int err2;
unsigned char a;
unsigned char b;
#if (FS_FAT_NOFAT32==0)
unsigned char c;
unsigned char d;
#endif
/* Link old last cluster to this one */
if (FSysType == 1) {
fatindex = LastClust + (LastClust / 2); /* FAT12 */
}
else if (FSysType == 2) {
fatindex = LastClust * 4; /* FAT32 */
}
else {
fatindex = LastClust * 2; /* FAT16 */
}
fatsec = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / BytesPerSec);
fatoffs = fatindex % BytesPerSec;
if (fatsec != *pLastSector) {
/*
FAT entry, which has to be modified is not in the same FAT sector, which is
currently in the buffer. So write it to the media now.
*/
err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, *pLastSector, (void*)pBuffer);
err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, *pLastSector + FATSize, (void*)pBuffer);
lexp = (err < 0);
lexp = lexp || (err2 < 0);
if (lexp) {
return -1;
}
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
if (err < 0) {
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
if (err<0) {
return -1;
}
/* Try to repair original FAT sector with contents of copy */
FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
}
*pLastSector = fatsec;
}
a = Cluster & 0xff;
b = (Cluster / 0x100L) & 0xff;
#if (FS_FAT_NOFAT32==0)
c = (Cluster / 0x10000L) & 0xff;
d = (Cluster / 0x1000000L) & 0x0f;
#endif
if (FSysType == 1) {
if (fatoffs == (BytesPerSec - 1)) {
/* Entry in 2 sectors (we have 2nd sector in buffer) */
if (LastClust & 1) {
pBuffer[fatoffs] &= (char)0x0f;
pBuffer[fatoffs] |= (char)((a << 4) & 0xf0);
}
else {
pBuffer[fatoffs] = (char)(a & 0xff);
}
err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
lexp = (err < 0);
lexp = lexp || (err2 < 0);
if (lexp) {
return -1;
}
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)pBuffer);
if (err < 0) {
return -1;
}
*pLastSector = fatsec + 1;
if (LastClust & 1) {
pBuffer[0] = (char)(((a >> 4) & 0x0f) | ((b << 4) & 0xf0));
}
else {
pBuffer[0] &= (char)0xf0;
pBuffer[0] |= (char)(b & 0x0f);
}
err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)pBuffer);
err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec + 1, (void*)pBuffer);
lexp = (err < 0);
lexp = lexp || (err2 < 0);
if (lexp) {
return -1;
}
}
else {
if (LastClust & 1) {
pBuffer[fatoffs] &= (char)0x0f;
pBuffer[fatoffs] |= (char)((a << 4) & 0xf0);
pBuffer[fatoffs + 1] = (char)(((a >> 4) & 0x0f) | ((b << 4) & 0xf0));
}
else {
pBuffer[fatoffs] = (char)(a & 0xff);
pBuffer[fatoffs + 1] &= (char)0xf0;
pBuffer[fatoffs + 1] |= (char)(b & 0x0f);
}
err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
lexp = (err < 0);
lexp = lexp || (err2 < 0);
if (lexp) {
return -1;
}
}
}
#if (FS_FAT_NOFAT32==0)
else if (FSysType == 2) { /* FAT32 */
pBuffer[fatoffs] = a;
pBuffer[fatoffs + 1] = b;
pBuffer[fatoffs + 2] = c;
pBuffer[fatoffs + 3] = d;
err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
lexp = (err < 0) ;
lexp = lexp || (err2 < 0);
if (lexp) {
return -1;
}
}
#endif /* FS_FAT_NOFAT32==0 */
else { /* FAT16 */
pBuffer[fatoffs] = a;
pBuffer[fatoffs + 1] = b;
err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)pBuffer);
err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, FATSize + fatsec, (void*)pBuffer);
lexp = (err < 0);
lexp = lexp || (err2 < 0);
if (lexp) {
return -1;
}
}
return 0;
}
/*********************************************************************
*
* Global functions section
*
**********************************************************************
Functions in this section are used by FAT File System layer only
*/
/*********************************************************************
*
* FS__fat_block_init
*
Description:
FS internal function. Init FAT block memory management.
Parameters:
None.
Return value:
None.
*/
void FS__fat_block_init(void) {
int i;
FS_X_OS_LockMem();
for (i = 0; i < FS_MEMBLOCK_NUM; i++) {
_FS_memblock[i].status = 0;
}
FS_X_OS_UnlockMem();
}
/*********************************************************************
*
* FS__fat_malloc
*
Description:
FS internal function. Allocate a sector buffer.
Parameters:
Size - Size of the sector buffer. Normally this is 512.
Parameter is for future extension.
Return value:
==0 - Cannot allocate a buffer.
!=0 - Address of a buffer.
*/
char *FS__fat_malloc(unsigned int Size) {
int i;
FS_X_OS_LockMem();
if (Size <= FS_FAT_SEC_SIZE) {
for (i = 0; i < FS_MEMBLOCK_NUM; i++) {
if (_FS_memblock[i].status == 0) {
_FS_memblock[i].status = 1;
FS__CLIB_memset((void*)_FS_memblock[i].memory, 0, (FS_size_t)FS_FAT_SEC_SIZE);
FS_X_OS_UnlockMem();
return ((void*)_FS_memblock[i].memory);
}
}
}
FS_X_OS_UnlockMem();
return 0;
}
/*********************************************************************
*
* FS__fat_free
*
Description:
FS internal function. Free sector buffer.
Parameters:
pBuffer - Pointer to a buffer, which has to be set free.
Return value:
None.
*/
void FS__fat_free(void *pBuffer) {
int i;
FS_X_OS_LockMem();
for (i = 0; i < FS_MEMBLOCK_NUM; i++) {
if (((void*)_FS_memblock[i].memory) == pBuffer) {
_FS_memblock[i].status = 0;
FS_X_OS_UnlockMem();
return;
}
}
FS_X_OS_UnlockMem();
}
/*********************************************************************
*
* FS__fat_checkunit
*
Description:
FS internal function. Read Bios-Parameter-Block from a device and
check, if it contains valid data.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
Return value:
==1 - BPB is okay.
==0 - An error has occured.
*/
int FS__fat_checkunit(int Idx, FS_u32 Unit) {
int err;
int status;
int lexp;
status = FS__lb_status(FS__pDevInfo[Idx].devdriver, Unit);
if (status < 0) {
return 0;
}
if (status == FS_LBL_MEDIACHANGED) {
/* Mount new volume */
err = _FS_ReadBPB(Idx, Unit);
if (err < 0) {
return 0;
}
}
if (FS__FAT_aBPBUnit[Idx][Unit].Signature != 0xaa55) {
err = _FS_ReadBPB(Idx, Unit);
lexp = (err < 0);
lexp = lexp || (FS__FAT_aBPBUnit[Idx][Unit].Signature != 0xaa55);
if (lexp) {
return 0;
}
}
if (FS__FAT_aBPBUnit[Idx][Unit].NumFATs != 2) {
return 0; /* Only 2 FATs are supported */
}
if (FS__FAT_aBPBUnit[Idx][Unit].FATSz16 == 0) {
if (FS__FAT_aBPBUnit[Idx][Unit].ExtFlags & 0x0080) {
return 0; /* Only mirroring at runtime supported */
}
}
return 1;
}
/*********************************************************************
*
* FS__fat_which_type
*
Description:
FS internal function. Determine FAT type used on a media. This
function is following the MS specification very closely.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
Return value:
==0 - FAT16.
==1 - FAT12.
==2 - FAT32
*/
int FS__fat_which_type(int Idx, FS_u32 Unit) {
FS_u32 coc;
FS_u32 fatsize;
FS_u32 totsec;
FS_u32 datasec;
FS_u32 bytespersec;
FS_u32 dsize;
bytespersec = (FS_u32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
dsize = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt) * FS_FAT_DENTRY_SIZE) / bytespersec;
fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
if (fatsize == 0) {
fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
}
totsec = (FS_u32)FS__FAT_aBPBUnit[Idx][Unit].TotSec16;
if (totsec == 0) {
totsec = FS__FAT_aBPBUnit[Idx][Unit].TotSec32;
}
datasec = totsec - (FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt +
FS__FAT_aBPBUnit[Idx][Unit].NumFATs * fatsize + dsize);
coc = datasec / FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
if (coc < 4085) {
return 1; /* FAT12 */
}
else if (coc < 65525) {
return 0; /* FAT16 */
}
return 2; /* FAT32 */
}
/*********************************************************************
*
* FS__fat_FAT_find_eof
*
Description:
FS internal function. Find the next EOF mark in the FAT.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
StrtClst - Starting cluster in FAT.
pClstCnt - If not zero, this is a pointer to an FS_u32, which
is used to return the number of clusters found
between StrtClst and the next EOF mark.
Return value:
>=0 - Cluster, which contains the EOF mark.
<0 - An error has occured.
*/
FS_i32 FS__fat_FAT_find_eof(int Idx, FS_u32 Unit, FS_i32 StrtClst, FS_u32 *pClstCnt) {
FS_u32 clstcount;
FS_u32 fatsize;
FS_u32 maxclst;
FS_i32 fatindex;
FS_i32 fatsec;
FS_i32 fatoffs;
FS_i32 lastsec;
FS_i32 curclst;
FS_i32 bytespersec;
FS_i32 eofclst;
int fattype;
int err;
char *buffer;
unsigned char a;
unsigned char b;
#if (FS_FAT_NOFAT32==0)
unsigned char c;
unsigned char d;
#endif /* FS_FAT_NOFAT32==0 */
fattype = FS__fat_which_type(Idx, Unit);
if (fattype == 1) {
maxclst = 4085UL; /* FAT12 */
}
else if (fattype == 2) {
#if (FS_FAT_NOFAT32 == 0)
maxclst = 0x0ffffff0UL; /* FAT32 */
#else
return -1;
#endif /* (FS_FAT_NOFAT32==0) */
}
else {
maxclst = 65525UL; /* FAT16 */
}
buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
if (!buffer) {
return -1;
}
fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
if (fatsize == 0) {
fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
}
bytespersec = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
curclst = StrtClst;
lastsec = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -