userlibandfileserver/fileserver/sfat/sl_fat16.cpp
changeset 0 a41df078684a
child 2 4122176ea935
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfat\sl_fat16.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 
       
    19 #include "sl_std.h"
       
    20 #include "sl_cache.h"
       
    21 
       
    22 const TUint KDefFatResvdSec = 1;    ///< default number of FAT12/16 reserved sectors
       
    23 
       
    24 /**
       
    25 Initialize the format parameters for a normal fixed sized disk
       
    26 Setting set to adhere to Rules of Count of clusters for FAT type
       
    27 
       
    28 @param  aDiskSizeInSectors Size of volume in sectors
       
    29 @return system-wide error code
       
    30 */
       
    31 TInt CFatFormatCB::InitFormatDataForFixedSizeDiskNormal(TInt aDiskSizeInSectors, const TLocalDriveCapsV6& aCaps)
       
    32 	{
       
    33 	if( Drive().IsRemovable() )
       
    34 		iNumberOfFats = KNumberOfFatsExternal;
       
    35 	else
       
    36 		iNumberOfFats = KNumberOfFatsInternal;
       
    37 	
       
    38 	iReservedSectors=KDefFatResvdSec;		
       
    39 	if (aDiskSizeInSectors<4084*1) // < 2MB
       
    40 		{
       
    41 		iRootDirEntries=128;
       
    42 		iSectorsPerCluster=1;
       
    43 		iFileSystemName=KFileSystemName12;
       
    44 		iSectorsPerFat=MaxFat12Sectors();
       
    45    		}
       
    46 	else if (aDiskSizeInSectors<4084*2) // < 4MB (8168 sectors)
       
    47 		{
       
    48 		iRootDirEntries=256; 
       
    49 		iSectorsPerCluster=2;
       
    50 		iFileSystemName=KFileSystemName12;
       
    51 		iSectorsPerFat=MaxFat12Sectors();
       
    52 		}
       
    53 	else if (aDiskSizeInSectors<4084*4) // < 8MB (16336 sectors)
       
    54 		{
       
    55 		iRootDirEntries=512;
       
    56 		iSectorsPerCluster=4;
       
    57 		iFileSystemName=KFileSystemName12;
       
    58 		iSectorsPerFat=MaxFat12Sectors();
       
    59 		}
       
    60 	else if (aDiskSizeInSectors<4084*8) // < 16MB (32672 sectors)
       
    61 		{
       
    62 		iRootDirEntries=512;
       
    63 		iSectorsPerCluster=8;
       
    64 		iFileSystemName=KFileSystemName12;
       
    65 		iSectorsPerFat=MaxFat12Sectors();
       
    66 		}
       
    67 	else	// >= 16Mb - FAT16
       
    68 		{
       
    69 		iFileSystemName=KFileSystemName16;
       
    70 		TInt minSectorsPerCluster=(aDiskSizeInSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
       
    71 		iRootDirEntries=512;
       
    72 		iSectorsPerCluster=1;
       
    73 		while (minSectorsPerCluster>iSectorsPerCluster)
       
    74 			iSectorsPerCluster<<=1;
       
    75 		iSectorsPerFat=MaxFat16Sectors();
       
    76 		}
       
    77 	
       
    78 	// Ensure cluster size is a multiple of the block size
       
    79 	TInt blockSizeInSectors = aCaps.iBlockSize >> iSectorSizeLog2;
       
    80 	__PRINT1(_L("blockSizeInSectors: %d"),blockSizeInSectors);
       
    81 	ASSERT(blockSizeInSectors == 0 || IsPowerOf2(blockSizeInSectors));
       
    82 	if (blockSizeInSectors != 0 && IsPowerOf2(blockSizeInSectors))
       
    83 		{
       
    84 		__PRINT1(_L("iSectorsPerCluster	(old): %d"),iSectorsPerCluster);
       
    85 		AdjustClusterSize(blockSizeInSectors);
       
    86 		__PRINT1(_L("iSectorsPerCluster	(new): %d"),iSectorsPerCluster);
       
    87 		}
       
    88 	
       
    89 	// Align first data sector on an erase block boundary if
       
    90 	// (1) the iEraseBlockSize is specified
       
    91 	// (2) the start of the partition is already aligned to an erase block boundary, 
       
    92 	//     i.e. iHiddenSectors is zero or a multiple of iEraseBlockSize
       
    93 	__PRINT1(_L("iHiddenSectors: %d"),iHiddenSectors);
       
    94 	TInt eraseblockSizeInSectors = aCaps.iEraseBlockSize >> iSectorSizeLog2;
       
    95 	__PRINT1(_L("eraseblockSizeInSectors: %d"),eraseblockSizeInSectors);
       
    96 	ASSERT(eraseblockSizeInSectors == 0 || IsPowerOf2(eraseblockSizeInSectors));	
       
    97 	ASSERT(eraseblockSizeInSectors == 0 || eraseblockSizeInSectors >= blockSizeInSectors);
       
    98 	if ((eraseblockSizeInSectors != 0) &&
       
    99 		(iHiddenSectors % eraseblockSizeInSectors == 0) &&	
       
   100 		(IsPowerOf2(eraseblockSizeInSectors)) &&
       
   101 		(eraseblockSizeInSectors >= blockSizeInSectors))
       
   102 		{
       
   103 		TInt r = AdjustFirstDataSectorAlignment(eraseblockSizeInSectors);
       
   104 		ASSERT(r == KErrNone);
       
   105 		(void) r;
       
   106 		}
       
   107 	__PRINT1(_L("iReservedSectors: %d"),iReservedSectors);
       
   108 	__PRINT1(_L("FirstDataSector: %d"), FirstDataSector());
       
   109 
       
   110     return KErrNone;
       
   111 	}
       
   112 
       
   113 TInt CFatFormatCB::FirstDataSector() const
       
   114 	{
       
   115 	TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
       
   116     return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors;
       
   117 	}
       
   118 
       
   119 void CFatFormatCB::AdjustClusterSize(TInt aRecommendedSectorsPerCluster)
       
   120 	{
       
   121     const TInt KMaxSecPerCluster = 64;	// 32K
       
   122 	while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2))
       
   123 		iSectorsPerCluster<<= 1;
       
   124 	}
       
   125 
       
   126 // AdjustFirstDataSectorAlignment()
       
   127 // Attempts to align the first data sector on an erase block boundary by modifying the
       
   128 // number of reserved sectors.
       
   129 TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TInt aEraseBlockSizeInSectors)
       
   130 	{
       
   131 	const TBool bFat16 = Is16BitFat();
       
   132 
       
   133 	// Save these 2 values in the event of a convergence failure; this should 
       
   134 	// hopefully never happen, but we will cater for this in release mode to be safe,
       
   135 	TInt reservedSectorsSaved = iReservedSectors;
       
   136 	TInt sectorsPerFatSaved = iSectorsPerFat;
       
   137 
       
   138 	TInt reservedSectorsOld = 0;
       
   139 
       
   140 	// zero for FAT32
       
   141 	TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
       
   142 	TInt fatSectors = 0;
       
   143 
       
   144 	TInt KMaxIterations = 10;
       
   145 	TInt n;
       
   146 	for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++)
       
   147 		{
       
   148 		reservedSectorsOld = iReservedSectors;
       
   149 
       
   150 		iSectorsPerFat = bFat16 ? MaxFat16Sectors() : MaxFat12Sectors();
       
   151 
       
   152 		fatSectors = iSectorsPerFat * iNumberOfFats;
       
   153 
       
   154 		// calculate number of blocks
       
   155 		TInt nBlocks = (iReservedSectors + fatSectors + rootDirSectors + aEraseBlockSizeInSectors-1) / aEraseBlockSizeInSectors;
       
   156 
       
   157 		iReservedSectors = (nBlocks * aEraseBlockSizeInSectors) - rootDirSectors - fatSectors;
       
   158 		}
       
   159 	
       
   160 	ASSERT(iReservedSectors >= (TInt) KDefFatResvdSec);
       
   161 
       
   162 	if ((FirstDataSector() & (aEraseBlockSizeInSectors-1)) == 0)
       
   163 		{
       
   164 		return KErrNone;
       
   165 		}
       
   166 	else
       
   167 		{
       
   168 		iReservedSectors = reservedSectorsSaved;
       
   169 		iSectorsPerFat = sectorsPerFatSaved;
       
   170 		return KErrGeneral;
       
   171 		}
       
   172 	}
       
   173 
       
   174 /**
       
   175     Initialize the user specific format parameters for fixed sized disk.
       
   176     
       
   177     @param  aDiskSizeInSectors disk size in sectors
       
   178     @return system-wide error code
       
   179 */
       
   180 TInt  CFatFormatCB::InitFormatDataForFixedSizeDiskUser(TInt aDiskSizeInSectors)
       
   181 	{
       
   182     //-- KErrArgument will be returned if iSpecialInfo().iFATBits isn't one of EFB32, EFB16, EFB32
       
   183 
       
   184     if(iSpecialInfo().iFlags & TLDFormatInfo::EOneFatTable)
       
   185 		iNumberOfFats = 1;
       
   186     else if(iSpecialInfo().iFlags & TLDFormatInfo::ETwoFatTables)
       
   187 		iNumberOfFats = 2;
       
   188     else if(Drive().IsRemovable())
       
   189 		iNumberOfFats = KNumberOfFatsExternal;
       
   190 	else 
       
   191 		iNumberOfFats = KNumberOfFatsInternal;
       
   192 
       
   193 
       
   194     if(iSpecialInfo().iReservedSectors == 0)
       
   195         iReservedSectors = KDefFatResvdSec; //-- user hasn't specified reserved sectors count, use default (FAT12/16)
       
   196     else
       
   197         iReservedSectors = iSpecialInfo().iReservedSectors;
       
   198 
       
   199 
       
   200     const TInt KMaxSecPerCluster = 64; 
       
   201 	const TInt KDefaultSecPerCluster= 8;   //-- default value, if the iSpecialInfo().iSectorsPerCluster isn't specified
       
   202 	
       
   203     iSectorsPerCluster = iSpecialInfo().iSectorsPerCluster;
       
   204     if(iSectorsPerCluster <= 0)
       
   205         {//-- default value, user hasn't specified TLDFormatInfo::iSectorsPerCluster
       
   206         iSectorsPerCluster = KDefaultSecPerCluster; //-- will be adjusted later
       
   207         }
       
   208     else
       
   209         {
       
   210         iSectorsPerCluster = Min(1<<Log2(iSectorsPerCluster), KMaxSecPerCluster);
       
   211 	    }
       
   212 
       
   213     //-----------------------------------------
       
   214 
       
   215 	if (aDiskSizeInSectors < 4096) // < 2MB
       
   216         {
       
   217         iSectorsPerCluster = 1;
       
   218 		iRootDirEntries = 128;
       
   219         }
       
   220 	else if (aDiskSizeInSectors < 8192) // < 4MB
       
   221         {
       
   222         iSectorsPerCluster = Min(iSectorsPerCluster, 2);
       
   223 		iRootDirEntries = 256;
       
   224         }
       
   225 	else if (aDiskSizeInSectors < 32768) // < 16MB
       
   226         {
       
   227         iSectorsPerCluster = Min(iSectorsPerCluster, 4);
       
   228 		iRootDirEntries = 512;
       
   229         }
       
   230 	else if (aDiskSizeInSectors < 131072) // < 64MB
       
   231         {
       
   232         iSectorsPerCluster = Min(iSectorsPerCluster, 8);
       
   233 		iRootDirEntries = 512;
       
   234         }
       
   235 	else	// >= 64Mb
       
   236 		iRootDirEntries = 512;
       
   237 
       
   238     //-----------------------------------------
       
   239 
       
   240 	TLDFormatInfo::TFATBits fatBits = iSpecialInfo().iFATBits;
       
   241 	if (fatBits == TLDFormatInfo::EFBDontCare)
       
   242 		{
       
   243         const TFatType fatType = SuggestFatType();
       
   244 		switch(fatType)
       
   245 			{
       
   246 			case EFat12:
       
   247 				fatBits = TLDFormatInfo::EFB12;
       
   248 				break;
       
   249 			case EFat16:
       
   250 				fatBits = TLDFormatInfo::EFB16;
       
   251 				break;
       
   252 			case EFat32:
       
   253 				fatBits = TLDFormatInfo::EFB32;
       
   254 				break;
       
   255 			case EInvalid:
       
   256 				ASSERT(0);
       
   257 			}
       
   258 		}
       
   259 
       
   260     TFatType reqFatType(EInvalid); //-- requested FAT type
       
   261 
       
   262     switch (fatBits)
       
   263         {
       
   264         case TLDFormatInfo::EFB12:
       
   265         iFileSystemName=KFileSystemName12;
       
   266         iSectorsPerFat=MaxFat12Sectors();
       
   267         reqFatType = EFat12;
       
   268         break;
       
   269 
       
   270         case TLDFormatInfo::EFB16:
       
   271         iFileSystemName=KFileSystemName16;
       
   272 		iSectorsPerFat=MaxFat16Sectors();
       
   273         reqFatType = EFat16;
       
   274         break;
       
   275         
       
   276         case TLDFormatInfo::EFB32:
       
   277         __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() FAT32 Not supported!"));
       
   278         return KErrNotSupported;
       
   279 
       
   280         default:
       
   281         __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() Incorrect FAT type specifier!"));
       
   282         return KErrArgument;
       
   283         };
       
   284 
       
   285         //-- check if we can format the volume with requested FAT type
       
   286         const TFatType fatType = SuggestFatType();
       
   287         if(fatType != reqFatType)
       
   288         {//-- volume metrics don't correspond to the requested FAT type
       
   289             __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() FAT type mismatch!"));
       
   290             return KErrArgument;
       
   291         }
       
   292 
       
   293 
       
   294     return KErrNone;
       
   295 	}
       
   296 
       
   297 /**
       
   298     Initialize the format parameters for a custom fixed sized disk
       
   299 
       
   300     @param  aFormatInfo The custom format parameters
       
   301     @return system-wide error code
       
   302 */
       
   303 TInt CFatFormatCB::InitFormatDataForFixedSizeDiskCustom(const TLDFormatInfo& aFormatInfo)
       
   304 	{
       
   305 	if(aFormatInfo.iFlags & TLDFormatInfo::EOneFatTable)
       
   306 		iNumberOfFats = 1;
       
   307     else if(aFormatInfo.iFlags & TLDFormatInfo::ETwoFatTables)
       
   308 		iNumberOfFats = 2;
       
   309     else if(Drive().IsRemovable())
       
   310 		iNumberOfFats = KNumberOfFatsExternal;
       
   311 	else
       
   312 		iNumberOfFats = KNumberOfFatsInternal;	
       
   313 
       
   314 	iRootDirEntries=512;
       
   315 
       
   316 	iSectorsPerCluster = aFormatInfo.iSectorsPerCluster;
       
   317 	iSectorsPerTrack   = aFormatInfo.iSectorsPerTrack;
       
   318 	iNumberOfHeads     = aFormatInfo.iNumberOfSides;
       
   319 	iReservedSectors   = aFormatInfo.iReservedSectors ? aFormatInfo.iReservedSectors : KDefFatResvdSec;
       
   320 	
       
   321     switch (aFormatInfo.iFATBits)
       
   322 		{
       
   323 		case TLDFormatInfo::EFB12:
       
   324 			iFileSystemName = KFileSystemName12;
       
   325 			iSectorsPerFat  = MaxFat12Sectors();
       
   326 			break;
       
   327 
       
   328 		case TLDFormatInfo::EFB16:
       
   329 			iFileSystemName = KFileSystemName16;
       
   330 			iSectorsPerFat  = MaxFat16Sectors();
       
   331             break;
       
   332 
       
   333 		default:
       
   334 			{
       
   335 			TInt64 clusters64 = (aFormatInfo.iCapacity / KDefaultSectorSize) / iSectorsPerCluster;
       
   336 			TInt clusters = I64LOW(clusters64);
       
   337 			if (clusters < 4085)
       
   338 				{
       
   339 				iFileSystemName = KFileSystemName12;
       
   340 				iSectorsPerFat  = MaxFat12Sectors();
       
   341 				}
       
   342 			else
       
   343 				{
       
   344 				iFileSystemName = KFileSystemName16;
       
   345 				iSectorsPerFat  = MaxFat16Sectors();
       
   346                 }
       
   347 			}
       
   348 		}
       
   349 
       
   350     return KErrNone;
       
   351 	}
       
   352 
       
   353 void CFatFormatCB::RecordOldInfoL()
       
   354     {
       
   355 	__PRINT(_L("CFatFormatCB::RecordOldInfoL"));
       
   356     // Check if mount or disk is corrupt
       
   357     // This should be stored in member variable because FatMount is remounted
       
   358     //  every time RFormat::Next() gets called thus FatMount().Initialised()
       
   359     //  will be inconsistent with previous state.
       
   360 	TLocalDriveCapsV3Buf caps;
       
   361 	User::LeaveIfError(LocalDrive()->Caps(caps));
       
   362 	iVariableSize=((caps().iMediaAtt)&KMediaAttVariableSize) ? (TBool)ETrue : (TBool)EFalse;
       
   363     iDiskCorrupt = !FatMount().ConsistentState();
       
   364     iBadClusters.Reset();
       
   365     iBadSectors.Reset();
       
   366     if (!iVariableSize && !iDiskCorrupt && (iMode & EQuickFormat))
       
   367         {
       
   368         iOldFirstFreeSector = FatMount().iFirstFreeByte >> FatMount().SectorSizeLog2();
       
   369         iOldSectorsPerCluster = FatMount().SectorsPerCluster();
       
   370         
       
   371         FatMount().FAT().InvalidateCacheL(); //-- invalidate whole FAT cache
       
   372 
       
   373     	const TInt maxClusterNum = FatMount().iUsableClusters + KFatFirstSearchCluster;
       
   374 
       
   375         // Collect bad cluster information from current FAT table
       
   376         const TUint32 mark = FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit;
       
   377         for (TInt i=KFatFirstSearchCluster; i<maxClusterNum; i++)
       
   378             if (FatMount().FAT().ReadL(i) == mark)
       
   379                 iBadClusters.AppendL(i);
       
   380         }
       
   381     }
       
   382 
       
   383 /**
       
   384 Create the boot sector on media for the volume. 
       
   385 
       
   386 @leave System wide error codes
       
   387 */
       
   388 void CFatFormatCB::CreateBootSectorL()
       
   389 	{
       
   390 	__PRINT1(_L("CFatFormatCB::CreateBootSector() drive:%d"),DriveNumber());
       
   391 
       
   392 	TFatBootSector bootSector;
       
   393 
       
   394 	bootSector.SetVendorID(KDefaultVendorID);
       
   395 	bootSector.SetBytesPerSector(iBytesPerSector);
       
   396 	bootSector.SetSectorsPerCluster(iSectorsPerCluster);
       
   397 	bootSector.SetReservedSectors(iReservedSectors);
       
   398 	bootSector.SetNumberOfFats(iNumberOfFats);
       
   399 	bootSector.SetRootDirEntries(iRootDirEntries);
       
   400 	if (iMaxDiskSectors<(TInt)KMaxTUint16)
       
   401 		bootSector.SetTotalSectors(iMaxDiskSectors);
       
   402 	else
       
   403 		{
       
   404 		bootSector.SetTotalSectors(0);
       
   405 		bootSector.SetHugeSectors(iMaxDiskSectors);
       
   406 		}
       
   407 	TInt numberOfClusters=iMaxDiskSectors/iSectorsPerCluster;
       
   408 	if (numberOfClusters>(TInt)KMaxTUint16)
       
   409 		User::Leave(KErrTooBig);
       
   410 	bootSector.SetFatSectors(iSectorsPerFat);
       
   411 	bootSector.SetReservedByte(0);
       
   412 	TTime timeID;
       
   413 	timeID.HomeTime();						//	System time in future?
       
   414 	bootSector.SetUniqueID(I64LOW(timeID.Int64()));	//	Generate UniqueID from time
       
   415 	bootSector.SetVolumeLabel(_L8(""));
       
   416 	bootSector.SetFileSysType(iFileSystemName);
       
   417 // Floppy specific info:
       
   418 	bootSector.SetJumpInstruction();
       
   419 	bootSector.SetMediaDescriptor(KBootSectorMediaDescriptor);
       
   420 	bootSector.SetNumberOfHeads(iNumberOfHeads);
       
   421 	bootSector.SetHiddenSectors(iHiddenSectors);
       
   422 	bootSector.SetSectorsPerTrack(iSectorsPerTrack);
       
   423 	bootSector.SetPhysicalDriveNumber(128);
       
   424 	bootSector.SetExtendedBootSignature(0x29);
       
   425 
       
   426 	
       
   427     User::LeaveIfError(FatMount().DoWriteBootSector(KBootSectorNum*bootSector.BytesPerSector(), bootSector));
       
   428 	}
       
   429 
       
   430 //-------------------------------------------------------------------------------------------------------------------
       
   431 
       
   432 /**
       
   433 Format a disk section, called iteratively to erase whole of media, on last iteration
       
   434 creates an empty volume. If called with quick formatonly erases the Fat leaving the
       
   435 rest of the volume intact.
       
   436 
       
   437 @leave System wide error code
       
   438 */
       
   439 void CFatFormatCB::DoFormatStepL()
       
   440 	{
       
   441 	if (iFormatInfo.iFormatIsCurrent==EFalse)
       
   442 		{
       
   443 		if (iMode & EForceErase)
       
   444 			{
       
   445 			TInt r = FatMount().ErasePassword();
       
   446 			User::LeaveIfError(r);
       
   447 			// CFatMountCB::ErasePassword() calls TBusLocalDrive::ForceRemount(), 
       
   448 			// so need to stop a remount from occurring in next call to :
       
   449 			// TFsFormatNext::DoRequestL((), TDrive::CheckMount().
       
   450 			FatMount().Drive().SetChanged(EFalse);
       
   451 			}
       
   452 
       
   453         RecordOldInfoL();
       
   454         InitializeFormatDataL();
       
   455 		FatMount().DoDismount();
       
   456 		if (iVariableSize)
       
   457 			FatMount().ReduceSizeL(0,I64LOW(FatMount().iSize));
       
   458 		}
       
   459     //
       
   460     // Blank disk if not EQuickFormat
       
   461     //
       
   462 	if (!iVariableSize && !(iMode & EQuickFormat) && iCurrentStep)
       
   463 		{
       
   464 		if (iFormatInfo.iFormatIsCurrent == EFalse)
       
   465 			{//-- firstly invalidate sectors 0-6 inclusive
       
   466 	        DoZeroFillMediaL(0, 7*iBytesPerSector);
       
   467 			}
       
   468 
       
   469 		TInt ret=FatMount().LocalDrive()->Format(iFormatInfo);
       
   470 		if (ret!=KErrNone && ret!=KErrEof) // Handle format error
       
   471 		    ret = HandleCorrupt(ret);
       
   472         if (ret!=KErrNone && ret!=KErrEof) // KErrEof could be set by LocalDrive()->Format()
       
   473 		    User::Leave(ret);
       
   474 		if (ret==KErrNone)
       
   475 			{
       
   476 			iCurrentStep=100-(100*iFormatInfo.i512ByteSectorsFormatted)/iMaxDiskSectors;
       
   477 			if (iCurrentStep<=0)
       
   478 				iCurrentStep=1;
       
   479 			return;
       
   480 			}
       
   481 		}
       
   482 
       
   483 	// ReMount since MBR may have been rewritten and partition may have moved / changed size
       
   484 	TInt ret = LocalDrive()->ForceRemount(0);
       
   485 	if (ret != KErrNone && ret != KErrNotSupported)
       
   486 		User::Leave(ret);
       
   487 
       
   488 	// MBR may have changed, so need to re-read iHiddenSectors etc.before BPB is written
       
   489 	InitializeFormatDataL(); 
       
   490 
       
   491     // Translate bad sector number to cluster number which contains that sector
       
   492     // This only happens in full format, in quick format they are already cluster numbers
       
   493     if (!iVariableSize && !(iMode & EQuickFormat))
       
   494         User::LeaveIfError(BadSectorToCluster());
       
   495 
       
   496     //
       
   497     // Do the rest of the disk in one lump
       
   498     //
       
   499 	iCurrentStep=0;
       
   500 	
       
   501 
       
   502     //-- zero-fill media from position 0 to the FAT end, i.e main & backup boot sector, FSInfo and its copy and all FATs
       
   503     const TUint32 posFatEnd = ((iSectorsPerFat*iNumberOfFats) + iReservedSectors) * iBytesPerSector; //-- last FAT end position
       
   504 	
       
   505     if (iVariableSize)
       
   506 		FatMount().EnlargeL(posFatEnd); 
       
   507 
       
   508     DoZeroFillMediaL(0, posFatEnd);
       
   509 
       
   510     //-- Zero fill root directory
       
   511     const TInt rootDirSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); 
       
   512     const TInt rootDirSize   = iRootDirEntries * KSizeOfFatDirEntry; //-- size in bytes
       
   513             
       
   514     const TUint32 posRootDirStart = rootDirSector * iBytesPerSector;
       
   515     const TUint32 posRootDirEnd   = posRootDirStart + rootDirSize;
       
   516 
       
   517     const TInt numOfRootSectors=(rootDirSize%iBytesPerSector) ? (rootDirSize/iBytesPerSector+1) : (rootDirSize/iBytesPerSector);
       
   518 	if (iVariableSize)
       
   519 	    FatMount().EnlargeL(iBytesPerSector*numOfRootSectors);
       
   520 
       
   521     DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
       
   522 
       
   523 	// Enlarge ram drive to take into account rounding of
       
   524 	// data start to cluster boundary
       
   525 	if(iVariableSize && iSectorsPerCluster!=1)
       
   526 		{
       
   527 		const TInt firstFreeSector=rootDirSector+numOfRootSectors;
       
   528 		const TInt firstFreeCluster=firstFreeSector%iSectorsPerCluster ? firstFreeSector/iSectorsPerCluster+1 : firstFreeSector/iSectorsPerCluster;
       
   529 		const TInt alignedSector=firstFreeCluster*iSectorsPerCluster;
       
   530 		if(alignedSector!=firstFreeSector)
       
   531 			FatMount().EnlargeL((alignedSector-firstFreeSector)*iBytesPerSector);
       
   532 		}
       
   533 
       
   534     //-- FAT[0] must contain media descriptor in the low byte, FAT[1] for fat16/32 may contain some flags
       
   535 	TBuf8<4> startFat(4);
       
   536     startFat.Fill(0xFF);
       
   537     
       
   538     if(iVariableSize||Is16BitFat()) //-- FAT16 or RAM drive which is always FAT16
       
   539         {
       
   540         startFat.SetLength(4);
       
   541         }
       
   542     else //-- FAT12
       
   543         {
       
   544         startFat.SetLength(3);
       
   545         }
       
   546      
       
   547     startFat[0]=KBootSectorMediaDescriptor; 
       
   548 
       
   549     //-- write FAT[0] and FAT[1] entries to all copies of FAT
       
   550 	for(TInt i=0;i<iNumberOfFats;i++)
       
   551 		{
       
   552 		User::LeaveIfError(LocalDrive()->Write(iBytesPerSector*(iReservedSectors+(iSectorsPerFat*i)),startFat));
       
   553 		}
       
   554 
       
   555     //-- create boot sectors
       
   556 	CreateBootSectorL();
       
   557 
       
   558     //-- here we have bad clusters numbers saved by the quick format
       
   559     //-- Interpret old bad cluster number to new cluster number and mark new bad clusters
       
   560     if (!iVariableSize && iBadClusters.Count()>0)
       
   561         {
       
   562         //-- Here we need fully mounted volume, so mount it normally.
       
   563 	    FatMount().MountL(EFalse);
       
   564 
       
   565         iBadClusters.Sort();
       
   566         TranslateL();
       
   567         TInt mark = FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit;
       
   568         TInt i;
       
   569         
       
   570         for (i=0; i<iBadClusters.Count(); ++i)
       
   571             FatMount().FAT().WriteL(iBadClusters[i], mark);
       
   572         
       
   573         FatMount().FAT().FlushL();
       
   574 #if defined(_DEBUG)
       
   575 	TInt r=FatMount().CheckDisk();
       
   576 	__PRINT1(_L("CFatFormatCB::DoFormatStepL() CheckDisk res: %d"),r);
       
   577 #endif
       
   578         }
       
   579         else
       
   580         {
       
   581         //-- We do not need to perform full mount in this case, the TDrive object will be marked as changed in ~CFormatCB and the
       
   582         //-- mount will be closed. Therefore on the first access to it it will be mounted normally.
       
   583         FatMount().MountL(ETrue); //-- force mount
       
   584         }
       
   585 
       
   586     __PRINT1(_L("CFatFormatCB::DoFormatStepL() Format complete drv:%d"), DriveNumber());
       
   587 	}
       
   588 
       
   589 TInt CFatFormatCB::BadSectorToCluster()
       
   590     {
       
   591     const TInt sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2);
       
   592     TInt firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
       
   593 
       
   594     TInt i, r;
       
   595     for (i=0; i<iBadSectors.Count(); ++i)
       
   596         {
       
   597         TInt badSector = iBadSectors[i];
       
   598         // Check in rare case that corrupt in critical area
       
   599         // which includes bootsector, FAT table, (and root dir if not FAT32)
       
   600         if (badSector < firstFreeSector)
       
   601             {
       
   602             if (badSector == 0) // Boot sector corrupt
       
   603                 return KErrCorrupt;
       
   604             if (badSector < iReservedSectors) // Harmless in reserved area
       
   605                 continue;
       
   606             // Extend reserved area to cover bad sector
       
   607             iReservedSectors = badSector + 1;
       
   608             firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
       
   609             continue;
       
   610             }
       
   611 
       
   612         // Figure out bad cluster number and record it
       
   613         TInt cluster = (badSector-firstFreeSector)/iSectorsPerCluster + KFatFirstSearchCluster;
       
   614         if (iBadClusters.Find(cluster) == KErrNotFound)
       
   615             {
       
   616             if ((r=iBadClusters.Append(cluster)) != KErrNone)
       
   617                 return r;
       
   618             }
       
   619         }
       
   620     return KErrNone;
       
   621     }
       
   622