Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// f32\sfat32\sl_mnt16.cpp
// CFatMountCB code, specific to the EFAT.FSY
//
//
/**
@file
*/
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!
//!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
//!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include "sl_std.h"
#include "sl_cache.h"
#include "sl_leafdir_cache.h"
//-------------------------------------------------------------------------------------------------------------------
/**
Write aligned members of TFatBootSector to media
@param aMediaPos media position the data will be written to
@param aBootSector data to write
@return Media write error code
*/
TInt CFatMountCB::DoWriteBootSector(TInt64 aMediaPos, const TFatBootSector& aBootSector) const
{
__PRINT2(_L("#- CFatMountCB::DoWriteBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);
ASSERT(aMediaPos>=0);
TBuf8<KDefaultSectorSize> bootSecBuf(KDefaultSectorSize);
bootSecBuf.FillZ();
//-- externalize boot sector to the data buffer
aBootSector.Externalize(bootSecBuf);
//-- put a boot sector signature to the last 2 bytes
bootSecBuf[KDefaultSectorSize-2] = 0x55;
bootSecBuf[KDefaultSectorSize-1] = 0xaa;
//-- write boot sector to the media
TInt r=LocalDrive()->Write(aMediaPos, bootSecBuf);
if (r!=KErrNone)
{//-- write failure
__PRINT2(_L("CFatMountCB::DoWriteBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
}
return r;
}
//-------------------------------------------------------------------------------------------------------------------
/**
Read non aligned boot data from media into TFatBootSector structure
@param aMediaPos media position the data will be read from
@param aBootSector refrence to TFatBootSector populate
@return Media read error code
*/
TInt CFatMountCB::DoReadBootSector(TInt64 aMediaPos, TFatBootSector& aBootSector) const
{
__PRINT2(_L("#- CFatMountCB::DoReadBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);
ASSERT(aMediaPos>=0);
TBuf8<KSizeOfFatBootSector> bootSecBuf(KSizeOfFatBootSector);
//-- read boot sector from the media
TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFatBootSector, bootSecBuf);
if (r != KErrNone)
{
__PRINT2(_L("CFatMountCB::DoReadBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
//-- fiddling with the error code; taken from MountL()
if (r==KErrNotSupported)
return KErrNotReady;
#if defined(_LOCKABLE_MEDIA)
else if(r==KErrLocked)
return KErrLocked;
#endif
else if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown)
return KErrCorrupt;
return r;
}
ASSERT(r==KErrNone);
//-- initialise TFatBootSector object
aBootSector.Internalize(bootSecBuf);
//-- Validate the partition size, and fix up if the out of bounds
TLocalDriveCapsV2Buf localDriveCaps;
r = LocalDrive()->Caps(localDriveCaps);
ASSERT(r==KErrNone);
if(!(localDriveCaps().iMediaAtt & KMediaAttVariableSize))
{//-- this is not a RAM drive.
const TUint32 maxSectors = I64LOW(localDriveCaps().iSize >> KDefSectorSzLog2);
if(aBootSector.TotalSectors())
aBootSector.SetTotalSectors(Min(aBootSector.TotalSectors(), maxSectors));
else
aBootSector.SetHugeSectors(Min(aBootSector.HugeSectors(), maxSectors));
}
return KErrNone;
}
//-------------------------------------------------------------------------------------------------------------------
/**
Read and validate the boot sector.
@param aBootSector reference to the boot sector object to be read.
@param aDoNotReadBkBootSec if true, there won't be an attempt to read backup sector (N/A for FAT12/16)
@return standard error code.
*/
TInt CFatMountCB::ReadBootSector(TFatBootSector& aBootSector, TBool /*aDoNotReadBkBootSec=EFalse*/)
{
//-- read main boot sector from the sector 0
TInt nRes = DoReadBootSector(KBootSectorNum << KDefSectorSzLog2, aBootSector);
if(nRes == KErrNone)
{
if(aBootSector.IsValid())
{//-- main boot sector is valid, everything is OK
return KErrNone;
}
else
{
__PRINT(_L("Boot Sector is invalid! dump:\n"));
aBootSector.PrintDebugInfo();
return KErrCorrupt;
}
}
//-- can't read boot sector
return nRes;
}
//-------------------------------------------------------------------------------------------------------------------
/**
Write a new volume label to BPB in media
@param aVolumeLabel Descriptor containing the new volume label
@leave
*/
void CFatMountCB::WriteVolumeLabelL(const TDesC8& aVolumeLabel) const
{
if(aVolumeLabel.Length() > KVolumeLabelSize)
User::Leave(KErrArgument);
User::LeaveIfError(LocalDrive()->Write(KFat16VolumeLabelPos,aVolumeLabel));
}
//-------------------------------------------------------------------------------------------------------------------
const TUint16 KFat16CleanShutDownMask = 0x08000; ///< Mask used to indicate test clean/dirty bit for Fat16
/**
Set or reset "VolumeClean" (ClnShutBitmask) flag.
@param aClean if ETrue, marks the volume as clean, otherwise as dirty.
@leave if write error occured.
*/
void CFatMountCB::SetVolumeCleanL(TBool aClean)
{
//-- The volume can't be set clean if there are objects opened on it. This precondition must be checked before calling this function
if(aClean && LockStatus()!=0)
{
__PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber());
ASSERT(0);
User::Leave(KErrInUse);
return;
}
if(FatType() == EFat12)
{//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive
// (ignoring any error for now as there's nothing we can do with it)
(void)LocalDrive()->Finalise(aClean);
return;
}
//-- further read and write will be directly from the CProxyDrive, bypassing FAT cache.
//-- this is because CFatTable doesn't allow access to FAT[1]
if(Is16BitFat())
{//-- Fat16
__PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT16, efat.fsy"),DriveNumber(), aClean);
if(FatConfig().FAT16_UseCleanShutDownBit())
{
TFat16Entry fatEntry;
const TInt KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
TPtr8 ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
const TFat16Entry tmp = fatEntry;
if(aClean)
fatEntry |= KFat16CleanShutDownMask; //-- set ClnShutBit flag
else
fatEntry &= ~KFat16CleanShutDownMask; //-- reset ClnShutBit flag
if(tmp != fatEntry)
{//-- write FAT[1] entry to all available FATs
for(TInt i=0; i<NumberOfFats(); ++i)
{
const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry
}
}
//-- Notify the underlying media that the mount is consistent
// (ignoring any error for now as there's nothing we can do with it)
(void)LocalDrive()->Finalise(aClean);
__PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry: %x->%x"), tmp, fatEntry);
}
else //if(FatConfig().FAT16_UseCleanShutDownBit())
{
__PRINT(_L("#- changing FAT16[1] is disabled in config!"));
}
}// if(Is16BitFat())
else
{//-- must never get here
ASSERT(0);
}
}
//-------------------------------------------------------------------------------------------------------------------
/**
Determine whether "VolumeClean" (ClnShutBitmask) flag is set.
@return ETrue if the volume is marked as clean and EFalse otherwise.
@leave if is called for FAT12 or if read error occured.
*/
TBool CFatMountCB::VolumeCleanL()
{
TFatDriveInterface& drive = DriveInterface();
if(Is16BitFat())
{//-- Fat16
TFat16Entry fatEntry;
const TInt KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
TPtr8 ptrFatEntry((TUint8*)&fatEntry, KFatEntrySize);
User::LeaveIfError(drive.ReadNonCritical(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
return (fatEntry & KFat16CleanShutDownMask);
}
else
{//-- Fat12 doesn't support this feature, shan't get here, actually
ASSERT(0);
User::Leave(KErrNotSupported);
return ETrue; //-- to satisfy the compiler
}
}
//-------------------------------------------------------------------------------------------------------------------
/**
Mount a Fat volume.
@param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs
@leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
*/
void CFatMountCB::MountL(TBool aForceMount)
{
const TInt driveNo = Drive().DriveNumber();
__PRINT2(_L("CFatMountCB::MountL() drv:%d, forceMount=%d\n"),driveNo,aForceMount);
ASSERT(State() == ENotMounted || State() == EDismounted);
SetState(EMounting);
SetReadOnly(EFalse);
User::LeaveIfError(CreateDrive(Drive().DriveNumber()));
//-- read FAT configuration parameters from estart.txt
iFatConfig.ReadConfig(driveNo);
//-- initialise interface to the low-level drive access
if(!iDriverInterface.Init(this))
User::LeaveIfError(KErrNoMemory);
//-- get drive capabilities
TLocalDriveCapsV2Buf capsBuf;
User::LeaveIfError(LocalDrive()->Caps(capsBuf));
iSize=capsBuf().iSize;
iRamDrive = EFalse;
if(capsBuf().iMediaAtt & KMediaAttVariableSize)
{//-- this is a RAM drive
UserSvr::UnlockRamDrive();
iRamDrive = ETrue;
}
if(aForceMount)
{//-- the state is "forcedly mounted", special case. This is an inconsistent state.
SetState(EInit_Forced);
return;
}
//-- read and validate boot sector (sector 0)
TFatBootSector bootSector;
User::LeaveIfError(ReadBootSector(bootSector, iRamDrive));
//-- print out boot sector debug information
bootSector.PrintDebugInfo();
//-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt
iFatType=bootSector.FatType();
ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector()
//-- values from the boot sector are checked in TFatBootSector::IsValid()
//-- store volume UID, it can be checked on Remount
iUniqueID = bootSector.UniqueID();
//-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid()
iVolParam.Populate(bootSector);
//-- initialize the volume
InitializeL(capsBuf());
ASSERT(State()==EInit_R);
GetVolumeLabelFromDiskL(bootSector);
__PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State());
}
//-------------------------------------------------------------------------------------------------------------------
/**
Initialize the FAT cache and disk access
@param aLocDrvCaps local drive capabilities
@leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
*/
void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool /*aIgnoreFSInfo=EFalse*/)
{
__PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber());
ASSERT(State() == EMounting); //-- we must get here only from MountL()
//========== Find out number of clusters on the volume
if(iRamDrive && SectorsPerCluster()!=1)
{// Align iFirstFreeByte to cluster boundary if internal ram drive
const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2();
const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2();
const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2;
iFirstFreeByte=alignedSector<<SectorSizeLog2();
}
else
{
iFirstFreeByte=RootDirEnd();
}
{//-- check if volume geometry looks valid
const TInt usableSectors=TotalSectors()-(iFirstFreeByte>>SectorSizeLog2());
iUsableClusters=usableSectors>>(ClusterSizeLog2()-SectorSizeLog2());
const TUint32 KMinClusters = 32; //-- absolute minimum number of clusters on the volume
const TUint32 KMaxClusters =(TotalSectors()-FirstFatSector()-NumberOfFats()*(FatSizeInBytes()>>SectorSizeLog2())) >> (ClusterSizeLog2()-SectorSizeLog2());
if(usableSectors <=0 || iUsableClusters < KMinClusters || iUsableClusters > KMaxClusters)
{
__PRINT(_L("CFatMountCB::InitializeL() Wrong number of usable cluster/sectors on the volume!"));
User::Leave(KErrCorrupt);
}
}
//========== initialise RawDisk interface
//-- CFatMountCB parameters might have changed, e.g. after formatting. Reconstruct directory cache with new parameters
delete iRawDisk;
iRawDisk=CRawDisk::NewL(*this, aLocDrvCaps);
iRawDisk->InitializeL();
//========== create FAT table object
delete iFatTable;
iFatTable=CFatTable::NewL(*this, aLocDrvCaps);
//========== create and setup leaf direcotry cache if cache limit is set bigger than one
const TUint32 cacheLimit = iFatConfig.LeafDirCacheSize();
if (cacheLimit > 1)
{
// destroy the old leaf dir cache to avoid memory leak.
delete iLeafDirCache;
iLeafDirCache = CLeafDirCache::NewL(cacheLimit);
}
else
{
iLeafDirCache = NULL;
}
//========== find out free clusters number on the volume
FAT().CountFreeClustersL();
SetState(EInit_R); //-- the state is "Initialized, but not writen"
//-- make a callback, telling FileServer about free space discovered.
const TInt64 freeSpace = ((TInt64)FAT().NumberOfFreeClusters()) << ClusterSizeLog2();
SetDiskSpaceChange(freeSpace);
__PRINT3(_L("#- CFatMountCB::InitializeL() done. drv:%d, Free clusters:%d, 1st Free cluster:%d"),DriveNumber(), FAT().NumberOfFreeClusters(), FAT().FreeClusterHint());
}
//-------------------------------------------------------------------------------------------------------------------
/**
Checks for end of file for all Fat types
@param aCluster Cluster to check
@return Result of test
*/
TBool CFatMountCB::IsEndOfClusterCh(TInt aCluster) const
{
if(Is16BitFat())
return(aCluster>=0xFFF8 && aCluster<=0xFFFF);
else
return(aCluster>=0xFF8 && aCluster<=0xFFF);
}
/**
Set a cluster to the end of cluster chain marker
@param aCluster cluster to set to end of chain marker
*/
void CFatMountCB::SetEndOfClusterCh(TInt &aCluster) const
{
if(Is16BitFat())
aCluster=0xFFF8;
else
aCluster=0xFF8;
}
/**
Initialize data to represent the root directory
@param anEntry Entry to initialise
*/
void CFatMountCB::InitializeRootEntry(TFatDirEntry & anEntry) const
{
anEntry.SetName(_L8("ROOT"));
anEntry.SetAttributes(KEntryAttDir);
anEntry.SetStartCluster(0);
}
/**
Implementation of CMountCB::FileSystemSubType(). Retrieves the sub type of Fat file system
and returns the name as a descriptor.
@param aName Name of the sub type of Fat file system
@return KErrNone if successful; KErrArgument if aName is not long enough; KErrNotReady if
the mount is not ready.
@see CMountCB::FileSystemSubType()
*/
TInt CFatMountCB::SubType(TDes& aName) const
{
if(aName.MaxLength() < 5)
return KErrArgument;
switch (iFatType)
{
case EFat12:
{
aName = KFSSubType_FAT12;
return KErrNone;
}
case EFat16:
{
aName = KFSSubType_FAT16;
return KErrNone;
}
default:
// case EInvalidFatType
return KErrNotReady;
}
}
//-------------------------------------------------------------------------------------------------------------------
/**
CFatMountCB control method.
@param aLevel specifies the operation to perfrom on the mount
@param aOption specific option for the given operation
@param aParam pointer to generic parameter, its meaning depends on aLevel and aOption
@return standard error code.
*/
TInt CFatMountCB::MountControl(TInt aLevel, TInt aOption, TAny* aParam)
{
TInt nRes = KErrNotSupported;
if(aLevel == ECheckFsMountable)
{
return MntCtl_DoCheckFileSystemMountable();
}
//-- mount state query: check if is in finalised state
if(aLevel == EMountStateQuery && aOption == ESQ_IsMountFinalised)
{
TBool bFinalised;
nRes = IsFinalised(bFinalised);
if(nRes == KErrNone)
{
*((TBool*)aParam) = bFinalised;
}
return nRes;
}
//-- File System - specific queries
if(aLevel == EMountFsParamQuery && aOption == ESQ_GetMaxSupportedFileSize)
{//-- this is a query to provide the max. supported file size; aParam is a pointer to TUint64 to return the value
*(TUint64*)aParam = KMaxSupportedFatFileSize;
return KErrNone;
}
return nRes;
}
//-------------------------------------------------------------------------------------------------------------------
/**
Reports whether the specified interface is supported - if it is,
the supplied interface object is modified to it
@param aInterfaceId The interface of interest
@param aInterface The interface object
@return KErrNone if the interface is supported, otherwise KErrNotFound
@see CMountCB::GetInterface()
*/
TInt CFatMountCB::GetInterface(TInt aInterfaceId, TAny*& aInterface,TAny* aInput)
{
switch(aInterfaceId)
{
case (CMountCB::EFileAccessor):
((CMountCB::MFileAccessor*&) aInterface) = this;
return KErrNone;
case (CMountCB::EGetFileSystemSubType):
aInterface = (MFileSystemSubType*) (this);
return KErrNone;
case (CMountCB::EGetClusterSize):
aInterface = (MFileSystemClusterSize*) (this);
return KErrNone;
case CMountCB::ELocalBufferSupport:
// RAM drives doesn't support local buffers (this results in file caching being disabled)
if (iRamDrive)
return KErrNotSupported;
else
return LocalDrive()->LocalBufferSupport();
case EGetProxyDrive:
((CProxyDrive*&)aInterface) = LocalDrive();
return KErrNone;
default:
return(CMountCB::GetInterface(aInterfaceId, aInterface, aInput));
}
}