Rework FAT filesystem to not be tied to boot filesystem

svn path=/trunk/; revision=43267
This commit is contained in:
Hervé Poussineau 2009-10-03 16:47:54 +00:00
parent 8ccb271064
commit c599bd7dc0
2 changed files with 239 additions and 240 deletions

View file

@ -23,33 +23,34 @@
#include <debug.h> #include <debug.h>
ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONG PartitionSectorCount); ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONG PartitionSectorCount);
PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG* EntryCountPointer, BOOLEAN RootDirectory); PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG DirectoryStartCluster, ULONG* EntryCountPointer, BOOLEAN RootDirectory);
BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG EntryCount, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer); BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG EntryCount, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
LONG FatLookupFile(PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPointer); LONG FatLookupFile(PFAT_VOLUME_INFO Volume, PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPointer);
void FatParseShortFileName(PCHAR Buffer, PDIRENTRY DirEntry); void FatParseShortFileName(PCHAR Buffer, PDIRENTRY DirEntry);
BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer); BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPointer);
ULONG FatCountClustersInChain(ULONG StartCluster); ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG StartCluster);
ULONG* FatGetClusterChainArray(ULONG StartCluster); ULONG* FatGetClusterChainArray(PFAT_VOLUME_INFO Volume, ULONG StartCluster);
BOOLEAN FatReadCluster(ULONG ClusterNumber, PVOID Buffer); BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer);
BOOLEAN FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer); BOOLEAN FatReadPartialCluster(PFAT_VOLUME_INFO Volume, ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer);
BOOLEAN FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer); BOOLEAN FatReadVolumeSectors(PFAT_VOLUME_INFO Volume, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer);
BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer);
BOOLEAN FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer);
ULONG BytesPerSector; /* Number of bytes per sector */ typedef struct _FAT_VOLUME_INFO
ULONG SectorsPerCluster; /* Number of sectors per cluster */ {
ULONG FatVolumeStartSector; /* Absolute starting sector of the partition */ ULONG BytesPerSector; /* Number of bytes per sector */
ULONG FatSectorStart; /* Starting sector of 1st FAT table */ ULONG SectorsPerCluster; /* Number of sectors per cluster */
ULONG ActiveFatSectorStart; /* Starting sector of active FAT table */ ULONG FatSectorStart; /* Starting sector of 1st FAT table */
ULONG NumberOfFats; /* Number of FAT tables */ ULONG ActiveFatSectorStart; /* Starting sector of active FAT table */
ULONG SectorsPerFat; /* Sectors per FAT table */ ULONG NumberOfFats; /* Number of FAT tables */
ULONG RootDirSectorStart; /* Starting sector of the root directory (non-fat32) */ ULONG SectorsPerFat; /* Sectors per FAT table */
ULONG RootDirSectors; /* Number of sectors of the root directory (non-fat32) */ ULONG RootDirSectorStart; /* Starting sector of the root directory (non-fat32) */
ULONG RootDirStartCluster; /* Starting cluster number of the root directory (fat32 only) */ ULONG RootDirSectors; /* Number of sectors of the root directory (non-fat32) */
ULONG DataSectorStart; /* Starting sector of the data area */ ULONG RootDirStartCluster; /* Starting cluster number of the root directory (fat32 only) */
ULONG DataSectorStart; /* Starting sector of the data area */
ULONG FatType; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */
ULONG DeviceId;
} FAT_VOLUME_INFO;
ULONG FatType = 0; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */ PFAT_VOLUME_INFO FatVolumes[MAX_FDS];
ULONG FatDriveNumber = 0;
VOID FatSwapFatBootSector(PFAT_BOOTSECTOR Obj) VOID FatSwapFatBootSector(PFAT_BOOTSECTOR Obj)
{ {
@ -129,7 +130,7 @@ VOID FatSwapFatXDirEntry(PFATX_DIRENTRY Obj)
SW(Obj, LastAccessDate); SW(Obj, LastAccessDate);
} }
BOOLEAN FatOpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG PartitionSectorCount) BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONGLONG PartitionSectorCount)
{ {
char ErrMsg[80]; char ErrMsg[80];
ULONG FatSize; ULONG FatSize;
@ -137,42 +138,21 @@ BOOLEAN FatOpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG
PFAT32_BOOTSECTOR Fat32VolumeBootSector; PFAT32_BOOTSECTOR Fat32VolumeBootSector;
PFATX_BOOTSECTOR FatXVolumeBootSector; PFATX_BOOTSECTOR FatXVolumeBootSector;
DPRINTM(DPRINT_FILESYSTEM, "FatOpenVolume() DriveNumber = 0x%x VolumeStartSector = %d\n", DriveNumber, VolumeStartSector); DPRINTM(DPRINT_FILESYSTEM, "FatOpenVolume() DeviceId = %d\n", Volume->DeviceId);
// Store the drive number
FatDriveNumber = DriveNumber;
// //
// Allocate the memory to hold the boot sector // Allocate the memory to hold the boot sector
// //
FatVolumeBootSector = (PFAT_BOOTSECTOR) MmHeapAlloc(512); FatVolumeBootSector = (PFAT_BOOTSECTOR)BootSector;
Fat32VolumeBootSector = (PFAT32_BOOTSECTOR) FatVolumeBootSector; Fat32VolumeBootSector = (PFAT32_BOOTSECTOR)BootSector;
FatXVolumeBootSector = (PFATX_BOOTSECTOR) FatVolumeBootSector; FatXVolumeBootSector = (PFATX_BOOTSECTOR)BootSector;
//
// Make sure we got the memory
//
if (FatVolumeBootSector == NULL)
{
FileSystemError("Out of memory.");
return FALSE;
}
// Now try to read the boot sector
// If this fails then abort
if (!MachDiskReadLogicalSectors(DriveNumber, VolumeStartSector, 1, (PVOID)DISKREADBUFFER))
{
MmHeapFree(FatVolumeBootSector);
return FALSE;
}
RtlCopyMemory(FatVolumeBootSector, (PVOID)DISKREADBUFFER, 512);
// Get the FAT type // Get the FAT type
FatType = FatDetermineFatType(FatVolumeBootSector, PartitionSectorCount); Volume->FatType = FatDetermineFatType(FatVolumeBootSector, PartitionSectorCount);
// Dump boot sector (and swap it for big endian systems) // Dump boot sector (and swap it for big endian systems)
DPRINTM(DPRINT_FILESYSTEM, "Dumping boot sector:\n"); DPRINTM(DPRINT_FILESYSTEM, "Dumping boot sector:\n");
if (ISFATX(FatType)) if (ISFATX(Volume->FatType))
{ {
FatSwapFatXBootSector(FatXVolumeBootSector); FatSwapFatXBootSector(FatXVolumeBootSector);
DPRINTM(DPRINT_FILESYSTEM, "sizeof(FATX_BOOTSECTOR) = 0x%x.\n", sizeof(FATX_BOOTSECTOR)); DPRINTM(DPRINT_FILESYSTEM, "sizeof(FATX_BOOTSECTOR) = 0x%x.\n", sizeof(FATX_BOOTSECTOR));
@ -183,10 +163,10 @@ BOOLEAN FatOpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG
DPRINTM(DPRINT_FILESYSTEM, "NumberOfFats: %d\n", FatXVolumeBootSector->NumberOfFats); DPRINTM(DPRINT_FILESYSTEM, "NumberOfFats: %d\n", FatXVolumeBootSector->NumberOfFats);
DPRINTM(DPRINT_FILESYSTEM, "Unknown: 0x%x\n", FatXVolumeBootSector->Unknown); DPRINTM(DPRINT_FILESYSTEM, "Unknown: 0x%x\n", FatXVolumeBootSector->Unknown);
DPRINTM(DPRINT_FILESYSTEM, "FatType %s\n", FatType == FATX16 ? "FATX16" : "FATX32"); DPRINTM(DPRINT_FILESYSTEM, "FatType %s\n", Volume->FatType == FATX16 ? "FATX16" : "FATX32");
} }
else if (FatType == FAT32) else if (Volume->FatType == FAT32)
{ {
FatSwapFat32BootSector(Fat32VolumeBootSector); FatSwapFat32BootSector(Fat32VolumeBootSector);
DPRINTM(DPRINT_FILESYSTEM, "sizeof(FAT32_BOOTSECTOR) = 0x%x.\n", sizeof(FAT32_BOOTSECTOR)); DPRINTM(DPRINT_FILESYSTEM, "sizeof(FAT32_BOOTSECTOR) = 0x%x.\n", sizeof(FAT32_BOOTSECTOR));
@ -248,20 +228,14 @@ BOOLEAN FatOpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG
DPRINTM(DPRINT_FILESYSTEM, "BootSectorMagic: 0x%x\n", FatVolumeBootSector->BootSectorMagic); DPRINTM(DPRINT_FILESYSTEM, "BootSectorMagic: 0x%x\n", FatVolumeBootSector->BootSectorMagic);
} }
//
// Set the correct partition offset
//
FatVolumeStartSector = VolumeStartSector;
// //
// Check the boot sector magic // Check the boot sector magic
// //
if (! ISFATX(FatType) && FatVolumeBootSector->BootSectorMagic != 0xaa55) if (! ISFATX(Volume->FatType) && FatVolumeBootSector->BootSectorMagic != 0xaa55)
{ {
sprintf(ErrMsg, "Invalid boot sector magic on drive 0x%x (expected 0xaa55 found 0x%x)", sprintf(ErrMsg, "Invalid boot sector magic (expected 0xaa55 found 0x%x)",
DriveNumber, FatVolumeBootSector->BootSectorMagic); FatVolumeBootSector->BootSectorMagic);
FileSystemError(ErrMsg); FileSystemError(ErrMsg);
MmHeapFree(FatVolumeBootSector);
return FALSE; return FALSE;
} }
@ -269,72 +243,60 @@ BOOLEAN FatOpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG
// Check the FAT cluster size // Check the FAT cluster size
// We do not support clusters bigger than 64k // We do not support clusters bigger than 64k
// //
if ((ISFATX(FatType) && 64 * 1024 < FatXVolumeBootSector->SectorsPerCluster * 512) || if ((ISFATX(Volume->FatType) && 64 * 1024 < FatXVolumeBootSector->SectorsPerCluster * 512) ||
(! ISFATX(FatType) && 64 * 1024 < FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector)) (! ISFATX(Volume->FatType) && 64 * 1024 < FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector))
{ {
FileSystemError("This file system has cluster sizes bigger than 64k.\nFreeLoader does not support this."); FileSystemError("This file system has cluster sizes bigger than 64k.\nFreeLoader does not support this.");
MmHeapFree(FatVolumeBootSector);
return FALSE; return FALSE;
} }
//
// Clear our variables
//
FatSectorStart = 0;
ActiveFatSectorStart = 0;
NumberOfFats = 0;
RootDirSectorStart = 0;
DataSectorStart = 0;
SectorsPerFat = 0;
RootDirSectors = 0;
// //
// Get the sectors per FAT, // Get the sectors per FAT,
// root directory starting sector, // root directory starting sector,
// and data sector start // and data sector start
// //
if (ISFATX(FatType)) if (ISFATX(Volume->FatType))
{ {
BytesPerSector = 512; Volume->BytesPerSector = 512;
SectorsPerCluster = SWAPD(FatXVolumeBootSector->SectorsPerCluster); Volume->SectorsPerCluster = SWAPD(FatXVolumeBootSector->SectorsPerCluster);
FatSectorStart = (4096 / BytesPerSector); Volume->FatSectorStart = (4096 / Volume->BytesPerSector);
ActiveFatSectorStart = FatSectorStart; Volume->ActiveFatSectorStart = Volume->FatSectorStart;
NumberOfFats = 1; Volume->NumberOfFats = 1;
FatSize = PartitionSectorCount / SectorsPerCluster * FatSize = PartitionSectorCount / Volume->SectorsPerCluster *
(FATX16 == FatType ? 2 : 4); (Volume->FatType == FATX16 ? 2 : 4);
SectorsPerFat = (((FatSize + 4095) / 4096) * 4096) / BytesPerSector; Volume->SectorsPerFat = (((FatSize + 4095) / 4096) * 4096) / Volume->BytesPerSector;
RootDirSectorStart = FatSectorStart + NumberOfFats * SectorsPerFat; Volume->RootDirSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
RootDirSectors = FatXVolumeBootSector->SectorsPerCluster; Volume->RootDirSectors = FatXVolumeBootSector->SectorsPerCluster;
DataSectorStart = RootDirSectorStart + RootDirSectors; Volume->DataSectorStart = Volume->RootDirSectorStart + Volume->RootDirSectors;
} }
else if (FatType != FAT32) else if (Volume->FatType != FAT32)
{ {
BytesPerSector = FatVolumeBootSector->BytesPerSector; Volume->BytesPerSector = FatVolumeBootSector->BytesPerSector;
SectorsPerCluster = FatVolumeBootSector->SectorsPerCluster; Volume->SectorsPerCluster = FatVolumeBootSector->SectorsPerCluster;
FatSectorStart = FatVolumeBootSector->ReservedSectors; Volume->FatSectorStart = FatVolumeBootSector->ReservedSectors;
ActiveFatSectorStart = FatSectorStart; Volume->ActiveFatSectorStart = Volume->FatSectorStart;
NumberOfFats = FatVolumeBootSector->NumberOfFats; Volume->NumberOfFats = FatVolumeBootSector->NumberOfFats;
SectorsPerFat = FatVolumeBootSector->SectorsPerFat; Volume->SectorsPerFat = FatVolumeBootSector->SectorsPerFat;
RootDirSectorStart = FatSectorStart + NumberOfFats * SectorsPerFat; Volume->RootDirSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
RootDirSectors = ((FatVolumeBootSector->RootDirEntries * 32) + (BytesPerSector - 1)) / BytesPerSector; Volume->RootDirSectors = ((FatVolumeBootSector->RootDirEntries * 32) + (Volume->BytesPerSector - 1)) / Volume->BytesPerSector;
DataSectorStart = RootDirSectorStart + RootDirSectors; Volume->DataSectorStart = Volume->RootDirSectorStart + Volume->RootDirSectors;
} }
else else
{ {
BytesPerSector = Fat32VolumeBootSector->BytesPerSector; Volume->BytesPerSector = Fat32VolumeBootSector->BytesPerSector;
SectorsPerCluster = Fat32VolumeBootSector->SectorsPerCluster; Volume->SectorsPerCluster = Fat32VolumeBootSector->SectorsPerCluster;
FatSectorStart = Fat32VolumeBootSector->ReservedSectors; Volume->FatSectorStart = Fat32VolumeBootSector->ReservedSectors;
ActiveFatSectorStart = FatSectorStart + Volume->ActiveFatSectorStart = Volume->FatSectorStart +
((Fat32VolumeBootSector->ExtendedFlags & 0x80) ? ((Fat32VolumeBootSector->ExtendedFlags & 0x0f) * Fat32VolumeBootSector->SectorsPerFatBig) : 0); ((Fat32VolumeBootSector->ExtendedFlags & 0x80) ? ((Fat32VolumeBootSector->ExtendedFlags & 0x0f) * Fat32VolumeBootSector->SectorsPerFatBig) : 0);
NumberOfFats = Fat32VolumeBootSector->NumberOfFats; Volume->NumberOfFats = Fat32VolumeBootSector->NumberOfFats;
SectorsPerFat = Fat32VolumeBootSector->SectorsPerFatBig; Volume->SectorsPerFat = Fat32VolumeBootSector->SectorsPerFatBig;
RootDirStartCluster = Fat32VolumeBootSector->RootDirStartCluster; Volume->RootDirStartCluster = Fat32VolumeBootSector->RootDirStartCluster;
DataSectorStart = FatSectorStart + NumberOfFats * SectorsPerFat; Volume->DataSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
// //
// Check version // Check version
@ -346,20 +308,6 @@ BOOLEAN FatOpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG
return FALSE; return FALSE;
} }
} }
MmHeapFree(FatVolumeBootSector);
{
GEOMETRY DriveGeometry;
ULONG BlockSize;
// Initialize drive by getting its geometry
if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry))
{
return FALSE;
}
BlockSize = MachDiskGetCacheableBlockCount(DriveNumber);
}
return TRUE; return TRUE;
} }
@ -419,7 +367,7 @@ ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONG PartitionSectorCo
} }
} }
PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOLEAN RootDirectory) PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOLEAN RootDirectory)
{ {
PVOID DirectoryBuffer; PVOID DirectoryBuffer;
@ -429,9 +377,9 @@ PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL
* For FAT32, the root directory is nothing special. We can treat it the same * For FAT32, the root directory is nothing special. We can treat it the same
* as a subdirectory. * as a subdirectory.
*/ */
if (RootDirectory && FAT32 == FatType) if (RootDirectory && Volume->FatType == FAT32)
{ {
DirectoryStartCluster = RootDirStartCluster; DirectoryStartCluster = Volume->RootDirStartCluster;
RootDirectory = FALSE; RootDirectory = FALSE;
} }
@ -440,18 +388,18 @@ PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL
// //
if (RootDirectory) if (RootDirectory)
{ {
*DirectorySize = RootDirSectors * BytesPerSector; *DirectorySize = Volume->RootDirSectors * Volume->BytesPerSector;
} }
else else
{ {
*DirectorySize = FatCountClustersInChain(DirectoryStartCluster) * SectorsPerCluster * BytesPerSector; *DirectorySize = FatCountClustersInChain(Volume, DirectoryStartCluster) * Volume->SectorsPerCluster * Volume->BytesPerSector;
} }
// //
// Attempt to allocate memory for directory buffer // Attempt to allocate memory for directory buffer
// //
DPRINTM(DPRINT_FILESYSTEM, "Trying to allocate (DirectorySize) %d bytes.\n", *DirectorySize); DPRINTM(DPRINT_FILESYSTEM, "Trying to allocate (DirectorySize) %d bytes.\n", *DirectorySize);
DirectoryBuffer = MmHeapAlloc(*DirectorySize); DirectoryBuffer = MmAllocateMemory(*DirectorySize);
if (DirectoryBuffer == NULL) if (DirectoryBuffer == NULL)
{ {
@ -463,17 +411,17 @@ PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL
// //
if (RootDirectory) if (RootDirectory)
{ {
if (!FatReadVolumeSectors(FatDriveNumber, RootDirSectorStart, RootDirSectors, DirectoryBuffer)) if (!FatReadVolumeSectors(Volume, Volume->RootDirSectorStart, Volume->RootDirSectors, DirectoryBuffer))
{ {
MmHeapFree(DirectoryBuffer); MmFreeMemory(DirectoryBuffer);
return NULL; return NULL;
} }
} }
else else
{ {
if (!FatReadClusterChain(DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer)) if (!FatReadClusterChain(Volume, DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer))
{ {
MmHeapFree(DirectoryBuffer); MmFreeMemory(DirectoryBuffer);
return NULL; return NULL;
} }
} }
@ -481,7 +429,7 @@ PVOID FatBufferDirectory(ULONG DirectoryStartCluster, ULONG *DirectorySize, BOOL
return DirectoryBuffer; return DirectoryBuffer;
} }
BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
{ {
ULONG EntryCount; ULONG EntryCount;
ULONG CurrentEntry; ULONG CurrentEntry;
@ -639,8 +587,8 @@ BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySi
// //
FatParseShortFileName(ShortNameBuffer, DirEntry); FatParseShortFileName(ShortNameBuffer, DirEntry);
DPRINTM(DPRINT_FILESYSTEM, "Entry: %d LFN = %s\n", CurrentEntry, LfnNameBuffer); //DPRINTM(DPRINT_FILESYSTEM, "Entry: %d LFN = %s\n", CurrentEntry, LfnNameBuffer);
DPRINTM(DPRINT_FILESYSTEM, "Entry: %d DOS name = %s\n", CurrentEntry, ShortNameBuffer); //DPRINTM(DPRINT_FILESYSTEM, "Entry: %d DOS name = %s\n", CurrentEntry, ShortNameBuffer);
// //
// See if the file name matches either the short or long name // See if the file name matches either the short or long name
@ -672,7 +620,7 @@ BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySi
// //
StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow; StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow;
DPRINTM(DPRINT_FILESYSTEM, "StartCluster = 0x%x\n", StartCluster); DPRINTM(DPRINT_FILESYSTEM, "StartCluster = 0x%x\n", StartCluster);
FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(StartCluster); FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(Volume, StartCluster);
// //
// See if memory allocation failed // See if memory allocation failed
@ -696,7 +644,7 @@ BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySi
return FALSE; return FALSE;
} }
static BOOLEAN FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer) static BOOLEAN FatXSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
{ {
ULONG EntryCount; ULONG EntryCount;
ULONG CurrentEntry; ULONG CurrentEntry;
@ -746,7 +694,7 @@ static BOOLEAN FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG Dir
/* /*
* Get the cluster chain * Get the cluster chain
*/ */
FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(DirEntry->StartCluster); FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(Volume, DirEntry->StartCluster);
/* /*
* See if memory allocation failed * See if memory allocation failed
@ -769,7 +717,7 @@ static BOOLEAN FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG Dir
* specified filename and fills in an FAT_FILE_INFO structure * specified filename and fills in an FAT_FILE_INFO structure
* with info describing the file, etc. returns ARC error code * with info describing the file, etc. returns ARC error code
*/ */
LONG FatLookupFile(PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPointer) LONG FatLookupFile(PFAT_VOLUME_INFO Volume, PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPointer)
{ {
UINT32 i; UINT32 i;
ULONG NumberOfPathParts; ULONG NumberOfPathParts;
@ -809,7 +757,7 @@ LONG FatLookupFile(PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPoi
// //
// Buffer the directory contents // Buffer the directory contents
// //
DirectoryBuffer = FatBufferDirectory(DirectoryStartCluster, &DirectorySize, (i == 0) ); DirectoryBuffer = FatBufferDirectory(Volume, DirectoryStartCluster, &DirectorySize, (i == 0) );
if (DirectoryBuffer == NULL) if (DirectoryBuffer == NULL)
{ {
return ENOMEM; return ENOMEM;
@ -818,24 +766,24 @@ LONG FatLookupFile(PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPoi
// //
// Search for file name in directory // Search for file name in directory
// //
if (ISFATX(FatType)) if (ISFATX(Volume->FatType))
{ {
if (!FatXSearchDirectoryBufferForFile(DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo)) if (!FatXSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{ {
MmHeapFree(DirectoryBuffer); MmFreeMemory(DirectoryBuffer);
return ENOENT; return ENOENT;
} }
} }
else else
{ {
if (!FatSearchDirectoryBufferForFile(DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo)) if (!FatSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
{ {
MmHeapFree(DirectoryBuffer); MmFreeMemory(DirectoryBuffer);
return ENOENT; return ENOENT;
} }
} }
MmHeapFree(DirectoryBuffer); MmFreeMemory(DirectoryBuffer);
// //
// If we have another sub-directory to go then // If we have another sub-directory to go then
@ -844,8 +792,8 @@ LONG FatLookupFile(PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPoi
if ((i+1) < NumberOfPathParts) if ((i+1) < NumberOfPathParts)
{ {
DirectoryStartCluster = FatFileInfo.FileFatChain[0]; DirectoryStartCluster = FatFileInfo.FileFatChain[0];
MmHeapFree(FatFileInfo.FileFatChain);
} }
MmFreeMemory(FatFileInfo.FileFatChain);
} }
memcpy(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO)); memcpy(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO));
@ -899,44 +847,44 @@ void FatParseShortFileName(PCHAR Buffer, PDIRENTRY DirEntry)
Buffer[Idx++] = (DirEntry->FileName[10] == ' ') ? '\0' : DirEntry->FileName[10]; Buffer[Idx++] = (DirEntry->FileName[10] == ' ') ? '\0' : DirEntry->FileName[10];
} }
DPRINTM(DPRINT_FILESYSTEM, "FatParseShortFileName() ShortName = %s\n", Buffer); //DPRINTM(DPRINT_FILESYSTEM, "FatParseShortFileName() ShortName = %s\n", Buffer);
} }
/* /*
* FatGetFatEntry() * FatGetFatEntry()
* returns the Fat entry for a given cluster number * returns the Fat entry for a given cluster number
*/ */
BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer) BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPointer)
{ {
ULONG fat = 0; ULONG fat = 0;
UINT32 FatOffset; UINT32 FatOffset;
UINT32 ThisFatSecNum; UINT32 ThisFatSecNum;
UINT32 ThisFatEntOffset; UINT32 ThisFatEntOffset;
DPRINTM(DPRINT_FILESYSTEM, "FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster); //DPRINTM(DPRINT_FILESYSTEM, "FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster);
switch(FatType) switch(Volume->FatType)
{ {
case FAT12: case FAT12:
FatOffset = Cluster + (Cluster / 2); FatOffset = Cluster + (Cluster / 2);
ThisFatSecNum = ActiveFatSectorStart + (FatOffset / BytesPerSector); ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
ThisFatEntOffset = (FatOffset % BytesPerSector); ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
DPRINTM(DPRINT_FILESYSTEM, "FatOffset: %d\n", FatOffset); DPRINTM(DPRINT_FILESYSTEM, "FatOffset: %d\n", FatOffset);
DPRINTM(DPRINT_FILESYSTEM, "ThisFatSecNum: %d\n", ThisFatSecNum); DPRINTM(DPRINT_FILESYSTEM, "ThisFatSecNum: %d\n", ThisFatSecNum);
DPRINTM(DPRINT_FILESYSTEM, "ThisFatEntOffset: %d\n", ThisFatEntOffset); DPRINTM(DPRINT_FILESYSTEM, "ThisFatEntOffset: %d\n", ThisFatEntOffset);
if (ThisFatEntOffset == (BytesPerSector - 1)) if (ThisFatEntOffset == (Volume->BytesPerSector - 1))
{ {
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 2, (PVOID)FILESYSBUFFER)) if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 2, (PVOID)FILESYSBUFFER))
{ {
return FALSE; return FALSE;
} }
} }
else else
{ {
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER)) if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
{ {
return FALSE; return FALSE;
} }
@ -955,10 +903,10 @@ BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer)
case FATX16: case FATX16:
FatOffset = (Cluster * 2); FatOffset = (Cluster * 2);
ThisFatSecNum = ActiveFatSectorStart + (FatOffset / BytesPerSector); ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
ThisFatEntOffset = (FatOffset % BytesPerSector); ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER)) if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
{ {
return FALSE; return FALSE;
} }
@ -972,10 +920,10 @@ BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer)
case FATX32: case FATX32:
FatOffset = (Cluster * 4); FatOffset = (Cluster * 4);
ThisFatSecNum = ActiveFatSectorStart + (FatOffset / BytesPerSector); ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
ThisFatEntOffset = (FatOffset % BytesPerSector); ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
if (!FatReadVolumeSectors(FatDriveNumber, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER)) if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, (PVOID)FILESYSBUFFER))
{ {
return FALSE; return FALSE;
} }
@ -986,16 +934,20 @@ BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer)
break; break;
default:
DPRINTM(DPRINT_FILESYSTEM, "Unknown FAT type %d\n", Volume->FatType);
return FALSE;
} }
DPRINTM(DPRINT_FILESYSTEM, "FAT entry is 0x%x.\n", fat); //DPRINTM(DPRINT_FILESYSTEM, "FAT entry is 0x%x.\n", fat);
*ClusterPointer = fat; *ClusterPointer = fat;
return TRUE; return TRUE;
} }
ULONG FatCountClustersInChain(ULONG StartCluster) ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG StartCluster)
{ {
ULONG ClusterCount = 0; ULONG ClusterCount = 0;
@ -1006,9 +958,9 @@ ULONG FatCountClustersInChain(ULONG StartCluster)
// //
// If end of chain then break out of our cluster counting loop // If end of chain then break out of our cluster counting loop
// //
if (((FatType == FAT12) && (StartCluster >= 0xff8)) || if (((Volume->FatType == FAT12) && (StartCluster >= 0xff8)) ||
((FatType == FAT16 || FatType == FATX16) && (StartCluster >= 0xfff8)) || ((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (StartCluster >= 0xfff8)) ||
((FatType == FAT32 || FatType == FATX32) && (StartCluster >= 0x0ffffff8))) ((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (StartCluster >= 0x0ffffff8)))
{ {
break; break;
} }
@ -1021,7 +973,7 @@ ULONG FatCountClustersInChain(ULONG StartCluster)
// //
// Get next cluster // Get next cluster
// //
if (!FatGetFatEntry(StartCluster, &StartCluster)) if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
{ {
return 0; return 0;
} }
@ -1032,7 +984,7 @@ ULONG FatCountClustersInChain(ULONG StartCluster)
return ClusterCount; return ClusterCount;
} }
ULONG* FatGetClusterChainArray(ULONG StartCluster) ULONG* FatGetClusterChainArray(PFAT_VOLUME_INFO Volume, ULONG StartCluster)
{ {
ULONG ClusterCount; ULONG ClusterCount;
ULONG ArraySize; ULONG ArraySize;
@ -1041,13 +993,13 @@ ULONG* FatGetClusterChainArray(ULONG StartCluster)
DPRINTM(DPRINT_FILESYSTEM, "FatGetClusterChainArray() StartCluster = %d\n", StartCluster); DPRINTM(DPRINT_FILESYSTEM, "FatGetClusterChainArray() StartCluster = %d\n", StartCluster);
ClusterCount = FatCountClustersInChain(StartCluster) + 1; // Lets get the 0x0ffffff8 on the end of the array ClusterCount = FatCountClustersInChain(Volume, StartCluster) + 1; // Lets get the 0x0ffffff8 on the end of the array
ArraySize = ClusterCount * sizeof(ULONG); ArraySize = ClusterCount * sizeof(ULONG);
// //
// Allocate array memory // Allocate array memory
// //
ArrayPointer = MmHeapAlloc(ArraySize); ArrayPointer = MmAllocateMemory(ArraySize);
if (ArrayPointer == NULL) if (ArrayPointer == NULL)
{ {
@ -1067,9 +1019,9 @@ ULONG* FatGetClusterChainArray(ULONG StartCluster)
// //
// Don't try to get next cluster for last cluster // Don't try to get next cluster for last cluster
// //
if (((FatType == FAT12) && (StartCluster >= 0xff8)) || if (((Volume->FatType == FAT12) && (StartCluster >= 0xff8)) ||
((FatType == FAT16 || FatType == FATX16) && (StartCluster >= 0xfff8)) || ((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (StartCluster >= 0xfff8)) ||
((FatType == FAT32 || FatType == FATX32) && (StartCluster >= 0x0ffffff8))) ((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (StartCluster >= 0x0ffffff8)))
{ {
Idx++; Idx++;
break; break;
@ -1078,9 +1030,9 @@ ULONG* FatGetClusterChainArray(ULONG StartCluster)
// //
// Get next cluster // Get next cluster
// //
if (!FatGetFatEntry(StartCluster, &StartCluster)) if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
{ {
MmHeapFree(ArrayPointer); MmFreeMemory(ArrayPointer);
return NULL; return NULL;
} }
} }
@ -1088,33 +1040,11 @@ ULONG* FatGetClusterChainArray(ULONG StartCluster)
return ArrayPointer; return ArrayPointer;
} }
/*
* FatReadCluster()
* Reads the specified cluster into memory
*/
BOOLEAN FatReadCluster(ULONG ClusterNumber, PVOID Buffer)
{
ULONG ClusterStartSector;
ClusterStartSector = ((ClusterNumber - 2) * SectorsPerCluster) + DataSectorStart;
DPRINTM(DPRINT_FILESYSTEM, "FatReadCluster() ClusterNumber = %d Buffer = 0x%x ClusterStartSector = %d\n", ClusterNumber, Buffer, ClusterStartSector);
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, SectorsPerCluster, (PVOID)FILESYSBUFFER))
{
return FALSE;
}
memcpy(Buffer, (PVOID)FILESYSBUFFER, SectorsPerCluster * BytesPerSector);
return TRUE;
}
/* /*
* FatReadClusterChain() * FatReadClusterChain()
* Reads the specified clusters into memory * Reads the specified clusters into memory
*/ */
BOOLEAN FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer) BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer)
{ {
ULONG ClusterStartSector; ULONG ClusterStartSector;
@ -1123,21 +1053,21 @@ BOOLEAN FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PV
while (NumberOfClusters > 0) while (NumberOfClusters > 0)
{ {
DPRINTM(DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer); //DPRINTM(DPRINT_FILESYSTEM, "FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer);
// //
// Calculate starting sector for cluster // Calculate starting sector for cluster
// //
ClusterStartSector = ((StartClusterNumber - 2) * SectorsPerCluster) + DataSectorStart; ClusterStartSector = ((StartClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
// //
// Read cluster into memory // Read cluster into memory
// //
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, SectorsPerCluster, (PVOID)FILESYSBUFFER)) if (!FatReadVolumeSectors(Volume, ClusterStartSector, Volume->SectorsPerCluster, (PVOID)FILESYSBUFFER))
{ {
return FALSE; return FALSE;
} }
memcpy(Buffer, (PVOID)FILESYSBUFFER, SectorsPerCluster * BytesPerSector); memcpy(Buffer, (PVOID)FILESYSBUFFER, Volume->SectorsPerCluster * Volume->BytesPerSector);
// //
// Decrement count of clusters left to read // Decrement count of clusters left to read
@ -1147,12 +1077,12 @@ BOOLEAN FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PV
// //
// Increment buffer address by cluster size // Increment buffer address by cluster size
// //
Buffer = (PVOID)((ULONG_PTR)Buffer + (SectorsPerCluster * BytesPerSector)); Buffer = (PVOID)((ULONG_PTR)Buffer + (Volume->SectorsPerCluster * Volume->BytesPerSector));
// //
// Get next cluster // Get next cluster
// //
if (!FatGetFatEntry(StartClusterNumber, &StartClusterNumber)) if (!FatGetFatEntry(Volume, StartClusterNumber, &StartClusterNumber))
{ {
return FALSE; return FALSE;
} }
@ -1160,9 +1090,9 @@ BOOLEAN FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PV
// //
// If end of chain then break out of our cluster reading loop // If end of chain then break out of our cluster reading loop
// //
if (((FatType == FAT12) && (StartClusterNumber >= 0xff8)) || if (((Volume->FatType == FAT12) && (StartClusterNumber >= 0xff8)) ||
((FatType == FAT16 || FatType == FATX16) && (StartClusterNumber >= 0xfff8)) || ((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (StartClusterNumber >= 0xfff8)) ||
((FatType == FAT32 || FatType == FATX32) && (StartClusterNumber >= 0x0ffffff8))) ((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (StartClusterNumber >= 0x0ffffff8)))
{ {
break; break;
} }
@ -1175,15 +1105,15 @@ BOOLEAN FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PV
* FatReadPartialCluster() * FatReadPartialCluster()
* Reads part of a cluster into memory * Reads part of a cluster into memory
*/ */
BOOLEAN FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer) BOOLEAN FatReadPartialCluster(PFAT_VOLUME_INFO Volume, ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
{ {
ULONG ClusterStartSector; ULONG ClusterStartSector;
DPRINTM(DPRINT_FILESYSTEM, "FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer); //DPRINTM(DPRINT_FILESYSTEM, "FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer);
ClusterStartSector = ((ClusterNumber - 2) * SectorsPerCluster) + DataSectorStart; ClusterStartSector = ((ClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
if (!FatReadVolumeSectors(FatDriveNumber, ClusterStartSector, SectorsPerCluster, (PVOID)FILESYSBUFFER)) if (!FatReadVolumeSectors(Volume, ClusterStartSector, Volume->SectorsPerCluster, (PVOID)FILESYSBUFFER))
{ {
return FALSE; return FALSE;
} }
@ -1200,6 +1130,7 @@ BOOLEAN FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG L
*/ */
BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer) BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer)
{ {
PFAT_VOLUME_INFO Volume = FatFileInfo->Volume;
ULONG ClusterNumber; ULONG ClusterNumber;
ULONG OffsetInCluster; ULONG OffsetInCluster;
ULONG LengthInCluster; ULONG LengthInCluster;
@ -1260,7 +1191,7 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesR
// the last cluster. // the last cluster.
// //
BytesPerCluster = SectorsPerCluster * BytesPerSector; BytesPerCluster = Volume->SectorsPerCluster * Volume->BytesPerSector;
// //
// Only do the first read if we // Only do the first read if we
@ -1279,7 +1210,7 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesR
// //
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
// //
if (!FatReadPartialCluster(ClusterNumber, OffsetInCluster, LengthInCluster, Buffer)) if (!FatReadPartialCluster(Volume, ClusterNumber, OffsetInCluster, LengthInCluster, Buffer))
{ {
return FALSE; return FALSE;
} }
@ -1310,7 +1241,7 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesR
// //
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
// //
if (!FatReadClusterChain(ClusterNumber, NumberOfClusters, Buffer)) if (!FatReadClusterChain(Volume, ClusterNumber, NumberOfClusters, Buffer))
{ {
return FALSE; return FALSE;
} }
@ -1335,7 +1266,7 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesR
// //
// Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
// //
if (!FatReadPartialCluster(ClusterNumber, 0, BytesToRead, Buffer)) if (!FatReadPartialCluster(Volume, ClusterNumber, 0, BytesToRead, Buffer))
{ {
return FALSE; return FALSE;
} }
@ -1351,16 +1282,35 @@ BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG* BytesR
return TRUE; return TRUE;
} }
BOOLEAN FatReadVolumeSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer) BOOLEAN FatReadVolumeSectors(PFAT_VOLUME_INFO Volume, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{ {
// Now try to read in the block LARGE_INTEGER Position;
if (!MachDiskReadLogicalSectors(DriveNumber, SectorNumber + FatVolumeStartSector, SectorCount, (PVOID)DISKREADBUFFER)) ULONG Count;
LONG ret;
//DPRINTM(DPRINT_FILESYSTEM, "FatReadVolumeSectors(): SectorNumber %d, SectorCount %d, Buffer %p\n",
// SectorNumber, SectorCount, Buffer);
//
// Seek to right position
//
Position.QuadPart = SectorNumber * 512;
ret = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
if (ret != ESUCCESS)
{ {
DPRINTM(DPRINT_FILESYSTEM, "FatReadVolumeSectors() Failed to seek\n");
return FALSE; return FALSE;
} }
// Copy data to the caller //
RtlCopyMemory(Buffer, (PVOID)DISKREADBUFFER, SectorCount * BytesPerSector); // Read data
//
ret = ArcRead(Volume->DeviceId, Buffer, SectorCount * 512, &Count);
if (ret != ESUCCESS || Count != SectorCount * 512)
{
DPRINTM(DPRINT_FILESYSTEM, "FatReadVolumeSectors() Failed to read\n");
return FALSE;
}
// Return success // Return success
return TRUE; return TRUE;
@ -1393,6 +1343,7 @@ LONG FatGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
LONG FatOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId) LONG FatOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
{ {
PFAT_VOLUME_INFO FatVolume;
FAT_FILE_INFO TempFileInfo; FAT_FILE_INFO TempFileInfo;
PFAT_FILE_INFO FileHandle; PFAT_FILE_INFO FileHandle;
ULONG DeviceId; ULONG DeviceId;
@ -1402,11 +1353,12 @@ LONG FatOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
return EACCES; return EACCES;
DeviceId = FsGetDeviceId(*FileId); DeviceId = FsGetDeviceId(*FileId);
FatVolume = FatVolumes[DeviceId];
DPRINTM(DPRINT_FILESYSTEM, "FatOpen() FileName = %s\n", Path); DPRINTM(DPRINT_FILESYSTEM, "FatOpen() FileName = %s\n", Path);
RtlZeroMemory(&TempFileInfo, sizeof(TempFileInfo)); RtlZeroMemory(&TempFileInfo, sizeof(TempFileInfo));
ret = FatLookupFile(Path, DeviceId, &TempFileInfo); ret = FatLookupFile(FatVolume, Path, DeviceId, &TempFileInfo);
if (ret != ESUCCESS) if (ret != ESUCCESS)
return ENOENT; return ENOENT;
@ -1415,6 +1367,7 @@ LONG FatOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
return ENOMEM; return ENOMEM;
RtlCopyMemory(FileHandle, &TempFileInfo, sizeof(FAT_FILE_INFO)); RtlCopyMemory(FileHandle, &TempFileInfo, sizeof(FAT_FILE_INFO));
FileHandle->Volume = FatVolume;
FsSetDeviceSpecific(*FileId, FileHandle); FsSetDeviceSpecific(*FileId, FileHandle);
return ESUCCESS; return ESUCCESS;
@ -1468,14 +1421,25 @@ const DEVVTBL FatFuncTable =
const DEVVTBL* FatMount(ULONG DeviceId) const DEVVTBL* FatMount(ULONG DeviceId)
{ {
PFAT_VOLUME_INFO Volume;
UCHAR Buffer[512]; UCHAR Buffer[512];
PFAT_BOOTSECTOR BootSector = (PFAT_BOOTSECTOR)Buffer; PFAT_BOOTSECTOR BootSector = (PFAT_BOOTSECTOR)Buffer;
PFAT32_BOOTSECTOR BootSector32 = (PFAT32_BOOTSECTOR)Buffer; PFAT32_BOOTSECTOR BootSector32 = (PFAT32_BOOTSECTOR)Buffer;
PFATX_BOOTSECTOR BootSectorX = (PFATX_BOOTSECTOR)Buffer; PFATX_BOOTSECTOR BootSectorX = (PFATX_BOOTSECTOR)Buffer;
FILEINFORMATION FileInformation;
LARGE_INTEGER Position; LARGE_INTEGER Position;
ULONG Count; ULONG Count;
ULARGE_INTEGER SectorCount;
LONG ret; LONG ret;
//
// Allocate data for volume information
//
Volume = MmHeapAlloc(sizeof(FAT_VOLUME_INFO));
if (!Volume)
return NULL;
RtlZeroMemory(Volume, sizeof(FAT_VOLUME_INFO));
// //
// Read the BootSector // Read the BootSector
// //
@ -1483,31 +1447,63 @@ const DEVVTBL* FatMount(ULONG DeviceId)
Position.LowPart = 0; Position.LowPart = 0;
ret = ArcSeek(DeviceId, &Position, SeekAbsolute); ret = ArcSeek(DeviceId, &Position, SeekAbsolute);
if (ret != ESUCCESS) if (ret != ESUCCESS)
{
MmHeapFree(Volume);
return NULL; return NULL;
}
ret = ArcRead(DeviceId, Buffer, sizeof(Buffer), &Count); ret = ArcRead(DeviceId, Buffer, sizeof(Buffer), &Count);
if (ret != ESUCCESS || Count != sizeof(Buffer)) if (ret != ESUCCESS || Count != sizeof(Buffer))
{
MmHeapFree(Volume);
return NULL; return NULL;
}
// //
// Check if BootSector is valid. If yes, return FAT function table // Check if BootSector is valid. If no, return early
// //
if (RtlEqualMemory(BootSector->FileSystemType, "FAT12 ", 8) || if (!RtlEqualMemory(BootSector->FileSystemType, "FAT12 ", 8) &&
RtlEqualMemory(BootSector->FileSystemType, "FAT16 ", 8) || !RtlEqualMemory(BootSector->FileSystemType, "FAT16 ", 8) &&
RtlEqualMemory(BootSector32->FileSystemType, "FAT32 ", 8) || !RtlEqualMemory(BootSector32->FileSystemType, "FAT32 ", 8) &&
RtlEqualMemory(BootSectorX->FileSystemType, "FATX", 4)) !RtlEqualMemory(BootSectorX->FileSystemType, "FATX", 4))
{ {
// MmHeapFree(Volume);
// Compatibility hack as long as FS is not using underlying device DeviceId
//
ULONG DriveNumber;
ULONGLONG StartSector;
ULONGLONG SectorCount;
int Type;
if (!DiskGetBootVolume(&DriveNumber, &StartSector, &SectorCount, &Type))
return NULL;
FatOpenVolume(DriveNumber, StartSector, SectorCount);
return &FatFuncTable;
}
else
return NULL; return NULL;
}
//
// Determine sector count
//
ret = ArcGetFileInformation(DeviceId, &FileInformation);
if (ret != ESUCCESS)
{
MmHeapFree(Volume);
return NULL;
}
SectorCount.HighPart = FileInformation.EndingAddress.HighPart;
SectorCount.LowPart = FileInformation.EndingAddress.LowPart;
SectorCount.QuadPart /= SECTOR_SIZE;
//
// Keep device id
//
Volume->DeviceId = DeviceId;
//
// Really open the volume
//
if (!FatOpenVolume(Volume, BootSector, SectorCount.QuadPart))
{
MmHeapFree(Volume);
return NULL;
}
//
// Remember FAT volume information
//
FatVolumes[DeviceId] = Volume;
//
// Return success
//
return &FatFuncTable;
} }

View file

@ -144,12 +144,15 @@ typedef struct
} FATX_DIRENTRY, * PFATX_DIRENTRY; } FATX_DIRENTRY, * PFATX_DIRENTRY;
#include <poppack.h> #include <poppack.h>
typedef struct _FAT_VOLUME_INFO *PFAT_VOLUME_INFO;
typedef struct typedef struct
{ {
ULONG FileSize; /* File size */ ULONG FileSize; /* File size */
ULONG FilePointer; /* File pointer */ ULONG FilePointer; /* File pointer */
ULONG* FileFatChain; /* File fat chain array */ ULONG* FileFatChain; /* File fat chain array */
ULONG DriveNumber; ULONG DriveNumber;
PFAT_VOLUME_INFO Volume;
} FAT_FILE_INFO, * PFAT_FILE_INFO; } FAT_FILE_INFO, * PFAT_FILE_INFO;
#define ATTR_NORMAL 0x00 #define ATTR_NORMAL 0x00