First public contribution.
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfat32\sl_mnt16.cpp
15 // CFatMountCB code, specific to the EFAT.FSY
23 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
24 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
26 //!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
28 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
29 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
34 #include "sl_leafdir_cache.h"
37 //-------------------------------------------------------------------------------------------------------------------
39 Write aligned members of TFatBootSector to media
41 @param aMediaPos media position the data will be written to
42 @param aBootSector data to write
43 @return Media write error code
45 TInt CFatMountCB::DoWriteBootSector(TInt64 aMediaPos, const TFatBootSector& aBootSector) const
47 __PRINT2(_L("#- CFatMountCB::DoWriteBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);
51 TBuf8<KDefaultSectorSize> bootSecBuf(KDefaultSectorSize);
54 //-- externalize boot sector to the data buffer
55 aBootSector.Externalize(bootSecBuf);
57 //-- put a boot sector signature to the last 2 bytes
58 bootSecBuf[KDefaultSectorSize-2] = 0x55;
59 bootSecBuf[KDefaultSectorSize-1] = 0xaa;
61 //-- write boot sector to the media
62 TInt r=LocalDrive()->Write(aMediaPos, bootSecBuf);
65 __PRINT2(_L("CFatMountCB::DoWriteBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
71 //-------------------------------------------------------------------------------------------------------------------
74 Read non aligned boot data from media into TFatBootSector structure
76 @param aMediaPos media position the data will be read from
77 @param aBootSector refrence to TFatBootSector populate
78 @return Media read error code
80 TInt CFatMountCB::DoReadBootSector(TInt64 aMediaPos, TFatBootSector& aBootSector) const
82 __PRINT2(_L("#- CFatMountCB::DoReadBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);
86 TBuf8<KSizeOfFatBootSector> bootSecBuf(KSizeOfFatBootSector);
88 //-- read boot sector from the media
89 TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFatBootSector, bootSecBuf);
92 __PRINT2(_L("CFatMountCB::DoReadBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
94 //-- fiddling with the error code; taken from MountL()
95 if (r==KErrNotSupported)
97 #if defined(_LOCKABLE_MEDIA)
98 else if(r==KErrLocked)
101 else if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown)
109 //-- initialise TFatBootSector object
110 aBootSector.Internalize(bootSecBuf);
112 //-- Validate the partition size, and fix up if the out of bounds
113 TLocalDriveCapsV2Buf localDriveCaps;
114 r = LocalDrive()->Caps(localDriveCaps);
117 if(!(localDriveCaps().iMediaAtt & KMediaAttVariableSize))
118 {//-- this is not a RAM drive.
119 const TUint32 maxSectors = I64LOW(localDriveCaps().iSize >> KDefSectorSzLog2);
121 if(aBootSector.TotalSectors())
122 aBootSector.SetTotalSectors(Min(aBootSector.TotalSectors(), maxSectors));
124 aBootSector.SetHugeSectors(Min(aBootSector.HugeSectors(), maxSectors));
130 //-------------------------------------------------------------------------------------------------------------------
133 Read and validate the boot sector.
134 @param aBootSector reference to the boot sector object to be read.
135 @param aDoNotReadBkBootSec if true, there won't be an attempt to read backup sector (N/A for FAT12/16)
136 @return standard error code.
138 TInt CFatMountCB::ReadBootSector(TFatBootSector& aBootSector, TBool /*aDoNotReadBkBootSec=EFalse*/)
140 //-- read main boot sector from the sector 0
141 TInt nRes = DoReadBootSector(KBootSectorNum << KDefSectorSzLog2, aBootSector);
144 if(aBootSector.IsValid())
145 {//-- main boot sector is valid, everything is OK
150 __PRINT(_L("Boot Sector is invalid! dump:\n"));
151 aBootSector.PrintDebugInfo();
156 //-- can't read boot sector
160 //-------------------------------------------------------------------------------------------------------------------
163 Write a new volume label to BPB in media
165 @param aVolumeLabel Descriptor containing the new volume label
168 void CFatMountCB::WriteVolumeLabelL(const TDesC8& aVolumeLabel) const
170 if(aVolumeLabel.Length() > KVolumeLabelSize)
171 User::Leave(KErrArgument);
173 User::LeaveIfError(LocalDrive()->Write(KFat16VolumeLabelPos,aVolumeLabel));
178 //-------------------------------------------------------------------------------------------------------------------
180 const TUint16 KFat16CleanShutDownMask = 0x08000; ///< Mask used to indicate test clean/dirty bit for Fat16
183 Set or reset "VolumeClean" (ClnShutBitmask) flag.
185 @param aClean if ETrue, marks the volume as clean, otherwise as dirty.
186 @leave if write error occured.
188 void CFatMountCB::SetVolumeCleanL(TBool aClean)
190 //-- The volume can't be set clean if there are objects opened on it. This precondition must be checked before calling this function
191 if(aClean && LockStatus()!=0)
193 __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber());
195 User::Leave(KErrInUse);
199 if(FatType() == EFat12)
200 {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive
201 // (ignoring any error for now as there's nothing we can do with it)
202 (void)LocalDrive()->Finalise(aClean);
206 //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache.
207 //-- this is because CFatTable doesn't allow access to FAT[1]
211 __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT16, efat.fsy"),DriveNumber(), aClean);
213 if(FatConfig().FAT16_UseCleanShutDownBit())
216 TFat16Entry fatEntry;
217 const TInt KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
218 TPtr8 ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
220 User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
222 const TFat16Entry tmp = fatEntry;
225 fatEntry |= KFat16CleanShutDownMask; //-- set ClnShutBit flag
227 fatEntry &= ~KFat16CleanShutDownMask; //-- reset ClnShutBit flag
230 {//-- write FAT[1] entry to all available FATs
231 for(TInt i=0; i<NumberOfFats(); ++i)
233 const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
234 User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry
238 //-- Notify the underlying media that the mount is consistent
239 // (ignoring any error for now as there's nothing we can do with it)
240 (void)LocalDrive()->Finalise(aClean);
242 __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry: %x->%x"), tmp, fatEntry);
245 else //if(FatConfig().FAT16_UseCleanShutDownBit())
247 __PRINT(_L("#- changing FAT16[1] is disabled in config!"));
252 {//-- must never get here
258 //-------------------------------------------------------------------------------------------------------------------
261 Determine whether "VolumeClean" (ClnShutBitmask) flag is set.
263 @return ETrue if the volume is marked as clean and EFalse otherwise.
264 @leave if is called for FAT12 or if read error occured.
266 TBool CFatMountCB::VolumeCleanL()
268 TFatDriveInterface& drive = DriveInterface();
272 TFat16Entry fatEntry;
273 const TInt KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
274 TPtr8 ptrFatEntry((TUint8*)&fatEntry, KFatEntrySize);
276 User::LeaveIfError(drive.ReadNonCritical(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry
277 return (fatEntry & KFat16CleanShutDownMask);
280 {//-- Fat12 doesn't support this feature, shan't get here, actually
282 User::Leave(KErrNotSupported);
283 return ETrue; //-- to satisfy the compiler
287 //-------------------------------------------------------------------------------------------------------------------
292 @param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs
293 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
295 void CFatMountCB::MountL(TBool aForceMount)
297 const TInt driveNo = Drive().DriveNumber();
299 __PRINT2(_L("CFatMountCB::MountL() drv:%d, forceMount=%d\n"),driveNo,aForceMount);
301 ASSERT(State() == ENotMounted || State() == EDismounted);
306 User::LeaveIfError(CreateDrive(Drive().DriveNumber()));
308 //-- read FAT configuration parameters from estart.txt
309 iFatConfig.ReadConfig(driveNo);
312 //-- initialise interface to the low-level drive access
313 if(!iDriverInterface.Init(this))
314 User::LeaveIfError(KErrNoMemory);
316 //-- get drive capabilities
317 TLocalDriveCapsV2Buf capsBuf;
318 User::LeaveIfError(LocalDrive()->Caps(capsBuf));
320 iSize=capsBuf().iSize;
323 if(capsBuf().iMediaAtt & KMediaAttVariableSize)
324 {//-- this is a RAM drive
325 UserSvr::UnlockRamDrive();
330 {//-- the state is "forcedly mounted", special case. This is an inconsistent state.
331 SetState(EInit_Forced);
335 //-- read and validate boot sector (sector 0)
336 TFatBootSector bootSector;
337 User::LeaveIfError(ReadBootSector(bootSector, iRamDrive));
339 //-- print out boot sector debug information
340 bootSector.PrintDebugInfo();
342 //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt
343 iFatType=bootSector.FatType();
344 ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector()
346 //-- values from the boot sector are checked in TFatBootSector::IsValid()
347 //-- store volume UID, it can be checked on Remount
348 iUniqueID = bootSector.UniqueID();
350 //-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid()
351 iVolParam.Populate(bootSector);
353 //-- initialize the volume
354 InitializeL(capsBuf());
355 ASSERT(State()==EInit_R);
357 GetVolumeLabelFromDiskL(bootSector);
359 __PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State());
364 //-------------------------------------------------------------------------------------------------------------------
367 Initialize the FAT cache and disk access
369 @param aLocDrvCaps local drive capabilities
370 @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
372 void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool /*aIgnoreFSInfo=EFalse*/)
374 __PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber());
376 ASSERT(State() == EMounting); //-- we must get here only from MountL()
378 //========== Find out number of clusters on the volume
379 if(iRamDrive && SectorsPerCluster()!=1)
380 {// Align iFirstFreeByte to cluster boundary if internal ram drive
381 const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2();
382 const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2();
383 const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2;
384 iFirstFreeByte=alignedSector<<SectorSizeLog2();
388 iFirstFreeByte=RootDirEnd();
392 {//-- check if volume geometry looks valid
393 const TInt usableSectors=TotalSectors()-(iFirstFreeByte>>SectorSizeLog2());
394 iUsableClusters=usableSectors>>(ClusterSizeLog2()-SectorSizeLog2());
396 const TUint32 KMinClusters = 32; //-- absolute minimum number of clusters on the volume
397 const TUint32 KMaxClusters =(TotalSectors()-FirstFatSector()-NumberOfFats()*(FatSizeInBytes()>>SectorSizeLog2())) >> (ClusterSizeLog2()-SectorSizeLog2());
399 if(usableSectors <=0 || iUsableClusters < KMinClusters || iUsableClusters > KMaxClusters)
401 __PRINT(_L("CFatMountCB::InitializeL() Wrong number of usable cluster/sectors on the volume!"));
402 User::Leave(KErrCorrupt);
407 //========== initialise RawDisk interface
408 //-- CFatMountCB parameters might have changed, e.g. after formatting. Reconstruct directory cache with new parameters
411 iRawDisk=CRawDisk::NewL(*this, aLocDrvCaps);
412 iRawDisk->InitializeL();
415 //========== create FAT table object
417 iFatTable=CFatTable::NewL(*this, aLocDrvCaps);
419 //========== create and setup leaf direcotry cache if cache limit is set bigger than one
420 const TUint32 cacheLimit = iFatConfig.LeafDirCacheSize();
423 // destroy the old leaf dir cache to avoid memory leak.
424 delete iLeafDirCache;
425 iLeafDirCache = CLeafDirCache::NewL(cacheLimit);
429 iLeafDirCache = NULL;
432 //========== find out free clusters number on the volume
433 FAT().CountFreeClustersL();
435 SetState(EInit_R); //-- the state is "Initialized, but not writen"
437 //-- make a callback, telling FileServer about free space discovered.
438 const TInt64 freeSpace = ((TInt64)FAT().NumberOfFreeClusters()) << ClusterSizeLog2();
439 SetDiskSpaceChange(freeSpace);
441 __PRINT3(_L("#- CFatMountCB::InitializeL() done. drv:%d, Free clusters:%d, 1st Free cluster:%d"),DriveNumber(), FAT().NumberOfFreeClusters(), FAT().FreeClusterHint());
444 //-------------------------------------------------------------------------------------------------------------------
449 Checks for end of file for all Fat types
451 @param aCluster Cluster to check
452 @return Result of test
454 TBool CFatMountCB::IsEndOfClusterCh(TInt aCluster) const
457 return(aCluster>=0xFFF8 && aCluster<=0xFFFF);
459 return(aCluster>=0xFF8 && aCluster<=0xFFF);
463 Set a cluster to the end of cluster chain marker
465 @param aCluster cluster to set to end of chain marker
467 void CFatMountCB::SetEndOfClusterCh(TInt &aCluster) const
476 Initialize data to represent the root directory
478 @param anEntry Entry to initialise
480 void CFatMountCB::InitializeRootEntry(TFatDirEntry & anEntry) const
482 anEntry.SetName(_L8("ROOT"));
483 anEntry.SetAttributes(KEntryAttDir);
484 anEntry.SetStartCluster(0);
489 Implementation of CMountCB::FileSystemSubType(). Retrieves the sub type of Fat file system
490 and returns the name as a descriptor.
492 @param aName Name of the sub type of Fat file system
493 @return KErrNone if successful; KErrArgument if aName is not long enough; KErrNotReady if
494 the mount is not ready.
496 @see CMountCB::FileSystemSubType()
498 TInt CFatMountCB::SubType(TDes& aName) const
500 if(aName.MaxLength() < 5)
507 aName = KFSSubType_FAT12;
512 aName = KFSSubType_FAT16;
516 // case EInvalidFatType
521 //-------------------------------------------------------------------------------------------------------------------
523 CFatMountCB control method.
524 @param aLevel specifies the operation to perfrom on the mount
525 @param aOption specific option for the given operation
526 @param aParam pointer to generic parameter, its meaning depends on aLevel and aOption
528 @return standard error code.
530 TInt CFatMountCB::MountControl(TInt aLevel, TInt aOption, TAny* aParam)
532 TInt nRes = KErrNotSupported;
534 if(aLevel == ECheckFsMountable)
536 return MntCtl_DoCheckFileSystemMountable();
539 //-- mount state query: check if is in finalised state
540 if(aLevel == EMountStateQuery && aOption == ESQ_IsMountFinalised)
543 nRes = IsFinalised(bFinalised);
546 *((TBool*)aParam) = bFinalised;
552 //-- File System - specific queries
553 if(aLevel == EMountFsParamQuery && aOption == ESQ_GetMaxSupportedFileSize)
554 {//-- this is a query to provide the max. supported file size; aParam is a pointer to TUint64 to return the value
555 *(TUint64*)aParam = KMaxSupportedFatFileSize;
563 //-------------------------------------------------------------------------------------------------------------------
565 Reports whether the specified interface is supported - if it is,
566 the supplied interface object is modified to it
568 @param aInterfaceId The interface of interest
569 @param aInterface The interface object
570 @return KErrNone if the interface is supported, otherwise KErrNotFound
572 @see CMountCB::GetInterface()
574 TInt CFatMountCB::GetInterface(TInt aInterfaceId, TAny*& aInterface,TAny* aInput)
578 case (CMountCB::EFileAccessor):
579 ((CMountCB::MFileAccessor*&) aInterface) = this;
582 case (CMountCB::EGetFileSystemSubType):
583 aInterface = (MFileSystemSubType*) (this);
586 case (CMountCB::EGetClusterSize):
587 aInterface = (MFileSystemClusterSize*) (this);
590 case CMountCB::ELocalBufferSupport:
591 // RAM drives doesn't support local buffers (this results in file caching being disabled)
593 return KErrNotSupported;
595 return LocalDrive()->LocalBufferSupport();
598 ((CProxyDrive*&)aInterface) = LocalDrive();
602 return(CMountCB::GetInterface(aInterfaceId, aInterface, aInput));