Update fat.c

This commit is contained in:
RocketRobz 2024-03-07 23:06:17 -07:00
parent c96b8e1855
commit 4cabc9d09f

View File

@ -75,12 +75,9 @@ License:
#define __PACKED __attribute__ ((__packed__)) #define __PACKED __attribute__ ((__packed__))
// Boot Sector - must be packed // BIOS Parameter Block
typedef struct typedef struct {
{
u8 jmpBoot[3];
u8 OEMName[8];
// BIOS Parameter Block
u16 bytesPerSector; u16 bytesPerSector;
u8 sectorsPerCluster; u8 sectorsPerCluster;
u16 reservedSectors; u16 reservedSectors;
@ -93,6 +90,14 @@ typedef struct
u16 numHeads; u16 numHeads;
u32 numHiddenSectors; u32 numHiddenSectors;
u32 numSectors; u32 numSectors;
} __PACKED BIOS_BPB;
// Boot Sector - must be packed
typedef struct
{
u8 jmpBoot[3];
u8 OEMName[8];
BIOS_BPB bpb;
union // Different types of extended BIOS Parameter Block for FAT16 and FAT32 union // Different types of extended BIOS Parameter Block for FAT16 and FAT32
{ {
struct struct
@ -106,7 +111,7 @@ typedef struct
u8 fileSysType[8]; u8 fileSysType[8];
// Bootcode // Bootcode
u8 bootCode[448]; u8 bootCode[448];
} fat16; } __PACKED fat16;
struct struct
{ {
// FAT32 extended block // FAT32 extended block
@ -126,13 +131,15 @@ typedef struct
u8 fileSysType[8]; u8 fileSysType[8];
// Bootcode // Bootcode
u8 bootCode[420]; u8 bootCode[420];
} fat32; } __PACKED fat32;
} extBlock; } __PACKED extBlock;
__PACKED u16 bootSig; __PACKED u16 bootSig;
} __PACKED BOOT_SEC; } __PACKED BOOT_SEC;
_Static_assert(sizeof(BOOT_SEC) == 512);
// Directory entry - must be packed // Directory entry - must be packed
typedef struct typedef struct
{ {
@ -251,8 +258,7 @@ u32 FAT_NextCluster(u32 cluster)
// read the nextCluster value // read the nextCluster value
nextCluster = ((u16*)globalBuffer)[offset]; nextCluster = ((u16*)globalBuffer)[offset];
if (nextCluster >= 0xFFF7) if (nextCluster >= 0xFFF7) {
{
nextCluster = CLUSTER_EOF; nextCluster = CLUSTER_EOF;
} }
break; break;
@ -265,8 +271,7 @@ u32 FAT_NextCluster(u32 cluster)
// read the nextCluster value // read the nextCluster value
nextCluster = (((u32*)globalBuffer)[offset]) & 0x0FFFFFFF; nextCluster = (((u32*)globalBuffer)[offset]) & 0x0FFFFFFF;
if (nextCluster >= 0x0FFFFFF7) if (nextCluster >= 0x0FFFFFF7) {
{
nextCluster = CLUSTER_EOF; nextCluster = CLUSTER_EOF;
} }
break; break;
@ -304,8 +309,7 @@ bool FAT_InitFiles (bool initCard)
int bootSector; int bootSector;
BOOT_SEC* bootSec; BOOT_SEC* bootSec;
if (initCard && !CARD_StartUp()) if (initCard && !CARD_StartUp()) {
{
return (false); return (false);
} }
@ -314,17 +318,10 @@ bool FAT_InitFiles (bool initCard)
{ {
return false; return false;
} }
// Check if there is a FAT string, which indicates this is a boot sector if (((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T')) // Check if there is a FAT string, which indicates this is a boot sector
if ((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T')) || ((globalBuffer[0x52] == 'F') && (globalBuffer[0x53] == 'A') && (globalBuffer[0x54] == 'T'))) { // Check for FAT32
{
bootSector = 0; bootSector = 0;
} } else // This is an MBR
// Check for FAT32
else if ((globalBuffer[0x52] == 'F') && (globalBuffer[0x53] == 'A') && (globalBuffer[0x54] == 'T'))
{
bootSector = 0;
}
else // This is an MBR
{ {
// Find first valid partition from MBR // Find first valid partition from MBR
// First check for an active partition // First check for an active partition
@ -334,7 +331,7 @@ bool FAT_InitFiles (bool initCard)
for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i+0x04] == 0x00); i+= 0x10); for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i+0x04] == 0x00); i+= 0x10);
// Go to first valid partition // Go to first valid partition
if ( i != 0x1FE) // Make sure it found a partition if (i != 0x1FE) // Make sure it found a partition
{ {
bootSector = globalBuffer[0x8 + i] + (globalBuffer[0x9 + i] << 8) + (globalBuffer[0xA + i] << 16) + ((globalBuffer[0xB + i] << 24) & 0x0F); bootSector = globalBuffer[0x8 + i] + (globalBuffer[0x9 + i] << 8) + (globalBuffer[0xA + i] << 16) + ((globalBuffer[0xB + i] << 24) & 0x0F);
} else { } else {
@ -347,55 +344,41 @@ bool FAT_InitFiles (bool initCard)
CARD_ReadSector (bootSector, bootSec); CARD_ReadSector (bootSector, bootSec);
// Store required information about the file system // Store required information about the file system
if (bootSec->sectorsPerFAT != 0) if (bootSec->bpb.sectorsPerFAT != 0) {
{ discSecPerFAT = bootSec->bpb.sectorsPerFAT;
discSecPerFAT = bootSec->sectorsPerFAT; } else {
}
else
{
discSecPerFAT = bootSec->extBlock.fat32.sectorsPerFAT32; discSecPerFAT = bootSec->extBlock.fat32.sectorsPerFAT32;
} }
if (bootSec->numSectorsSmall != 0) if (bootSec->bpb.numSectorsSmall != 0) {
{ discNumSec = bootSec->bpb.numSectorsSmall;
discNumSec = bootSec->numSectorsSmall; } else {
} discNumSec = bootSec->bpb.numSectors;
else
{
discNumSec = bootSec->numSectors;
} }
discBytePerSec = BYTES_PER_SECTOR; // Sector size is redefined to be 512 bytes discBytePerSec = BYTES_PER_SECTOR; // Sector size is redefined to be 512 bytes
discSecPerClus = bootSec->sectorsPerCluster * bootSec->bytesPerSector / BYTES_PER_SECTOR; discSecPerClus = bootSec->bpb.sectorsPerCluster * bootSec->bpb.bytesPerSector / BYTES_PER_SECTOR;
discBytePerClus = discBytePerSec * discSecPerClus; discBytePerClus = discBytePerSec * discSecPerClus;
discFAT = bootSector + bootSec->reservedSectors; discFAT = bootSector + bootSec->bpb.reservedSectors;
discRootDir = discFAT + (bootSec->numFATs * discSecPerFAT); discRootDir = discFAT + (bootSec->bpb.numFATs * discSecPerFAT);
discData = discRootDir + ((bootSec->rootEntries * sizeof(DIR_ENT)) / BYTES_PER_SECTOR); discData = discRootDir + ((bootSec->bpb.rootEntries * sizeof(DIR_ENT)) / BYTES_PER_SECTOR);
if ((discNumSec - discData) / bootSec->sectorsPerCluster < 4085) if ((discNumSec - discData) / bootSec->bpb.sectorsPerCluster < 4085) {
{
discFileSystem = FS_FAT12; discFileSystem = FS_FAT12;
} } else if ((discNumSec - discData) / bootSec->bpb.sectorsPerCluster < 65525) {
else if ((discNumSec - discData) / bootSec->sectorsPerCluster < 65525)
{
discFileSystem = FS_FAT16; discFileSystem = FS_FAT16;
} } else {
else
{
discFileSystem = FS_FAT32; discFileSystem = FS_FAT32;
} }
if (discFileSystem != FS_FAT32) if (discFileSystem != FS_FAT32) {
{
discRootDirClus = FAT16_ROOT_DIR_CLUSTER; discRootDirClus = FAT16_ROOT_DIR_CLUSTER;
} } else // Set up for the FAT32 way
else // Set up for the FAT32 way
{ {
discRootDirClus = bootSec->extBlock.fat32.rootClus; discRootDirClus = bootSec->extBlock.fat32.rootClus;
// Check if FAT mirroring is enabled // Check if FAT mirroring is enabled
if (!(bootSec->extBlock.fat32.extFlags & 0x80)) if (!(bootSec->extBlock.fat32.extFlags & 0x80)) {
{
// Use the active FAT // Use the active FAT
discFAT = discFAT + ( discSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F)); discFAT = discFAT + ( discSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F));
} }
@ -425,8 +408,7 @@ u32 getBootFileCluster (const char* bootName)
// Check if fat has been initialised // Check if fat has been initialised
if (discBytePerSec == 0) if (discBytePerSec == 0) {
{
return (CLUSTER_FREE); return (CLUSTER_FREE);
} }
@ -443,52 +425,42 @@ u32 getBootFileCluster (const char* bootName)
wrkDirOffset = -1; // Start at entry zero, Compensating for increment wrkDirOffset = -1; // Start at entry zero, Compensating for increment
while (!found && !notFound) { while (!found && !notFound) {
wrkDirOffset++; wrkDirOffset++;
if (wrkDirOffset == BYTES_PER_SECTOR / sizeof (DIR_ENT)) if (wrkDirOffset == BYTES_PER_SECTOR / sizeof (DIR_ENT)) {
{
wrkDirOffset = 0; wrkDirOffset = 0;
wrkDirSector++; wrkDirSector++;
if ((wrkDirSector == discSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER)) if ((wrkDirSector == discSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER)) {
{
wrkDirSector = 0; wrkDirSector = 0;
wrkDirCluster = FAT_NextCluster(wrkDirCluster); wrkDirCluster = FAT_NextCluster(wrkDirCluster);
if (wrkDirCluster == CLUSTER_EOF) if (wrkDirCluster == CLUSTER_EOF) {
{
notFound = true; notFound = true;
} }
firstSector = FAT_ClustToSect(wrkDirCluster); firstSector = FAT_ClustToSect(wrkDirCluster);
} } else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (discData - discRootDir))) {
else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (discData - discRootDir)))
{
notFound = true; // Got to end of root dir notFound = true; // Got to end of root dir
} }
CARD_ReadSector (firstSector + wrkDirSector, globalBuffer); CARD_ReadSector (firstSector + wrkDirSector, globalBuffer);
} }
dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset]; dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset];
found = true; found = true;
if ((dir.attrib & ATTRIB_DIR) || (dir.attrib & ATTRIB_VOL)) if ((dir.attrib & ATTRIB_DIR) || (dir.attrib & ATTRIB_VOL)) {
{
found = false; found = false;
} }
if(namelen<8 && dir.name[namelen]!=0x20) found = false; if (namelen<8 && dir.name[namelen]!=0x20) found = false;
for (nameOffset = 0; nameOffset < namelen && found; nameOffset++) for (nameOffset = 0; nameOffset < namelen && found; nameOffset++) {
{
if (ucase(dir.name[nameOffset]) != bootName[nameOffset]) if (ucase(dir.name[nameOffset]) != bootName[nameOffset])
found = false; found = false;
} }
for (nameOffset = 0; nameOffset < 3 && found; nameOffset++) for (nameOffset = 0; nameOffset < 3 && found; nameOffset++) {
{
if (ucase(dir.ext[nameOffset]) != bootName[nameOffset+namelen+1]) if (ucase(dir.ext[nameOffset]) != bootName[nameOffset+namelen+1])
found = false; found = false;
} }
if (dir.name[0] == FILE_LAST) if (dir.name[0] == FILE_LAST) {
{
notFound = true; notFound = true;
} }
} }
// If no file is found, return CLUSTER_FREE // If no file is found, return CLUSTER_FREE
if (notFound) if (notFound) {
{
return CLUSTER_FREE; return CLUSTER_FREE;
} }
@ -513,8 +485,7 @@ u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length)
} }
// Follow cluster list until desired one is found // Follow cluster list until desired one is found
for (chunks = startOffset / discBytePerClus; chunks > 0; chunks--) for (chunks = startOffset / discBytePerClus; chunks > 0; chunks--) {
{
cluster = FAT_NextCluster (cluster); cluster = FAT_NextCluster (cluster);
} }
@ -524,33 +495,30 @@ u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length)
curByte = startOffset % BYTES_PER_SECTOR; curByte = startOffset % BYTES_PER_SECTOR;
// Load sector buffer for new position in file // Load sector buffer for new position in file
CARD_ReadSector( curSect + FAT_ClustToSect(cluster), globalBuffer); CARD_ReadSector(curSect + FAT_ClustToSect(cluster), globalBuffer);
curSect++; curSect++;
// Number of bytes needed to read to align with a sector // Number of bytes needed to read to align with a sector
beginBytes = (BYTES_PER_SECTOR < length + curByte ? (BYTES_PER_SECTOR - curByte) : length); beginBytes = (BYTES_PER_SECTOR < length + curByte ? (BYTES_PER_SECTOR - curByte) : length);
// Read first part from buffer, to align with sector boundary // Read first part from buffer, to align with sector boundary
for (dataPos = 0 ; dataPos < beginBytes; dataPos++) for (dataPos = 0 ; dataPos < beginBytes; dataPos++) {
{
buffer[dataPos] = globalBuffer[curByte++]; buffer[dataPos] = globalBuffer[curByte++];
} }
// Read in all the 512 byte chunks of the file directly, saving time // Read in all the 512 byte chunks of the file directly, saving time
for ( chunks = ((int)length - beginBytes) / BYTES_PER_SECTOR; chunks > 0;) for (chunks = ((int)length - beginBytes) / BYTES_PER_SECTOR; chunks > 0;) {
{
int sectorsToRead; int sectorsToRead;
// Move to the next cluster if necessary // Move to the next cluster if necessary
if (curSect >= discSecPerClus) if (curSect >= discSecPerClus) {
{
curSect = 0; curSect = 0;
cluster = FAT_NextCluster (cluster); cluster = FAT_NextCluster (cluster);
} }
// Calculate how many sectors to read (read a maximum of discSecPerClus at a time) // Calculate how many sectors to read (read a maximum of discSecPerClus at a time)
sectorsToRead = discSecPerClus - curSect; sectorsToRead = discSecPerClus - curSect;
if(chunks < sectorsToRead) if (chunks < sectorsToRead)
sectorsToRead = chunks; sectorsToRead = chunks;
// Read the sectors // Read the sectors
@ -561,21 +529,18 @@ u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length)
} }
// Take care of any bytes left over before end of read // Take care of any bytes left over before end of read
if (dataPos < length) if (dataPos < length) {
{
// Update the read buffer // Update the read buffer
curByte = 0; curByte = 0;
if (curSect >= discSecPerClus) if (curSect >= discSecPerClus) {
{
curSect = 0; curSect = 0;
cluster = FAT_NextCluster (cluster); cluster = FAT_NextCluster (cluster);
} }
CARD_ReadSector( curSect + FAT_ClustToSect( cluster), globalBuffer); CARD_ReadSector(curSect + FAT_ClustToSect(cluster), globalBuffer);
// Read in last partial chunk // Read in last partial chunk
for (; dataPos < length; dataPos++) for (; dataPos < length; dataPos++) {
{
buffer[dataPos] = globalBuffer[curByte]; buffer[dataPos] = globalBuffer[curByte];
curByte++; curByte++;
} }