📄 fat32.c
字号:
/*
* DSPdap-bootloader - DSP based Digital Audio Player, Bootloader
* Copyright (C) 2004-2007 Roger Quadros <rogerquads @ yahoo . com>
* http://dspdap.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: FAT32.c,v 1.2 2007/06/03 08:54:03 Roger Exp $
*/
#include "FAT32.h"
#include "CF.h"
//----------------FAT fields--------------
//these fields are updated by GetFatFieldsFromVolumeID()
//----------------------------------------
UI32 partition_begin_lba = 0;
FAT FAT32;
//returns an 8-bit word from a byte offset in a given buffer
UI8 Get8BitWord(UI* buffer, int byteOffset)
{
UI8 byte;
UI *wordPtr;
wordPtr = (UI *)&buffer[byteOffset>>1]; //(buffer + byteOffset/2)
if(byteOffset & 1)
{
//odd boundary so byte is in MSB
byte = (*wordPtr)>>8 & 0xFF;
}
else
{
//even boundary so byte is in LSB
byte = (*wordPtr)&0xFF;
}
return byte;
}
//returns a 16-bit word from a byte offset in a given buffer
UI16 Get16BitWord(UI* buffer, int byteOffset)
{
UI16 word;
UI *wordPtr;
wordPtr = (UI *)&buffer[byteOffset>>1]; //(buffer + byteOffset/2)
if(byteOffset & 1)
{
//odd boundary so LSB of word is in given locations MSB
//and MSB of word is in next locations LSB
word = (*wordPtr)>>8 & 0xFF;
word |= (*(wordPtr + 1))<<8 & 0xFF00;
}
else
{
//even boundary so complete word is in given location
word = *wordPtr;
}
return word;
}
//returns a 32-bit word from a byte offset in a given buffer
UI32 Get32BitWord(UI* buffer, int byteOffset)
{
UI32 lword;
UI32 lword2;
UI *wordPtr;
wordPtr = (UI *)&buffer[byteOffset>>1]; //(buffer + byteOffset/2)
if(byteOffset & 1)
{
//odd boundary so LSB of word is in given locations MSB
//2nd LSB of word is in +1 locations LSB
//3rd LSB of word is in +1 locations MSB..and so on
lword = (*wordPtr)>>8 & 0xFF;
lword2 = (*(wordPtr + 1));
lword |= lword2<<8;
lword2 = (*(wordPtr + 2))<<8 & 0xFF00;
lword |= lword2 <<16;
}
else
{
//even boundary
lword = *wordPtr; //LS word
lword2 = (*(wordPtr+1));
lword |= lword2 << 16;
}
return lword;
}
UI32 FAT32_GetStartLBAofCluster(UI32 cluster_num)
{
return (FAT32.cluster_begin_lba + ((cluster_num)-2)*FAT32.sectors_per_cluster);
}
//populates the FAT32 structure fields from Volume ID sector of drive.
int FAT32_GetFAT32Details()
{
UI FAT_buffer[256];
partition_begin_lba = 0; //our partition starts at LBA 0..we have only 1 partition.
if(CF_ReadSector(partition_begin_lba, FAT_buffer))
{
return 1; //FAILED
}
FAT32.bytes_per_sector = Get16BitWord(FAT_buffer, 0xB);
FAT32.sectors_per_cluster = Get8BitWord(FAT_buffer, 0xD);
FAT32.num_reserved_sectors = Get16BitWord(FAT_buffer, 0xE);
FAT32.num_FATs = Get8BitWord(FAT_buffer, 0x10);
FAT32.FAT_size32 = Get32BitWord(FAT_buffer, 0x24);
FAT32.root_begin_cluster = Get32BitWord(FAT_buffer, 0x2C);
FAT32.signature = Get16BitWord(FAT_buffer, 0x1FE);
FAT32.fat_begin_lba = partition_begin_lba + FAT32.num_reserved_sectors;
FAT32.cluster_begin_lba = FAT32.fat_begin_lba + (FAT32.num_FATs * FAT32.FAT_size32);
FAT32.root_dir_lba = FAT32_GetStartLBAofCluster(FAT32.root_begin_cluster);
return 0; //success
}
//Finds the next cluster in the FAT cluster chain from the current cluster and FAT.
//Either returns the next cluster number or -1 (i.e. 0xFFFFFFFF) if
//end of cluster chain. i.e. currentCluster was the last cluster.
//not yet tested
UI32 FAT32_FindNextCluster(UI32 currentCluster)
{
UI FAT_buffer[256];
UI32 FAT_sectorToRead, recordIdx;
UI32 FAT_sector_offset;
UI32 nextCluster;
// Why is '..' labelled with cluster 0 when it should be 2 ??
if(currentCluster==0)
currentCluster=2;
// Find which sector of FAT table to read
//FAT_sectorNumber = ClusterNumber/Cluster Numbers per Sector
// = ClusterNumber/128
//as 1 cluster number = 32-bits = 4 bytes..so there are 128 cluster numbers in 1 sector
FAT_sector_offset = currentCluster / 128;
FAT_sectorToRead = FAT32.fat_begin_lba + FAT_sector_offset;
// Read required FAT sector into buffer
CF_ReadSector(FAT_sectorToRead, FAT_buffer);
// Find 32-bit FAT entry (record) index in current sector relating to cluster number
recordIdx = currentCluster - (FAT_sector_offset * 128);
// Read Next Clusters value from Sector Buffer
nextCluster = Get32BitWord(FAT_buffer, recordIdx*4);
// Mask out MS 4 bits (its 28bit addressing)
nextCluster &= 0x0FFFFFFF;
// If 0x0FFFFFFF then end of cluster chain found
if (nextCluster==0x0FFFFFFF)
return (0xFFFFFFFF);
else
// Else return next cluster
return (nextCluster);
}
//Interprets the short name FAT32 record in buffer and fills the DIR_ENTRY structure
//NOTE: one FAT32 record is of 32 bytes.
void GetDirEntryFromBuffer(UI16* recordBuf, DIR_ENTRY *pDirEntry)
{
//form name
pDirEntry->Name[0] = Get8BitWord(recordBuf, 0);
pDirEntry->Name[1] = Get8BitWord(recordBuf, 1);
pDirEntry->Name[2] = Get8BitWord(recordBuf, 2);
pDirEntry->Name[3] = Get8BitWord(recordBuf, 3);
pDirEntry->Name[4] = Get8BitWord(recordBuf, 4);
pDirEntry->Name[5] = Get8BitWord(recordBuf, 5);
pDirEntry->Name[6] = Get8BitWord(recordBuf, 6);
pDirEntry->Name[7] = Get8BitWord(recordBuf, 7);
pDirEntry->Name[8] = Get8BitWord(recordBuf, 8);
pDirEntry->Name[9] = Get8BitWord(recordBuf, 9);
pDirEntry->Name[10] = Get8BitWord(recordBuf, 10);
pDirEntry->Name[11] = 0;
pDirEntry->Attr = Get8BitWord(recordBuf, 11);
pDirEntry->NTRes = Get8BitWord(recordBuf, 12);
pDirEntry->CreTimeTenth = Get8BitWord(recordBuf, 13);
pDirEntry->CreTime = Get16BitWord(recordBuf, 14);
pDirEntry->CreDate = Get16BitWord(recordBuf, 16);
pDirEntry->LastAccessDate = Get16BitWord(recordBuf, 18);
//form first cluster
pDirEntry->FirstCluster = Get16BitWord(recordBuf, 20);
pDirEntry->FirstCluster = (pDirEntry->FirstCluster<<16) | (Get16BitWord(recordBuf, 26) & 0xFFFF);
pDirEntry->WriteTime = Get16BitWord(recordBuf, 22);
pDirEntry->WriteDate = Get16BitWord(recordBuf, 24);
pDirEntry->FileSize = Get32BitWord(recordBuf, 28);
}
//Interprets the long name FAT32 record in buffer and fills the
//LFN_ENTRY structure
//NOTE: one FAT32 record is of 32 bytes.
void GetLfnEntryFromBuffer(UI16* recordBuf, LFN_ENTRY *pLfn)
{
int i,j;
pLfn->Ordinal = recordBuf[0] & 0xFF;
//copy Name1 into name
for(i=0; i<5; i++)
{
//copy unicode characters.
pLfn->Name[i] = (recordBuf[i] >> 8) | (recordBuf[i+1] & 0xFF);
}
//copy Name2 into name
for(j=7; j<(7+6) ; j++)
{
pLfn->Name[i++] = recordBuf[j];
}
//copy Name3 into name
pLfn->Name[i++] = recordBuf[14];
pLfn->Name[i++] = recordBuf[15];
pLfn->Name[i] = 0; //NULL terminator;
pLfn->Attr = Get8BitWord(recordBuf, 11);
pLfn->Checksum = Get8BitWord(recordBuf, 13);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -