userlibandfileserver/fileserver/sfat32/sl_fatmisc32.cpp
changeset 281 13fbfa31d2ba
parent 90 947f0dc9f7a8
child 271 dc268b18d709
equal deleted inserted replaced
266:0008ccd16016 281:13fbfa31d2ba
    16 //
    16 //
    17 
    17 
    18 #include "sl_std.h"
    18 #include "sl_std.h"
    19 #include "sl_cache.h"
    19 #include "sl_cache.h"
    20 
    20 
    21 /**
    21 //-------------------------------------------------------------------------------------------------------------------
    22 @return ETrue if it is Fat32
       
    23 */
       
    24 TBool CFatFormatCB::Is32BitFat() const
       
    25 	{
       
    26 	return(iFileSystemName==KFileSystemName32);
       
    27 	}
       
    28 
       
    29 /**
       
    30 @return ETrue if it is Fat16
       
    31 */
       
    32 TBool CFatFormatCB::Is16BitFat() const
       
    33 	{
       
    34     return(iFileSystemName==KFileSystemName16);
       
    35     }
       
    36 
       
    37 /**
    22 /**
    38 Calculate the FAT size in sectors for a Fat32 volume
    23 Calculate the FAT size in sectors for a Fat32 volume
    39 
    24 
    40 @return The number of sectors
    25 @return The number of sectors
    41 */
    26 */
    67 #endif
    52 #endif
    68 }
    53 }
    69 
    54 
    70 //-------------------------------------------------------------------------------------------------------------------
    55 //-------------------------------------------------------------------------------------------------------------------
    71 
    56 
       
    57 TInt CFatFormatCB::FirstDataSector() const
       
    58 	{
       
    59 	TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
       
    60     return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors;
       
    61 	}
       
    62 
       
    63 void CFatFormatCB::AdjustClusterSize(TUint aRecommendedSectorsPerCluster)
       
    64 	{
       
    65     const TUint KMaxSecPerCluster = 64;	// 32K
       
    66 
       
    67 	while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2))
       
    68 		iSectorsPerCluster<<= 1;
       
    69 
       
    70 	}
       
    71 
       
    72 // AdjustFirstDataSectorAlignment()
       
    73 // Attempts to align the first data sector on an erase block boundary by modifying the
       
    74 // number of reserved sectors.
       
    75 TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TUint aEraseBlockSizeInSectors)
       
    76 	{
       
    77 	const TBool bFat16 = Is16BitFat();
       
    78     const TBool bFat32 = Is32BitFat();
       
    79 
       
    80 	// Save these 2 values in the event of a convergence failure; this should 
       
    81 	// hopefully never happen, but we will cater for this in release mode to be safe,
       
    82 	TUint reservedSectorsSaved = iReservedSectors;
       
    83 	TUint sectorsPerFatSaved = iSectorsPerFat;
       
    84 
       
    85 	TUint reservedSectorsOld = 0;
       
    86 
       
    87 	// zero for FAT32
       
    88 	TUint rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
       
    89 	TUint fatSectors = 0;
       
    90 
       
    91 	TUint KMaxIterations = 10;
       
    92 	TUint n;
       
    93 	for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++)
       
    94 		{
       
    95 		reservedSectorsOld = iReservedSectors;
       
    96 
       
    97 		iSectorsPerFat = bFat32 ? MaxFat32Sectors() : bFat16 ? MaxFat16Sectors() : MaxFat12Sectors();
       
    98 
       
    99 		fatSectors = iSectorsPerFat * iNumberOfFats;
       
   100 
       
   101 		// calculate number of blocks
       
   102 		TInt  nBlocks = (iReservedSectors + fatSectors + rootDirSectors + aEraseBlockSizeInSectors-1) / aEraseBlockSizeInSectors;
       
   103 
       
   104 		iReservedSectors = (nBlocks * aEraseBlockSizeInSectors) - rootDirSectors - fatSectors;
       
   105 		}
       
   106 	
       
   107 	ASSERT(iReservedSectors >= (bFat32 ? KDefFat32ResvdSec : KDefFatResvdSec));
       
   108 
       
   109 	if ((FirstDataSector() & (aEraseBlockSizeInSectors-1)) == 0)
       
   110 		{
       
   111 		return KErrNone;
       
   112 		}
       
   113 	else
       
   114 		{
       
   115 		iReservedSectors = reservedSectorsSaved;
       
   116 		iSectorsPerFat = sectorsPerFatSaved;
       
   117 		return KErrGeneral;
       
   118 		}
       
   119 	}
       
   120 
       
   121 
       
   122 //-------------------------------------------------------------------------------------------------------------------
       
   123 
    72 /**
   124 /**
    73 Initialize the format parameters for a normal fixed sized disk
   125 Create the boot sector on media for the volume. For FAT32 also creates a backup copy of the boot sector.
    74 Setting set to adhere to Rules of Count of clusters for FAT type
   126 
    75 
   127 @leave System wide error codes
    76 @param  aDiskSizeInSectors Size of volume in sectors
       
    77 @return system-wide error code
       
    78 */
   128 */
    79 TInt  CFatFormatCB::InitFormatDataForFixedSizeDiskNormal(TUint aDiskSizeInSectors, const TLocalDriveCapsV6& aCaps)
   129 void CFatFormatCB::CreateBootSectorL()
    80 	{
   130 	{
    81 	__PRINT1(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskNormal() sectors:%d"), aDiskSizeInSectors);
   131 	__PRINT1(_L("CFatFormatCB::CreateBootSector() drive:%d"),DriveNumber());
       
   132 
       
   133     _LIT8(KName_Fat12,"FAT12   ");    ///< Name in BPB given to a Fat12 volume
       
   134     _LIT8(KName_Fat16,"FAT16   ");    ///< Name in BPB given to a Fat16 volume
       
   135     _LIT8(KName_Fat32,"FAT32   ");    ///< Name in BPB given to a Fat32 volume
       
   136     _LIT8(KDefaultVendorID, "EPOC");  ///< Vendor Name for BPB for any volume formated using a Symbian OS device
       
   137 
       
   138     const TBool bFat32 = Is32BitFat();
       
   139     
       
   140     TFatBootSector bootSector;
       
   141 
       
   142 	bootSector.SetVendorID(KDefaultVendorID);
       
   143 	bootSector.SetBytesPerSector(iBytesPerSector);
       
   144 	bootSector.SetSectorsPerCluster(iSectorsPerCluster);
       
   145 	bootSector.SetReservedSectors(iReservedSectors);
       
   146 	bootSector.SetNumberOfFats(iNumberOfFats);
       
   147 	iCountOfClusters=iMaxDiskSectors/iSectorsPerCluster;
       
   148 	if (!bFat32)
       
   149 		{
       
   150 		if (iCountOfClusters>(TInt)KMaxTUint16)
       
   151 			User::Leave(KErrTooBig);
       
   152 		}
       
   153 
       
   154 	bootSector.SetReservedByte(0);
       
   155 	TTime timeID;
       
   156 	timeID.HomeTime();
       
   157 	bootSector.SetUniqueID(I64LOW(timeID.Int64()));	//	Generate Volume UniqueID from time
       
   158 	bootSector.SetVolumeLabel(_L8(""));
       
   159 	
       
   160     //-- set a text string in BPB that corresponds to the FS type
       
   161     switch(FatType())
       
   162         {
       
   163         case EFat12:
       
   164             bootSector.SetFileSysType(KName_Fat12);
       
   165         break;
       
   166         
       
   167         case EFat16:
       
   168             bootSector.SetFileSysType(KName_Fat16);
       
   169         break;
       
   170         
       
   171         case EFat32:
       
   172             bootSector.SetFileSysType(KName_Fat32);
       
   173         break;
       
   174 
       
   175         default:
       
   176             ASSERT(0);
       
   177             User::Leave(KErrArgument);
       
   178         };
       
   179 
       
   180 
       
   181 
       
   182 	bootSector.SetJumpInstruction();
       
   183 	bootSector.SetMediaDescriptor(KBootSectorMediaDescriptor);
       
   184 	bootSector.SetNumberOfHeads(iNumberOfHeads);
       
   185 	bootSector.SetHiddenSectors(iHiddenSectors);
       
   186 	bootSector.SetSectorsPerTrack(iSectorsPerTrack);
       
   187 	bootSector.SetPhysicalDriveNumber(128);
       
   188 	bootSector.SetExtendedBootSignature(0x29);
       
   189 
       
   190 	if(bFat32)
       
   191 		{
       
   192 		bootSector.SetFatSectors(0);
       
   193 		bootSector.SetFatSectors32(iSectorsPerFat);
       
   194 		bootSector.SetRootDirEntries(0);
       
   195 		bootSector.SetTotalSectors(0);
       
   196 		bootSector.SetHugeSectors(iMaxDiskSectors);
       
   197 		bootSector.SetFATFlags(0);			
       
   198 		bootSector.SetVersionNumber(0x00);	
       
   199 		bootSector.SetRootClusterNum(iRootClusterNum);
       
   200 		bootSector.SetFSInfoSectorNum(KFSInfoSectorNum);	
       
   201         bootSector.SetBkBootRecSector(KBkBootSectorNum);
       
   202 		}
       
   203 	else//fat12 and 16
       
   204 		{
       
   205 		bootSector.SetFatSectors32(0);
       
   206 		bootSector.SetFatSectors(iSectorsPerFat);
       
   207 		bootSector.SetRootDirEntries(iRootDirEntries);
       
   208 
       
   209 		if (iMaxDiskSectors<=KMaxTUint16)
       
   210 			{
       
   211 			bootSector.SetTotalSectors(iMaxDiskSectors);
       
   212 			bootSector.SetHugeSectors(0);
       
   213 			}
       
   214 		else
       
   215 			{
       
   216 			bootSector.SetTotalSectors(0);
       
   217 			bootSector.SetHugeSectors(iMaxDiskSectors);
       
   218 			}
       
   219 		}
       
   220 
       
   221 	//-- write main boot sector to the first sector on media
       
   222     User::LeaveIfError(FatMount().DoWriteBootSector(KBootSectorNum*bootSector.BytesPerSector(), bootSector));
       
   223 	
       
   224     //-- for FAT32 write backup copy of the boot sector
       
   225     if(bFat32)
       
   226         {
       
   227         User::LeaveIfError(FatMount().DoWriteBootSector(KBkBootSectorNum*bootSector.BytesPerSector(), bootSector));    
       
   228         }
       
   229 
       
   230     }
       
   231 
       
   232 //-------------------------------------------------------------------------------------------------------------------
       
   233 
       
   234 /**
       
   235 Format a disk section, called iteratively to erase whole of media, on last iteration
       
   236 creates an empty volume. If called with quick formatonly erases the Fat leaving the
       
   237 rest of the volume intact.
       
   238 
       
   239 @leave System wide error code
       
   240 */
       
   241 void CFatFormatCB::DoFormatStepL()
       
   242 	{
       
   243 	if (iFormatInfo.iFormatIsCurrent==EFalse)
       
   244 		{ // Only done first time through
       
   245 		if (iMode & EForceErase)
       
   246 			{
       
   247 			TInt r = FatMount().ErasePassword();
       
   248 			User::LeaveIfError(r);
       
   249 			// CFatMountCB::ErasePassword() calls TBusLocalDrive::ForceRemount(),
       
   250 			// so need to stop a remount from occurring in next call to :
       
   251 			// TFsFormatNext::DoRequestL((), TDrive::CheckMount().
       
   252 			FatMount().Drive().SetChanged(EFalse);
       
   253 			}
       
   254 
       
   255         RecordOldInfoL();
       
   256 		InitializeFormatDataL();
       
   257 		FatMount().DoDismount();
       
   258 		if (iVariableSize)
       
   259 			FatMount().ReduceSizeL(0,I64LOW(FatMount().iSize));
       
   260 		}
       
   261     //
       
   262     // Blank disk if not EQuickFormat
       
   263     //
       
   264 	if (!iVariableSize && !(iMode & EQuickFormat) && iCurrentStep)
       
   265 		{
       
   266 		if (iFormatInfo.iFormatIsCurrent == EFalse)
       
   267 			{//-- firstly invalidate sectors 0-6 inclusive, they may contain main boot sector, backup boot sector and FSInfo sector.
       
   268 	        DoZeroFillMediaL(0, (KBkBootSectorNum+1)*iBytesPerSector);
       
   269             }
       
   270 		TInt ret=FatMount().LocalDrive()->Format(iFormatInfo);
       
   271 		if (ret!=KErrNone && ret!=KErrEof) // Handle format error
       
   272             ret = HandleCorrupt(ret);
       
   273 
       
   274         if (ret!=KErrNone && ret!=KErrEof) // KErrEof could be set by LocalDrive()->Format()
       
   275 		    User::Leave(ret);
       
   276 
       
   277 		if (ret==KErrNone)
       
   278 			{
       
   279 			iCurrentStep = I64LOW( 100 - (100 * TInt64(iFormatInfo.i512ByteSectorsFormatted)) / iMaxDiskSectors );
       
   280 			if (iCurrentStep<=0)
       
   281 				iCurrentStep=1;
       
   282 			return;
       
   283 			}
       
   284 		}
       
   285 
       
   286 	// ReMount since MBR may have been rewritten and partition may have moved / changed size
       
   287 	TInt ret = LocalDrive()->ForceRemount(0);
       
   288 	if (ret != KErrNone && ret != KErrNotSupported)
       
   289 		User::Leave(ret);
       
   290 
       
   291 	// MBR may have changed, so need to re-read iHiddenSectors etc.before BPB is written
       
   292 	InitializeFormatDataL();
       
   293 
       
   294     // Translate bad sector number to cluster number which contains that sector
       
   295     // This only happens in full format, in quick format they are already cluster numbers
       
   296     if (!iVariableSize && !(iMode & EQuickFormat))
       
   297         User::LeaveIfError(BadSectorToCluster());
       
   298 
       
   299 	//Check if root cluster is bad and update as required
       
   300 	if(Is32BitFat() && !iVariableSize && (iMode & EQuickFormat))
       
   301 		{
       
   302 		if(iBadClusters.Find(iRootClusterNum) !=  KErrNotFound)
       
   303 			{
       
   304 			iRootClusterNum++;
       
   305             while(iBadClusters.Find(iRootClusterNum) != KErrNotFound)
       
   306 				{
       
   307 				iRootClusterNum++;
       
   308 				}
       
   309 			}
       
   310 		}
       
   311 
       
   312     //
       
   313     // Do the rest of the disk in one lump
       
   314     //
       
   315 	iCurrentStep=0;
       
   316 
       
   317     //-- zero-fill media from position 0 to the FAT end, i.e main & backup boot sector, FSInfo and its copy and all FATs
       
   318     const TUint32 posFatEnd = ((iSectorsPerFat*iNumberOfFats) + iReservedSectors) * iBytesPerSector; //-- last FAT end position
       
   319 	
       
   320     if (iVariableSize)
       
   321 		FatMount().EnlargeL(posFatEnd); 
       
   322 
       
   323     DoZeroFillMediaL(0, posFatEnd);
       
   324     
       
   325     if(Is32BitFat())
       
   326 		{//create an empty root directory entry here
       
   327 		
       
   328         const TUint KFat32EntrySz = 4; //-- FAT32 entry size, bytes
       
   329         const TInt  startFAT1   = iReservedSectors;              //-- FAT1 start sector
       
   330         const TInt  entryOffset = iRootClusterNum*KFat32EntrySz; //-- Root dir entry offset in the FAT, bytes
       
   331 
       
   332 		TBuf8<KFat32EntrySz> EOF(KFat32EntrySz);
       
   333 		EOF[0]=0xFF;		
       
   334 		EOF[1]=0xFF;
       
   335 		EOF[2]=0xFF;
       
   336 		EOF[3]=0x0F;
       
   337 
       
   338         //-- write EOF mark to the every FAT copy
       
   339     	for(TInt i=0; i<iNumberOfFats; i++)
       
   340             {
       
   341 		    const TInt rootDirEntryPos = iBytesPerSector*(startFAT1 + i*iSectorsPerFat) + entryOffset;
       
   342             User::LeaveIfError(LocalDrive()->Write(rootDirEntryPos, EOF));
       
   343             }
       
   344 
       
   345         //-- zero-fill FAT32 root directory (just 1 cluster)
       
   346 		const TInt firstDataSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); //+RootDirSectors (not required for fat32)
       
   347         const TInt firstSectorOfCluster = ((iRootClusterNum - KFatFirstSearchCluster) * iSectorsPerCluster) + firstDataSector;
       
   348 	
       
   349         const TUint32 posRootDirStart = firstSectorOfCluster * iBytesPerSector;
       
   350         const TUint32 posRootDirEnd = posRootDirStart + iSectorsPerCluster*iBytesPerSector;
       
   351 
       
   352         DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
       
   353         }
       
   354 	else
       
   355 		{//-- FAT12/16
       
   356 		    //-- Zero fill root directory
       
   357             const TInt rootDirSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); 
       
   358             const TInt rootDirSize   = iRootDirEntries * KSizeOfFatDirEntry; //-- size in bytes
       
   359             
       
   360             const TUint32 posRootDirStart = rootDirSector * iBytesPerSector;
       
   361             const TUint32 posRootDirEnd   = posRootDirStart + rootDirSize;
       
   362 
       
   363             const TInt numOfRootSectors=(rootDirSize%iBytesPerSector) ? (rootDirSize/iBytesPerSector+1) : (rootDirSize/iBytesPerSector);
       
   364 		    if (iVariableSize)
       
   365 			    FatMount().EnlargeL(iBytesPerSector*numOfRootSectors);
       
   366 
       
   367             DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
       
   368 
       
   369 		// Enlarge ram drive to take into account rounding of
       
   370 		// data start to cluster boundary
       
   371 		if(iVariableSize && iSectorsPerCluster!=1)
       
   372 			{
       
   373 			const TInt firstFreeSector=rootDirSector+numOfRootSectors;
       
   374 			const TInt firstFreeCluster=firstFreeSector%iSectorsPerCluster ? firstFreeSector/iSectorsPerCluster+1 : firstFreeSector/iSectorsPerCluster;
       
   375 			const TInt alignedSector=firstFreeCluster*iSectorsPerCluster;
       
   376 			if(alignedSector!=firstFreeSector)
       
   377 				FatMount().EnlargeL((alignedSector-firstFreeSector)*iBytesPerSector);
       
   378 			}
       
   379 		}
       
   380 
       
   381     //-- FAT[0] must contain media descriptor in the low byte, FAT[1] for fat16/32 may contain some flags
       
   382 	TBuf8<8> startFat(8);
       
   383     startFat.Fill(0xFF);
       
   384    
       
   385     if(Is32BitFat()) //-- FAT32
       
   386         {//-- FAT32 uses only low 28 bits in FAT entry. 
       
   387         startFat[3] = 0x0F;
       
   388         startFat[7] = 0x0F;
       
   389         } 
       
   390     else if(iVariableSize||Is16BitFat()) //-- FAT16 or RAM drive which is always FAT16
       
   391         {
       
   392         startFat.SetLength(4);
       
   393         }
       
   394     else //-- FAT12
       
   395         {
       
   396         startFat.SetLength(3);
       
   397         }
       
   398 
       
   399     startFat[0]=KBootSectorMediaDescriptor;
       
   400 
       
   401     //-- write FAT[0] and FAT[1] entries to all copies of FAT
       
   402 	for(TInt i=0;i<iNumberOfFats;i++)
       
   403         {
       
   404 		User::LeaveIfError(LocalDrive()->Write(iBytesPerSector*(iReservedSectors+(iSectorsPerFat*i)),startFat));
       
   405         }
       
   406 
       
   407 	//-- create boot sectors
       
   408     CreateBootSectorL();
       
   409 
       
   410     //-- create FSInfo sectors
       
   411     if (Is32BitFat())
       
   412 		{
       
   413 		CreateReservedBootSectorL();
       
   414         CreateFSInfoSectorL();
       
   415 		}
       
   416 
       
   417     //-- here we have bad clusters numbers saved by the quick format
       
   418     //-- Interpret old bad cluster number to new cluster number and mark new bad clusters
       
   419     if (!iVariableSize && iBadClusters.Count()>0)
       
   420         {
       
   421  	
       
   422         //-- Here we need fully mounted volume, so mount it normally.
       
   423 	    FatMount().MountL(EFalse);
       
   424 
       
   425         iBadClusters.Sort();
       
   426         TranslateL();
       
   427         const TInt mark = FatMount().Is32BitFat() ? KBad_32Bit : (FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit);
       
   428         
       
   429         for (TInt i=0; i<iBadClusters.Count(); ++i)
       
   430             FatMount().FAT().WriteL(iBadClusters[i], mark);
       
   431         
       
   432         FatMount().FAT().FlushL();
       
   433         
       
   434         //-- indicate that the volume is "dirty" in order to the next Mount evend not to use FSInfo, which
       
   435         //-- contains incorrect value of free clusters because we already have bad ones saved.  
       
   436         //-- This is a very rare condition.
       
   437         FatMount().SetVolumeCleanL(EFalse); 
       
   438 
       
   439 #if defined(_DEBUG)
       
   440 	TInt r=FatMount().CheckDisk();
       
   441 	__PRINT1(_L("CFatFormatCB::DoFormatStepL() CheckDisk res: %d"),r);
       
   442 #endif
       
   443         }
       
   444         else
       
   445         {
       
   446         //-- We do not need to perform full mount in this case, the TDrive object will be marked as changed in ~CFormatCB and the
       
   447         //-- mount will be closed. Therefore on the first access to it it will be mounted normally.
       
   448         FatMount().MountL(ETrue); //-- force mount
       
   449         }
       
   450 
       
   451     __PRINT1(_L("CFatFormatCB::DoFormatStepL() Format complete drv:%d"), DriveNumber());
       
   452 	}
       
   453 
       
   454 
       
   455 //-------------------------------------------------------------------------------------------------------------------
       
   456 
       
   457 
       
   458 void CFatFormatCB::RecordOldInfoL()
       
   459     {
       
   460     // Check if mount or disk is corrupt
       
   461     // This should be stored in member variable because FatMount is remounted
       
   462     //  every time RFormat::Next() gets called thus FatMount().Initialised()
       
   463     //  will be inconsistent with previous state.
       
   464 	TLocalDriveCapsV3Buf caps;
       
   465 	User::LeaveIfError(LocalDrive()->Caps(caps));
       
   466 	iVariableSize=((caps().iMediaAtt)&KMediaAttVariableSize) ? (TBool)ETrue : (TBool)EFalse;
       
   467     iDiskCorrupt = !FatMount().ConsistentState();
       
   468     iBadClusters.Reset();
       
   469     iBadSectors.Reset();
       
   470     if (!iVariableSize && !iDiskCorrupt && (iMode&EQuickFormat))
       
   471         {
       
   472         iOldFirstFreeSector = FatMount().iFirstFreeByte>>FatMount().SectorSizeLog2();
       
   473         iOldSectorsPerCluster = FatMount().SectorsPerCluster();
       
   474 
       
   475         FatMount().FAT().InvalidateCacheL(); //-- invalidate whole FAT cache
       
   476 
       
   477         // Collect bad cluster information from current FAT table
       
   478         const TInt maxClusterNum = FatMount().UsableClusters() + KFatFirstSearchCluster;
       
   479         const TUint32 mark = FatMount().Is32BitFat() ? KBad_32Bit : (FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit);
       
   480         
       
   481         for (TInt i=KFatFirstSearchCluster; i<maxClusterNum; ++i)
       
   482             {
       
   483             if (FatMount().FAT().ReadL(i) == mark)
       
   484                 iBadClusters.AppendL(i);
       
   485             }
       
   486         }
       
   487     }
       
   488 
       
   489 
       
   490 
       
   491 
       
   492 TInt CFatFormatCB::BadSectorToCluster()
       
   493     {
       
   494     TInt sizeofFatAndRootDir;
       
   495     
       
   496     if(!Is32BitFat())
       
   497 		sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2);
       
   498     else
       
   499         sizeofFatAndRootDir = (iRootClusterNum-2) * iSectorsPerCluster;
       
   500 
       
   501     TUint firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
       
   502 
       
   503     // Check in rare case that corrupt in critical area
       
   504     // which includes bootsector, FAT table, (and root dir if not FAT32)
       
   505     TInt i, r;
       
   506     for (i=0; i<iBadSectors.Count(); ++i)
       
   507         {
       
   508         const TUint badSector = iBadSectors[i];
       
   509         // Check in rare case that corrupt in critical area
       
   510         // which includes bootsector, FAT table, (and root dir if not FAT32)
       
   511         if (firstFreeSector > badSector)
       
   512             {
       
   513             if (badSector == 0) // Boot sector corrupt
       
   514                 return KErrCorrupt;
       
   515             
       
   516             if (Is32BitFat() && badSector==1) // FSInfo corrupt
       
   517                 return KErrCorrupt;
       
   518 
       
   519             if (badSector < iReservedSectors) // Harmless in reserved area
       
   520                 continue;
       
   521             // Extend reserved area to cover bad sector
       
   522             iReservedSectors = badSector + 1;
       
   523             firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
       
   524             continue;
       
   525             }
       
   526 
       
   527         // Figure out bad cluster number and record it
       
   528         TUint cluster = (badSector-firstFreeSector)/iSectorsPerCluster+2;
       
   529         if (iBadClusters.Find(cluster) == KErrNotFound)
       
   530             {
       
   531             if ((r=iBadClusters.Append(cluster)) != KErrNone)
       
   532                 return r;
       
   533 
       
   534             if (Is32BitFat() && iRootClusterNum==cluster)
       
   535                 iRootClusterNum++;
       
   536             }
       
   537         }
       
   538     return KErrNone;
       
   539     }
       
   540 
       
   541 /**
       
   542 Create the File system information sector and its backup copy on a disk. 
       
   543 Note that CFatMountCB is still not in mounted state, so we can not rely on it.
       
   544 
       
   545 @leave System wide error codes
       
   546 */
       
   547 void CFatFormatCB::CreateFSInfoSectorL()
       
   548 	{
       
   549 	__PRINT1(_L("CFatFormatCB::CreateFSInfoSectorL() drv:%d"), DriveNumber());
       
   550 	
       
   551     ASSERT(Is32BitFat()); //-- Actually, CFatMount shall be in a consistent state.
       
   552 
       
   553     TFSInfo fsInfo;
       
   554 	TBuf8<KSizeOfFSInfo> fsInfoSecBuf;
       
   555     
       
   556     const TUint32 freeSectors  = iMaxDiskSectors - (iReservedSectors + (iNumberOfFats * iSectorsPerFat));
       
   557     const TUint32 freeClusters = (freeSectors / iSectorsPerCluster) - 1; //-- 1st cluster is taken by empty Root Dir on FAT32
       
   558     const TUint32 nextFreeClust = iRootClusterNum+1; 
       
   559 
       
   560     fsInfo.SetFreeClusterCount(freeClusters);
       
   561     fsInfo.SetNextFreeCluster(nextFreeClust);
       
   562 
       
   563     fsInfo.Externalize(fsInfoSecBuf); //-- put data to the sector buffer
       
   564 
       
   565     User::LeaveIfError(LocalDrive()->Write(KFSInfoSectorNum*iBytesPerSector, fsInfoSecBuf)); //-- main FSInfo Sector
       
   566     User::LeaveIfError(LocalDrive()->Write(KBkFSInfoSectorNum*iBytesPerSector, fsInfoSecBuf)); //-- Backup FSInfo Sector
       
   567 
       
   568 	}
       
   569 
       
   570 /**
       
   571 Create the reserved boot sector and its backup copy on a disk. 
       
   572 These are located at sectors 2 & 8
       
   573 
       
   574 @leave System wide error codes
       
   575 */
       
   576 void CFatFormatCB::CreateReservedBootSectorL()
       
   577 	{
       
   578 	__PRINT1(_L("CFatFormatCB::CreateReserveBootSectorL() drv:%d"), DriveNumber());
       
   579 	
       
   580     ASSERT(Is32BitFat());
       
   581 
       
   582     TFatBootSector bootSector;
       
   583 
       
   584 	User::LeaveIfError(FatMount().DoWriteBootSector(KReservedBootSectorNum*KDefaultSectorSize, bootSector));
       
   585 	User::LeaveIfError(FatMount().DoWriteBootSector(KBkReservedBootSectorNum*KDefaultSectorSize, bootSector));    
       
   586 	}
       
   587 
       
   588 
       
   589 //-------------------------------------------------------------------------------------------------------------------
       
   590 
       
   591 /**
       
   592     Initialize the user-specific format parameters
       
   593     Tries to figure out number of FATs, SPC, etc. values passed from the user side.
       
   594     This method is called if the user has specified some formatting parameters, like SPC
       
   595 */
       
   596 TInt CFatFormatCB::ProcessVolParam_User(const TLocalDriveCapsV6& /*aCaps*/)
       
   597 {
       
   598     __PRINT1(_L("CFatFormatCB::ProcessVolParam_User() sectors:%d"), iMaxDiskSectors);
       
   599     Dump_TLDFormatInfo(iSpecialInfo());
       
   600 
       
   601     //-- KErrArgument will be returned if iSpecialInfo().iFATBits isn't one of EFB32, EFB16, EFB32
       
   602 
       
   603     if(iSpecialInfo().iFlags & TLDFormatInfo::EOneFatTable)
       
   604 		iNumberOfFats = 1;
       
   605     else if(iSpecialInfo().iFlags & TLDFormatInfo::ETwoFatTables)
       
   606 		iNumberOfFats = 2;
       
   607     else if(Drive().IsRemovable())
       
   608 		iNumberOfFats = KNumberOfFatsExternal;
       
   609 	else
       
   610 		iNumberOfFats = KNumberOfFatsInternal;
       
   611 
       
   612     
       
   613     if(iSpecialInfo().iReservedSectors)
       
   614         iReservedSectors = iSpecialInfo().iReservedSectors; 
       
   615     else
       
   616         iReservedSectors = KDefFatResvdSec; //-- the user hasn't specified reserved sectors count, use default (FAT12/16)
       
   617 
       
   618     //-----------------------------------------
       
   619 
       
   620 
       
   621     const TUint KMaxSecPerCluster    = 64; 
       
   622 	const TUint KDefaultSecPerCluster= 8;   //-- default value, if the iSpecialInfo().iSectorsPerCluster isn't specified
       
   623 
       
   624     iSectorsPerCluster = iSpecialInfo().iSectorsPerCluster;
       
   625     if(iSectorsPerCluster <= 0)
       
   626         {//-- default value, user hasn't specified TLDFormatInfo::iSectorsPerCluster
       
   627         iSectorsPerCluster = KDefaultSecPerCluster; //-- will be adjusted later
       
   628         }
       
   629     else
       
   630         {
       
   631         iSectorsPerCluster = Min(1<<Log2(iSectorsPerCluster), KMaxSecPerCluster);
       
   632 	    }
       
   633 
       
   634     //-----------------------------------------
       
   635 
       
   636     if (iMaxDiskSectors < 4096) // < 2MB
       
   637         {
       
   638         iSectorsPerCluster = 1;
       
   639 		iRootDirEntries = 128;
       
   640         }
       
   641 	else if (iMaxDiskSectors < 8192) // < 4MB
       
   642         {
       
   643         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)2);
       
   644 		iRootDirEntries = 256;
       
   645         }
       
   646 	else if (iMaxDiskSectors < 32768) // < 16MB
       
   647         {
       
   648         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)4);
       
   649 		iRootDirEntries = 512;
       
   650         }
       
   651 	else if (iMaxDiskSectors < 1048576) // < 512MB
       
   652         {
       
   653         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)8);
       
   654 		iRootDirEntries = 512;
       
   655         }
       
   656     else // FAT32
       
   657 		{
       
   658         iRootDirEntries = 512;
       
   659         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)KMaxSecPerCluster);
       
   660         }
       
   661 
       
   662 
       
   663     //-----------------------------------------
       
   664 
       
   665 	TLDFormatInfo::TFATBits fatBits = iSpecialInfo().iFATBits;
       
   666 	if (fatBits == TLDFormatInfo::EFBDontCare)
       
   667 		{//-- the user hasn't specified FAT type, need to work it out according to volume geometry
       
   668         const TFatType fatType = SuggestFatType();
       
   669 		switch(fatType)
       
   670 			{
       
   671 			case EFat12:
       
   672 				fatBits = TLDFormatInfo::EFB12;
       
   673 				break;
       
   674 			case EFat16:
       
   675 				fatBits = TLDFormatInfo::EFB16;
       
   676 				break;
       
   677 			case EFat32:
       
   678 				fatBits = TLDFormatInfo::EFB32;
       
   679 				break;
       
   680 			case EInvalid:
       
   681 				ASSERT(0);
       
   682 			}
       
   683 		}
       
   684 
       
   685     TFatType reqFatType(EInvalid); //-- requested FAT type
       
   686 
       
   687     switch (fatBits)
       
   688 		{
       
   689 		case TLDFormatInfo::EFB12:
       
   690             SetFatType(EFat12);
       
   691 			iSectorsPerFat=MaxFat12Sectors();
       
   692 			reqFatType = EFat12;
       
   693             break;
       
   694 
       
   695 		case TLDFormatInfo::EFB16:
       
   696             SetFatType(EFat16);
       
   697 			iSectorsPerFat=MaxFat16Sectors();
       
   698 			reqFatType = EFat16;
       
   699             break;
       
   700 
       
   701 		case TLDFormatInfo::EFB32:
       
   702             SetFatType(EFat32);
       
   703 			iSectorsPerFat=MaxFat32Sectors();
       
   704 	        
       
   705 			iRootDirEntries = 0;
       
   706 			iRootClusterNum = 2;
       
   707 			
       
   708             if(iSpecialInfo().iReservedSectors == 0)
       
   709                 iReservedSectors = KDefFat32ResvdSec; //-- user hasn't specified reserved sectors count, use default (FAT32)
       
   710             else
       
   711                 iReservedSectors = iSpecialInfo().iReservedSectors;
       
   712 
       
   713 			reqFatType = EFat32;
       
   714             break;
       
   715 
       
   716         default:
       
   717             __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() Incorrect FAT type specifier!"));
       
   718             return KErrArgument;
       
   719 		}
       
   720 	
       
   721         //-- check if we can format the volume with requested FAT type
       
   722         const TFatType fatType = SuggestFatType();
       
   723         if(fatType != reqFatType)
       
   724 			{
       
   725 			//-- volume metrics don't correspond to the requested FAT type
       
   726             __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() FAT type mismatch!"));
       
   727             return KErrArgument;
       
   728 			}
       
   729 
       
   730         return KErrNone;
       
   731 }
       
   732 
       
   733 //-------------------------------------------------------------------------------------------------------------------
       
   734 /**
       
   735     Initialize format parameters from the information provided by the media driver.
       
   736     This method is mostly called for SD cards formatting
       
   737 */
       
   738 TInt CFatFormatCB::ProcessVolParam_Custom(const TLocalDriveCapsV6& aCaps)
       
   739 {
       
   740     __PRINT(_L("CFatFormatCB::ProcessVolParam_Custom()"));
       
   741     
       
   742     //-- TLDFormatInfo structure is filled by the media driver, it decides the media formatting parameters
       
   743     const TLDFormatInfo& fmtInfo = aCaps.iFormatInfo;
       
   744     Dump_TLDFormatInfo(fmtInfo);
       
   745 
       
   746 	if(fmtInfo.iFlags & TLDFormatInfo::EOneFatTable)
       
   747 		iNumberOfFats = 1;
       
   748     else if(fmtInfo.iFlags & TLDFormatInfo::ETwoFatTables)
       
   749 		iNumberOfFats = 2;
       
   750     else if(Drive().IsRemovable())
       
   751 		iNumberOfFats = KNumberOfFatsExternal;
       
   752 	else
       
   753 		iNumberOfFats = KNumberOfFatsInternal;	
       
   754 
       
   755 	iRootDirEntries=512;
       
   756 
       
   757 	iSectorsPerCluster = fmtInfo.iSectorsPerCluster;
       
   758 	iSectorsPerTrack   = fmtInfo.iSectorsPerTrack;
       
   759 	iNumberOfHeads	   = fmtInfo.iNumberOfSides;
       
   760 	iReservedSectors   = fmtInfo.iReservedSectors ? fmtInfo.iReservedSectors : KDefFatResvdSec;
       
   761 	
       
   762     switch (fmtInfo.iFATBits)
       
   763 		{
       
   764 		case TLDFormatInfo::EFB12:
       
   765             SetFatType(EFat12);
       
   766 			iSectorsPerFat  = MaxFat12Sectors();
       
   767 			break;
       
   768 
       
   769 		case TLDFormatInfo::EFB16:
       
   770             SetFatType(EFat16);
       
   771 			iSectorsPerFat  = MaxFat16Sectors();
       
   772             break;
       
   773 
       
   774 		case TLDFormatInfo::EFB32:
       
   775             SetFatType(EFat32);
       
   776 			iReservedSectors = fmtInfo.iReservedSectors ? fmtInfo.iReservedSectors : KDefFat32ResvdSec;
       
   777 			iSectorsPerFat   = MaxFat32Sectors();
       
   778 			iRootDirEntries  = 0;
       
   779 			iRootClusterNum  = 2;
       
   780             break;
       
   781 
       
   782 		default:
       
   783 			{
       
   784 			TInt64 clusters64 = (fmtInfo.iCapacity / KDefaultSectorSize) / iSectorsPerCluster;
       
   785 			TInt clusters = I64LOW(clusters64);
       
   786 			if (clusters < 4085)
       
   787 				{
       
   788                 SetFatType(EFat12);
       
   789 				iSectorsPerFat  = MaxFat12Sectors();
       
   790 				}
       
   791 			else if(clusters < 65525)
       
   792 				{
       
   793                 SetFatType(EFat16);
       
   794 				iSectorsPerFat  = MaxFat16Sectors();
       
   795                 }
       
   796 			else
       
   797 				{
       
   798                 SetFatType(EFat32);
       
   799 				iReservedSectors = fmtInfo.iReservedSectors ? fmtInfo.iReservedSectors : KDefFat32ResvdSec;
       
   800 				iSectorsPerFat   = MaxFat32Sectors();
       
   801 				iRootDirEntries  = 0;
       
   802 				iRootClusterNum  = 2;
       
   803 				}
       
   804 			}
       
   805 		}
       
   806 
       
   807     return KErrNone;
       
   808 
       
   809 }
       
   810 
       
   811 //-------------------------------------------------------------------------------------------------------------------
       
   812 /**
       
   813     Initialize format parameters by defult.
       
   814     This method is called if the used has not specified any formatting parameters (all default)
       
   815 */
       
   816 TInt CFatFormatCB::ProcessVolParam_Default(const TLocalDriveCapsV6& aCaps)
       
   817 {
       
   818 	__PRINT1(_L("CFatFormatCB::ProcessVolParam_Default sectors:%d"), iMaxDiskSectors);
    82     
   819     
    83     if( Drive().IsRemovable() )
   820     if( Drive().IsRemovable() )
    84 		iNumberOfFats = KNumberOfFatsExternal;
   821 		iNumberOfFats = KNumberOfFatsExternal;
    85 	else
   822 	else
    86 		iNumberOfFats = KNumberOfFatsInternal;	
   823 		iNumberOfFats = KNumberOfFatsInternal;	
    87  	
   824  	
    88 	iReservedSectors=KDefFatResvdSec;		
   825 	iReservedSectors=KDefFatResvdSec;		
    89 	if (aDiskSizeInSectors <=4084*1)	// 2MB
   826 	if (iMaxDiskSectors <=4084*1)	// 2MB
    90 		{
   827 		{
    91 		iRootDirEntries=128;
   828 		iRootDirEntries=128;
    92 		iSectorsPerCluster=1;
   829 		iSectorsPerCluster=1;
    93 		iFileSystemName=KFileSystemName12;
   830         SetFatType(EFat12);
    94 		iSectorsPerFat=MaxFat12Sectors();
   831 		iSectorsPerFat=MaxFat12Sectors();
    95    		}
   832    		}
    96 	else if (aDiskSizeInSectors<4084*2) // < 4MB (8168 sectors)
   833 	else if (iMaxDiskSectors<4084*2) // < 4MB (8168 sectors)
    97 		{
   834 		{
    98 		iRootDirEntries=256; 
   835 		iRootDirEntries=256; 
    99 		iSectorsPerCluster=2;
   836 		iSectorsPerCluster=2;
   100 		iFileSystemName=KFileSystemName12;
   837         SetFatType(EFat12);
   101 		iSectorsPerFat=MaxFat12Sectors();
   838 		iSectorsPerFat=MaxFat12Sectors();
   102 		}
   839 		}
   103 	else if (aDiskSizeInSectors<4084*4) // < 8MB (16336 sectors)
   840 	else if (iMaxDiskSectors<4084*4) // < 8MB (16336 sectors)
   104 		{
   841 		{
   105 		iRootDirEntries=512;
   842 		iRootDirEntries=512;
   106 		iSectorsPerCluster=4;
   843 		iSectorsPerCluster=4;
   107 		iFileSystemName=KFileSystemName12;
   844         SetFatType(EFat12);
   108 		iSectorsPerFat=MaxFat12Sectors();
   845 		iSectorsPerFat=MaxFat12Sectors();
   109 		}
   846 		}
   110 	else if (aDiskSizeInSectors<4084*8) // < 16MB (32672 sectors)
   847 	else if (iMaxDiskSectors<4084*8) // < 16MB (32672 sectors)
   111 		{
   848 		{
   112 		iRootDirEntries=512;
   849 		iRootDirEntries=512;
   113 		iSectorsPerCluster=8;
   850 		iSectorsPerCluster=8;
   114 		iFileSystemName=KFileSystemName12;
   851         SetFatType(EFat12);
   115 		iSectorsPerFat=MaxFat12Sectors();
   852 		iSectorsPerFat=MaxFat12Sectors();
   116 		}
   853 		}
   117 	else if(aDiskSizeInSectors<1048576) // >= 16Mb - FAT16   < (1048576) 512MB
   854 	else if(iMaxDiskSectors<1048576) // >= 16Mb - FAT16   < (1048576) 512MB
   118 		{
   855 		{
   119 		iFileSystemName=KFileSystemName16;
   856         SetFatType(EFat16);
   120 		TUint minSectorsPerCluster=(aDiskSizeInSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
   857 		TUint minSectorsPerCluster=(iMaxDiskSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
   121 		iRootDirEntries=512;
   858 		iRootDirEntries=512;
   122 		iSectorsPerCluster=1;
   859 		iSectorsPerCluster=1;
   123 		
   860 		
   124 		while (minSectorsPerCluster>iSectorsPerCluster)
   861 		while (minSectorsPerCluster>iSectorsPerCluster)
   125 			iSectorsPerCluster<<=1;
   862 			iSectorsPerCluster<<=1;
   126 
   863 
   127 		iSectorsPerFat=MaxFat16Sectors();
   864 		iSectorsPerFat=MaxFat16Sectors();
   128 		}
   865 		}
   129 	else	//use FAT32
   866 	else	//use FAT32
   130 		{
   867 		{
   131 		iFileSystemName=KFileSystemName32;
   868         SetFatType(EFat32);
   132 		iRootDirEntries=0;						//this is always the case for fat32
   869 		iRootDirEntries=0;						//this is always the case for fat32
   133 		if(aDiskSizeInSectors < 16777216)		//8GB in 512byte sectors
   870 		
       
   871         if(iMaxDiskSectors < 16777216)		//8GB in 512byte sectors
   134 			iSectorsPerCluster=8;
   872 			iSectorsPerCluster=8;
   135 		else if(aDiskSizeInSectors < 33554432)	//16GB in 512byte sectors
   873 		else if(iMaxDiskSectors < 33554432)	//16GB in 512byte sectors
   136 			iSectorsPerCluster=16;
   874 			iSectorsPerCluster=16;
   137 		else if(aDiskSizeInSectors < 67108864)	//32GB in 512byte sectors 
   875 		else if(iMaxDiskSectors < 67108864)	//32GB in 512byte sectors 
   138 			iSectorsPerCluster=32;
   876 			iSectorsPerCluster=32;
   139 		else
   877 		else
   140 			iSectorsPerCluster=64;				//Anything >= 32GB uses a 32K cluster size
   878 			iSectorsPerCluster=64;				//Anything >= 32GB uses a 32K cluster size
       
   879 
   141 		iReservedSectors=KDefFat32ResvdSec;
   880 		iReservedSectors=KDefFat32ResvdSec;
   142 		iRootClusterNum=2;						//As recomended in the document
   881 		iRootClusterNum=2;						//As recomended in the document
   143 		iSectorsPerFat=MaxFat32Sectors();
   882 		iSectorsPerFat=MaxFat32Sectors();
   144 		
   883 		
   145 		}
   884 		}
   187 			break;
   926 			break;
   188 		}
   927 		}
   189 	__PRINT1(_L("iSectorsPerCluster  (final): %d"),iSectorsPerCluster);
   928 	__PRINT1(_L("iSectorsPerCluster  (final): %d"),iSectorsPerCluster);
   190 
   929 
   191     return KErrNone;
   930     return KErrNone;
       
   931 }
       
   932 
       
   933 //-------------------------------------------------------------------------------------------------------------------
       
   934 /**
       
   935     Initialize the format parameters for a variable sized disk (RAM drive)
       
   936     
       
   937     @param  aDiskSizeInSectors volume size in sectors
       
   938     @return standard error code
       
   939 */
       
   940 TInt CFatFormatCB::ProcessVolParam_RamDisk()
       
   941 	{
       
   942 	__PRINT1(_L("CFatFormatCB::ProcessVolParam_RamDisk() sectors:%d"), iMaxDiskSectors);
       
   943 
       
   944     iNumberOfFats   = 2; // 1 FAT 1 Indirection table (FIT)
       
   945 	iReservedSectors= 1;
       
   946 	iRootDirEntries = 2*(4*KDefaultSectorSize)/sizeof(SFatDirEntry);
       
   947 	TUint minSectorsPerCluster=(iMaxDiskSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
       
   948 	iSectorsPerCluster=1;
       
   949 
       
   950 	while(minSectorsPerCluster > iSectorsPerCluster)
       
   951 		iSectorsPerCluster<<=1;
       
   952 
       
   953 	
       
   954 	iSectorsPerFat=MaxFat16Sectors();
       
   955 	__PRINT1(_L("iSectorsPerCluster = %d"),iSectorsPerCluster);
       
   956     __PRINT1(_L("iSectorsPerFat = %d"),iSectorsPerFat);
       
   957 	
       
   958     SetFatType(EFat16);
       
   959 
       
   960 	return KErrNone;
   192 	}
   961 	}
   193 
   962 
   194 TInt CFatFormatCB::FirstDataSector() const
   963 
   195 	{
   964 
   196 	TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   965 
   197     return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors;
   966 
   198 	}
   967 
   199 
   968 
   200 void CFatFormatCB::AdjustClusterSize(TUint aRecommendedSectorsPerCluster)
   969 
   201 	{
   970 
   202     const TUint KMaxSecPerCluster = 64;	// 32K
   971 
   203 
   972 
   204 	while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2))
   973 
   205 		iSectorsPerCluster<<= 1;
   974 
   206 
   975 
   207 	}
   976 
   208 
   977 
   209 // AdjustFirstDataSectorAlignment()
   978 
   210 // Attempts to align the first data sector on an erase block boundary by modifying the
   979 
   211 // number of reserved sectors.
   980 
   212 TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TUint aEraseBlockSizeInSectors)
   981 
   213 	{
   982 
   214 	const TBool bFat16 = Is16BitFat();
   983 
   215     const TBool bFat32 = Is32BitFat();
   984 
   216 
   985 
   217 	// Save these 2 values in the event of a convergence failure; this should 
       
   218 	// hopefully never happen, but we will cater for this in release mode to be safe,
       
   219 	TUint reservedSectorsSaved = iReservedSectors;
       
   220 	TUint sectorsPerFatSaved = iSectorsPerFat;
       
   221 
       
   222 	TUint reservedSectorsOld = 0;
       
   223 
       
   224 	// zero for FAT32
       
   225 	TUint rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
       
   226 	TUint fatSectors = 0;
       
   227 
       
   228 	TUint KMaxIterations = 10;
       
   229 	TUint n;
       
   230 	for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++)
       
   231 		{
       
   232 		reservedSectorsOld = iReservedSectors;
       
   233 
       
   234 		iSectorsPerFat = bFat32 ? MaxFat32Sectors() : bFat16 ? MaxFat16Sectors() : MaxFat12Sectors();
       
   235 
       
   236 		fatSectors = iSectorsPerFat * iNumberOfFats;
       
   237 
       
   238 		// calculate number of blocks
       
   239 		TInt  nBlocks = (iReservedSectors + fatSectors + rootDirSectors + aEraseBlockSizeInSectors-1) / aEraseBlockSizeInSectors;
       
   240 
       
   241 		iReservedSectors = (nBlocks * aEraseBlockSizeInSectors) - rootDirSectors - fatSectors;
       
   242 		}
       
   243 	
       
   244 	ASSERT(iReservedSectors >= (bFat32 ? KDefFat32ResvdSec : KDefFatResvdSec));
       
   245 
       
   246 	if ((FirstDataSector() & (aEraseBlockSizeInSectors-1)) == 0)
       
   247 		{
       
   248 		return KErrNone;
       
   249 		}
       
   250 	else
       
   251 		{
       
   252 		iReservedSectors = reservedSectorsSaved;
       
   253 		iSectorsPerFat = sectorsPerFatSaved;
       
   254 		return KErrGeneral;
       
   255 		}
       
   256 	}
       
   257 
       
   258 
       
   259 //-------------------------------------------------------------------------------------------------------------------
       
   260 
       
   261 /**
       
   262 Create the boot sector on media for the volume. For FAT32 also creates a backup copy of the boot sector.
       
   263 
       
   264 @leave System wide error codes
       
   265 */
       
   266 void CFatFormatCB::CreateBootSectorL()
       
   267 	{
       
   268 	__PRINT1(_L("CFatFormatCB::CreateBootSector() drive:%d"),DriveNumber());
       
   269 
       
   270 	
       
   271     const TBool bFat32 = Is32BitFat();
       
   272     
       
   273     TFatBootSector bootSector;
       
   274 
       
   275 	bootSector.SetVendorID(KDefaultVendorID);
       
   276 	bootSector.SetBytesPerSector(iBytesPerSector);
       
   277 	bootSector.SetSectorsPerCluster(iSectorsPerCluster);
       
   278 	bootSector.SetReservedSectors(iReservedSectors);
       
   279 	bootSector.SetNumberOfFats(iNumberOfFats);
       
   280 	iCountOfClusters=iMaxDiskSectors/iSectorsPerCluster;
       
   281 	if (!bFat32)
       
   282 		{
       
   283 		if (iCountOfClusters>(TInt)KMaxTUint16)
       
   284 			User::Leave(KErrTooBig);
       
   285 		}
       
   286 
       
   287 	bootSector.SetReservedByte(0);
       
   288 	TTime timeID;
       
   289 	timeID.HomeTime();						//	System time in future?
       
   290 	bootSector.SetUniqueID(I64LOW(timeID.Int64()));	//	Generate UniqueID from time
       
   291 	bootSector.SetVolumeLabel(_L8(""));
       
   292 	bootSector.SetFileSysType(iFileSystemName);
       
   293 // Floppy specific info:
       
   294 	bootSector.SetJumpInstruction();
       
   295 	bootSector.SetMediaDescriptor(KBootSectorMediaDescriptor);
       
   296 	bootSector.SetNumberOfHeads(iNumberOfHeads);
       
   297 	bootSector.SetHiddenSectors(iHiddenSectors);
       
   298 	bootSector.SetSectorsPerTrack(iSectorsPerTrack);
       
   299 	bootSector.SetPhysicalDriveNumber(128);
       
   300 	bootSector.SetExtendedBootSignature(0x29);
       
   301 
       
   302 	if(bFat32)
       
   303 		{
       
   304 		bootSector.SetFatSectors(0);
       
   305 		bootSector.SetFatSectors32(iSectorsPerFat);
       
   306 		bootSector.SetRootDirEntries(0);
       
   307 		bootSector.SetTotalSectors(0);
       
   308 		bootSector.SetHugeSectors(iMaxDiskSectors);
       
   309 		bootSector.SetFATFlags(0);			
       
   310 		bootSector.SetVersionNumber(0x00);	
       
   311 		bootSector.SetRootClusterNum(iRootClusterNum);
       
   312 		bootSector.SetFSInfoSectorNum(KFSInfoSectorNum);	
       
   313         bootSector.SetBkBootRecSector(KBkBootSectorNum);
       
   314 		}
       
   315 	else//fat12 and 16
       
   316 		{
       
   317 		bootSector.SetFatSectors32(0);
       
   318 		bootSector.SetFatSectors(iSectorsPerFat);
       
   319 		bootSector.SetRootDirEntries(iRootDirEntries);
       
   320 
       
   321 		if (iMaxDiskSectors<=KMaxTUint16)
       
   322 			{
       
   323 			bootSector.SetTotalSectors(iMaxDiskSectors);
       
   324 			bootSector.SetHugeSectors(0);
       
   325 			}
       
   326 		else
       
   327 			{
       
   328 			bootSector.SetTotalSectors(0);
       
   329 			bootSector.SetHugeSectors(iMaxDiskSectors);
       
   330 			}
       
   331 		}
       
   332 
       
   333 	//-- write main boot sector to the first sector on media
       
   334     User::LeaveIfError(FatMount().DoWriteBootSector(KBootSectorNum*bootSector.BytesPerSector(), bootSector));
       
   335 	
       
   336     //-- for FAT32 write backup copy of the boot sector
       
   337     if(bFat32)
       
   338         {
       
   339         User::LeaveIfError(FatMount().DoWriteBootSector(KBkBootSectorNum*bootSector.BytesPerSector(), bootSector));    
       
   340         }
       
   341 
       
   342     }
       
   343 
       
   344 //-------------------------------------------------------------------------------------------------------------------
       
   345 
       
   346 /**
       
   347 Format a disk section, called iteratively to erase whole of media, on last iteration
       
   348 creates an empty volume. If called with quick formatonly erases the Fat leaving the
       
   349 rest of the volume intact.
       
   350 
       
   351 @leave System wide error code
       
   352 */
       
   353 void CFatFormatCB::DoFormatStepL()
       
   354 	{
       
   355 	if (iFormatInfo.iFormatIsCurrent==EFalse)
       
   356 		{ // Only done first time through
       
   357 		if (iMode & EForceErase)
       
   358 			{
       
   359 			TInt r = FatMount().ErasePassword();
       
   360 			User::LeaveIfError(r);
       
   361 			// CFatMountCB::ErasePassword() calls TBusLocalDrive::ForceRemount(),
       
   362 			// so need to stop a remount from occurring in next call to :
       
   363 			// TFsFormatNext::DoRequestL((), TDrive::CheckMount().
       
   364 			FatMount().Drive().SetChanged(EFalse);
       
   365 			}
       
   366 
       
   367         RecordOldInfoL();
       
   368 		InitializeFormatDataL();
       
   369 		FatMount().DoDismount();
       
   370 		if (iVariableSize)
       
   371 			FatMount().ReduceSizeL(0,I64LOW(FatMount().iSize));
       
   372 		}
       
   373     //
       
   374     // Blank disk if not EQuickFormat
       
   375     //
       
   376 	if (!iVariableSize && !(iMode & EQuickFormat) && iCurrentStep)
       
   377 		{
       
   378 		if (iFormatInfo.iFormatIsCurrent == EFalse)
       
   379 			{//-- firstly invalidate sectors 0-6 inclusive, they may contain main boot sector, backup boot sector and FSInfo sector.
       
   380 	        DoZeroFillMediaL(0, (KBkBootSectorNum+1)*iBytesPerSector);
       
   381             }
       
   382 		TInt ret=FatMount().LocalDrive()->Format(iFormatInfo);
       
   383 		if (ret!=KErrNone && ret!=KErrEof) // Handle format error
       
   384             ret = HandleCorrupt(ret);
       
   385 
       
   386         if (ret!=KErrNone && ret!=KErrEof) // KErrEof could be set by LocalDrive()->Format()
       
   387 		    User::Leave(ret);
       
   388 
       
   389 		if (ret==KErrNone)
       
   390 			{
       
   391 			iCurrentStep = I64LOW( 100 - (100 * TInt64(iFormatInfo.i512ByteSectorsFormatted)) / iMaxDiskSectors );
       
   392 			if (iCurrentStep<=0)
       
   393 				iCurrentStep=1;
       
   394 			return;
       
   395 			}
       
   396 		}
       
   397 
       
   398 	// ReMount since MBR may have been rewritten and partition may have moved / changed size
       
   399 	TInt ret = LocalDrive()->ForceRemount(0);
       
   400 	if (ret != KErrNone && ret != KErrNotSupported)
       
   401 		User::Leave(ret);
       
   402 
       
   403 	// MBR may have changed, so need to re-read iHiddenSectors etc.before BPB is written
       
   404 	InitializeFormatDataL();
       
   405 
       
   406     // Translate bad sector number to cluster number which contains that sector
       
   407     // This only happens in full format, in quick format they are already cluster numbers
       
   408     if (!iVariableSize && !(iMode & EQuickFormat))
       
   409         User::LeaveIfError(BadSectorToCluster());
       
   410 
       
   411 	//Check if root cluster is bad and update as required
       
   412 	if(Is32BitFat() && !iVariableSize && (iMode & EQuickFormat))
       
   413 		{
       
   414 		if(iBadClusters.Find(iRootClusterNum) !=  KErrNotFound)
       
   415 			{
       
   416 			iRootClusterNum++;
       
   417             while(iBadClusters.Find(iRootClusterNum) != KErrNotFound)
       
   418 				{
       
   419 				iRootClusterNum++;
       
   420 				}
       
   421 			}
       
   422 		}
       
   423 
       
   424     //
       
   425     // Do the rest of the disk in one lump
       
   426     //
       
   427 	iCurrentStep=0;
       
   428 
       
   429     //-- zero-fill media from position 0 to the FAT end, i.e main & backup boot sector, FSInfo and its copy and all FATs
       
   430     const TUint32 posFatEnd = ((iSectorsPerFat*iNumberOfFats) + iReservedSectors) * iBytesPerSector; //-- last FAT end position
       
   431 	
       
   432     if (iVariableSize)
       
   433 		FatMount().EnlargeL(posFatEnd); 
       
   434 
       
   435     DoZeroFillMediaL(0, posFatEnd);
       
   436     
       
   437     if(Is32BitFat())
       
   438 		{//create an empty root directory entry here
       
   439 		
       
   440         const TUint KFat32EntrySz = 4; //-- FAT32 entry size, bytes
       
   441         const TInt  startFAT1   = iReservedSectors;              //-- FAT1 start sector
       
   442         const TInt  entryOffset = iRootClusterNum*KFat32EntrySz; //-- Root dir entry offset in the FAT, bytes
       
   443 
       
   444 		TBuf8<KFat32EntrySz> EOF(KFat32EntrySz);
       
   445 		EOF[0]=0xFF;		
       
   446 		EOF[1]=0xFF;
       
   447 		EOF[2]=0xFF;
       
   448 		EOF[3]=0x0F;
       
   449 
       
   450         //-- write EOF mark to the every FAT copy
       
   451     	for(TInt i=0; i<iNumberOfFats; i++)
       
   452             {
       
   453 		    const TInt rootDirEntryPos = iBytesPerSector*(startFAT1 + i*iSectorsPerFat) + entryOffset;
       
   454             User::LeaveIfError(LocalDrive()->Write(rootDirEntryPos, EOF));
       
   455             }
       
   456 
       
   457         //-- zero-fill FAT32 root directory (just 1 cluster)
       
   458 		const TInt firstDataSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); //+RootDirSectors (not required for fat32)
       
   459         const TInt firstSectorOfCluster = ((iRootClusterNum - KFatFirstSearchCluster) * iSectorsPerCluster) + firstDataSector;
       
   460 	
       
   461         const TUint32 posRootDirStart = firstSectorOfCluster * iBytesPerSector;
       
   462         const TUint32 posRootDirEnd = posRootDirStart + iSectorsPerCluster*iBytesPerSector;
       
   463 
       
   464         DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
       
   465         }
       
   466 	else
       
   467 		{//-- FAT12/16
       
   468 		    //-- Zero fill root directory
       
   469             const TInt rootDirSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); 
       
   470             const TInt rootDirSize   = iRootDirEntries * KSizeOfFatDirEntry; //-- size in bytes
       
   471             
       
   472             const TUint32 posRootDirStart = rootDirSector * iBytesPerSector;
       
   473             const TUint32 posRootDirEnd   = posRootDirStart + rootDirSize;
       
   474 
       
   475             const TInt numOfRootSectors=(rootDirSize%iBytesPerSector) ? (rootDirSize/iBytesPerSector+1) : (rootDirSize/iBytesPerSector);
       
   476 		    if (iVariableSize)
       
   477 			    FatMount().EnlargeL(iBytesPerSector*numOfRootSectors);
       
   478 
       
   479             DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
       
   480 
       
   481 		// Enlarge ram drive to take into account rounding of
       
   482 		// data start to cluster boundary
       
   483 		if(iVariableSize && iSectorsPerCluster!=1)
       
   484 			{
       
   485 			const TInt firstFreeSector=rootDirSector+numOfRootSectors;
       
   486 			const TInt firstFreeCluster=firstFreeSector%iSectorsPerCluster ? firstFreeSector/iSectorsPerCluster+1 : firstFreeSector/iSectorsPerCluster;
       
   487 			const TInt alignedSector=firstFreeCluster*iSectorsPerCluster;
       
   488 			if(alignedSector!=firstFreeSector)
       
   489 				FatMount().EnlargeL((alignedSector-firstFreeSector)*iBytesPerSector);
       
   490 			}
       
   491 		}
       
   492 
       
   493     //-- FAT[0] must contain media descriptor in the low byte, FAT[1] for fat16/32 may contain some flags
       
   494 	TBuf8<8> startFat(8);
       
   495     startFat.Fill(0xFF);
       
   496    
       
   497     if(Is32BitFat()) //-- FAT32
       
   498         {//-- FAT32 uses only low 28 bits in FAT entry. 
       
   499         startFat[3] = 0x0F;
       
   500         startFat[7] = 0x0F;
       
   501         } 
       
   502     else if(iVariableSize||Is16BitFat()) //-- FAT16 or RAM drive which is always FAT16
       
   503         {
       
   504         startFat.SetLength(4);
       
   505         }
       
   506     else //-- FAT12
       
   507         {
       
   508         startFat.SetLength(3);
       
   509         }
       
   510 
       
   511     startFat[0]=KBootSectorMediaDescriptor;
       
   512 
       
   513     //-- write FAT[0] and FAT[1] entries to all copies of FAT
       
   514 	for(TInt i=0;i<iNumberOfFats;i++)
       
   515         {
       
   516 		User::LeaveIfError(LocalDrive()->Write(iBytesPerSector*(iReservedSectors+(iSectorsPerFat*i)),startFat));
       
   517         }
       
   518 
       
   519 	//-- create boot sectors
       
   520     CreateBootSectorL();
       
   521 
       
   522     //-- create FSInfo sectors
       
   523     if (Is32BitFat())
       
   524 		{
       
   525 		CreateReservedBootSectorL();
       
   526         CreateFSInfoSectorL();
       
   527 		}
       
   528 
       
   529     //-- here we have bad clusters numbers saved by the quick format
       
   530     //-- Interpret old bad cluster number to new cluster number and mark new bad clusters
       
   531     if (!iVariableSize && iBadClusters.Count()>0)
       
   532         {
       
   533  	
       
   534         //-- Here we need fully mounted volume, so mount it normally.
       
   535 	    FatMount().MountL(EFalse);
       
   536 
       
   537         iBadClusters.Sort();
       
   538         TranslateL();
       
   539         const TInt mark = FatMount().Is32BitFat() ? KBad_32Bit : (FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit);
       
   540         
       
   541         for (TInt i=0; i<iBadClusters.Count(); ++i)
       
   542             FatMount().FAT().WriteL(iBadClusters[i], mark);
       
   543         
       
   544         FatMount().FAT().FlushL();
       
   545         
       
   546         //-- indicate that the volume is "dirty" in order to the next Mount evend not to use FSInfo, which
       
   547         //-- contains incorrect value of free clusters because we already have bad ones saved.  
       
   548         //-- This is a very rare condition.
       
   549         FatMount().SetVolumeCleanL(EFalse); 
       
   550 
       
   551 #if defined(_DEBUG)
       
   552 	TInt r=FatMount().CheckDisk();
       
   553 	__PRINT1(_L("CFatFormatCB::DoFormatStepL() CheckDisk res: %d"),r);
       
   554 #endif
       
   555         }
       
   556         else
       
   557         {
       
   558         //-- We do not need to perform full mount in this case, the TDrive object will be marked as changed in ~CFormatCB and the
       
   559         //-- mount will be closed. Therefore on the first access to it it will be mounted normally.
       
   560         FatMount().MountL(ETrue); //-- force mount
       
   561         }
       
   562 
       
   563     __PRINT1(_L("CFatFormatCB::DoFormatStepL() Format complete drv:%d"), DriveNumber());
       
   564 	}
       
   565 
       
   566 
       
   567 //-------------------------------------------------------------------------------------------------------------------
       
   568 
       
   569 /**
       
   570     Initialize the user specific format parameters for fixed sized disk.
       
   571     
       
   572     @param  aDiskSizeInSectors disk size in sectors
       
   573     @return system-wide error code
       
   574 */
       
   575 TInt CFatFormatCB::InitFormatDataForFixedSizeDiskUser(TUint aDiskSizeInSectors)
       
   576 	{
       
   577     __PRINT1(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() sectors:%d"), aDiskSizeInSectors);
       
   578     Dump_TLDFormatInfo(iSpecialInfo());
       
   579 
       
   580     //-- KErrArgument will be returned if iSpecialInfo().iFATBits isn't one of EFB32, EFB16, EFB32
       
   581 
       
   582     if(iSpecialInfo().iFlags & TLDFormatInfo::EOneFatTable)
       
   583 		iNumberOfFats = 1;
       
   584     else if(iSpecialInfo().iFlags & TLDFormatInfo::ETwoFatTables)
       
   585 		iNumberOfFats = 2;
       
   586     else if(Drive().IsRemovable())
       
   587 		iNumberOfFats = KNumberOfFatsExternal;
       
   588 	else
       
   589 		iNumberOfFats = KNumberOfFatsInternal;
       
   590 
       
   591 
       
   592     if(iSpecialInfo().iReservedSectors == 0)
       
   593         iReservedSectors = KDefFatResvdSec; //-- user hasn't specified reserved sectors count, use default (FAT12/16)
       
   594     else
       
   595         iReservedSectors = iSpecialInfo().iReservedSectors;
       
   596 
       
   597 
       
   598     const TUint KMaxSecPerCluster    = 64; 
       
   599 	const TUint KDefaultSecPerCluster= 8;   //-- default value, if the iSpecialInfo().iSectorsPerCluster isn't specified
       
   600 
       
   601     iSectorsPerCluster = iSpecialInfo().iSectorsPerCluster;
       
   602     if(iSectorsPerCluster <= 0)
       
   603         {//-- default value, user hasn't specified TLDFormatInfo::iSectorsPerCluster
       
   604         iSectorsPerCluster = KDefaultSecPerCluster; //-- will be adjusted later
       
   605         }
       
   606     else
       
   607         {
       
   608         iSectorsPerCluster = Min(1<<Log2(iSectorsPerCluster), KMaxSecPerCluster);
       
   609 	    }
       
   610 
       
   611     //-----------------------------------------
       
   612 
       
   613     if (aDiskSizeInSectors < 4096) // < 2MB
       
   614         {
       
   615         iSectorsPerCluster = 1;
       
   616 		iRootDirEntries = 128;
       
   617         }
       
   618 	else if (aDiskSizeInSectors < 8192) // < 4MB
       
   619         {
       
   620         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)2);
       
   621 		iRootDirEntries = 256;
       
   622         }
       
   623 	else if (aDiskSizeInSectors < 32768) // < 16MB
       
   624         {
       
   625         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)4);
       
   626 		iRootDirEntries = 512;
       
   627         }
       
   628 	else if (aDiskSizeInSectors < 1048576) // < 512MB
       
   629         {
       
   630         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)8);
       
   631 		iRootDirEntries = 512;
       
   632         }
       
   633     else // FAT32
       
   634 		{
       
   635         iRootDirEntries = 512;
       
   636         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)KMaxSecPerCluster);
       
   637         }
       
   638 
       
   639 
       
   640     //-----------------------------------------
       
   641 
       
   642 	TLDFormatInfo::TFATBits fatBits = iSpecialInfo().iFATBits;
       
   643 	if (fatBits == TLDFormatInfo::EFBDontCare)
       
   644 		{
       
   645         const TFatType fatType = SuggestFatType();
       
   646 		switch(fatType)
       
   647 			{
       
   648 			case EFat12:
       
   649 				fatBits = TLDFormatInfo::EFB12;
       
   650 				break;
       
   651 			case EFat16:
       
   652 				fatBits = TLDFormatInfo::EFB16;
       
   653 				break;
       
   654 			case EFat32:
       
   655 				fatBits = TLDFormatInfo::EFB32;
       
   656 				break;
       
   657 			case EInvalid:
       
   658 				ASSERT(0);
       
   659 			}
       
   660 		}
       
   661 
       
   662     TFatType reqFatType(EInvalid); //-- requested FAT type
       
   663 
       
   664     switch (fatBits)
       
   665 		{
       
   666 		case TLDFormatInfo::EFB12:
       
   667 			iFileSystemName=KFileSystemName12;
       
   668 			iSectorsPerFat=MaxFat12Sectors();
       
   669 			reqFatType = EFat12;
       
   670             break;
       
   671 
       
   672 		case TLDFormatInfo::EFB16:
       
   673 			iFileSystemName=KFileSystemName16;
       
   674 			iSectorsPerFat=MaxFat16Sectors();
       
   675 			reqFatType = EFat16;
       
   676             break;
       
   677 
       
   678 		case TLDFormatInfo::EFB32:
       
   679 			iFileSystemName=KFileSystemName32;
       
   680 			iSectorsPerFat=MaxFat32Sectors();
       
   681 	        
       
   682 			iRootDirEntries = 0;
       
   683 			iRootClusterNum = 2;
       
   684 			
       
   685             if(iSpecialInfo().iReservedSectors == 0)
       
   686                 iReservedSectors = KDefFat32ResvdSec; //-- user hasn't specified reserved sectors count, use default (FAT32)
       
   687             else
       
   688                 iReservedSectors = iSpecialInfo().iReservedSectors;
       
   689 
       
   690 			reqFatType = EFat32;
       
   691             break;
       
   692 
       
   693         default:
       
   694             __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() Incorrect FAT type specifier!"));
       
   695             return KErrArgument;
       
   696 		}
       
   697 	
       
   698         //-- check if we can format the volume with requested FAT type
       
   699         const TFatType fatType = SuggestFatType();
       
   700         if(fatType != reqFatType)
       
   701 			{
       
   702 			//-- volume metrics don't correspond to the requested FAT type
       
   703             __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() FAT type mismatch!"));
       
   704             return KErrArgument;
       
   705 			}
       
   706 
       
   707         return KErrNone;
       
   708     }
       
   709 
       
   710 /**
       
   711     Initialize the format parameters for a custom fixed sized disk
       
   712 
       
   713     @param  aFormatInfo The custom format parameters
       
   714     @return system-wide error code
       
   715 */
       
   716 TInt CFatFormatCB::InitFormatDataForFixedSizeDiskCustom(const TLDFormatInfo& aFormatInfo)
       
   717 	{
       
   718     __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskCustom()"));
       
   719     Dump_TLDFormatInfo(aFormatInfo);
       
   720 
       
   721 	if(aFormatInfo.iFlags & TLDFormatInfo::EOneFatTable)
       
   722 		iNumberOfFats = 1;
       
   723     else if(aFormatInfo.iFlags & TLDFormatInfo::ETwoFatTables)
       
   724 		iNumberOfFats = 2;
       
   725     else if(Drive().IsRemovable())
       
   726 		iNumberOfFats = KNumberOfFatsExternal;
       
   727 	else
       
   728 		iNumberOfFats = KNumberOfFatsInternal;	
       
   729 
       
   730 	iRootDirEntries=512;
       
   731 
       
   732 	iSectorsPerCluster = aFormatInfo.iSectorsPerCluster;
       
   733 	iSectorsPerTrack   = aFormatInfo.iSectorsPerTrack;
       
   734 	iNumberOfHeads	   = aFormatInfo.iNumberOfSides;
       
   735 	iReservedSectors   = aFormatInfo.iReservedSectors ? aFormatInfo.iReservedSectors : KDefFatResvdSec;
       
   736 	
       
   737     switch (aFormatInfo.iFATBits)
       
   738 		{
       
   739 		case TLDFormatInfo::EFB12:
       
   740 			iFileSystemName = KFileSystemName12;
       
   741 			iSectorsPerFat  = MaxFat12Sectors();
       
   742 			break;
       
   743 
       
   744 		case TLDFormatInfo::EFB16:
       
   745 			iFileSystemName = KFileSystemName16;
       
   746 			iSectorsPerFat  = MaxFat16Sectors();
       
   747             break;
       
   748 
       
   749 		case TLDFormatInfo::EFB32:
       
   750 			iFileSystemName  = KFileSystemName32;
       
   751 			iReservedSectors = aFormatInfo.iReservedSectors ? aFormatInfo.iReservedSectors : KDefFat32ResvdSec;
       
   752 			iSectorsPerFat   = MaxFat32Sectors();
       
   753 			iRootDirEntries  = 0;
       
   754 			iRootClusterNum  = 2;
       
   755             break;
       
   756 
       
   757 		default:
       
   758 			{
       
   759 			TInt64 clusters64 = (aFormatInfo.iCapacity / KDefaultSectorSize) / iSectorsPerCluster;
       
   760 			TInt clusters = I64LOW(clusters64);
       
   761 			if (clusters < 4085)
       
   762 				{
       
   763 				iFileSystemName = KFileSystemName12;
       
   764 				iSectorsPerFat  = MaxFat12Sectors();
       
   765 				}
       
   766 			else if(clusters < 65525)
       
   767 				{
       
   768 				iFileSystemName = KFileSystemName16;
       
   769 				iSectorsPerFat  = MaxFat16Sectors();
       
   770                 }
       
   771 			else
       
   772 				{
       
   773 				iFileSystemName  = KFileSystemName32;
       
   774 				iReservedSectors = aFormatInfo.iReservedSectors ? aFormatInfo.iReservedSectors : KDefFat32ResvdSec;
       
   775 				iSectorsPerFat   = MaxFat32Sectors();
       
   776 				iRootDirEntries  = 0;
       
   777 				iRootClusterNum  = 2;
       
   778 				}
       
   779 			}
       
   780 		}
       
   781 
       
   782     return KErrNone;
       
   783 	}
       
   784 
       
   785 void CFatFormatCB::RecordOldInfoL()
       
   786     {
       
   787     // Check if mount or disk is corrupt
       
   788     // This should be stored in member variable because FatMount is remounted
       
   789     //  every time RFormat::Next() gets called thus FatMount().Initialised()
       
   790     //  will be inconsistent with previous state.
       
   791 	TLocalDriveCapsV3Buf caps;
       
   792 	User::LeaveIfError(LocalDrive()->Caps(caps));
       
   793 	iVariableSize=((caps().iMediaAtt)&KMediaAttVariableSize) ? (TBool)ETrue : (TBool)EFalse;
       
   794     iDiskCorrupt = !FatMount().ConsistentState();
       
   795     iBadClusters.Reset();
       
   796     iBadSectors.Reset();
       
   797     if (!iVariableSize && !iDiskCorrupt && (iMode&EQuickFormat))
       
   798         {
       
   799         iOldFirstFreeSector = FatMount().iFirstFreeByte>>FatMount().SectorSizeLog2();
       
   800         iOldSectorsPerCluster = FatMount().SectorsPerCluster();
       
   801 
       
   802         FatMount().FAT().InvalidateCacheL(); //-- invalidate whole FAT cache
       
   803 
       
   804         // Collect bad cluster information from current FAT table
       
   805         const TInt maxClusterNum = FatMount().UsableClusters() + KFatFirstSearchCluster;
       
   806         const TUint32 mark = FatMount().Is32BitFat() ? KBad_32Bit : (FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit);
       
   807         
       
   808         for (TInt i=KFatFirstSearchCluster; i<maxClusterNum; ++i)
       
   809             {
       
   810             if (FatMount().FAT().ReadL(i) == mark)
       
   811                 iBadClusters.AppendL(i);
       
   812             }
       
   813         }
       
   814     }
       
   815 
       
   816 
       
   817 
       
   818 
       
   819 TInt CFatFormatCB::BadSectorToCluster()
       
   820     {
       
   821     TInt sizeofFatAndRootDir;
       
   822     if (iFileSystemName != KFileSystemName32)
       
   823 		sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2);
       
   824     else
       
   825         sizeofFatAndRootDir = (iRootClusterNum-2) * iSectorsPerCluster;
       
   826 
       
   827     TUint firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
       
   828 
       
   829     // Check in rare case that corrupt in critical area
       
   830     // which includes bootsector, FAT table, (and root dir if not FAT32)
       
   831     TInt i, r;
       
   832     for (i=0; i<iBadSectors.Count(); ++i)
       
   833         {
       
   834         const TUint badSector = iBadSectors[i];
       
   835         // Check in rare case that corrupt in critical area
       
   836         // which includes bootsector, FAT table, (and root dir if not FAT32)
       
   837         if (firstFreeSector > badSector)
       
   838             {
       
   839             if (badSector == 0) // Boot sector corrupt
       
   840                 return KErrCorrupt;
       
   841             if (iFileSystemName==KFileSystemName32 && badSector==1) // FSInfo corrupt
       
   842                 return KErrCorrupt;
       
   843             if (badSector < iReservedSectors) // Harmless in reserved area
       
   844                 continue;
       
   845             // Extend reserved area to cover bad sector
       
   846             iReservedSectors = badSector + 1;
       
   847             firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
       
   848             continue;
       
   849             }
       
   850 
       
   851         // Figure out bad cluster number and record it
       
   852         TUint cluster = (badSector-firstFreeSector)/iSectorsPerCluster+2;
       
   853         if (iBadClusters.Find(cluster) == KErrNotFound)
       
   854             {
       
   855             if ((r=iBadClusters.Append(cluster)) != KErrNone)
       
   856                 return r;
       
   857             if (iFileSystemName==KFileSystemName32 && iRootClusterNum==cluster)
       
   858                 iRootClusterNum++;
       
   859             }
       
   860         }
       
   861     return KErrNone;
       
   862     }
       
   863 
       
   864 /**
       
   865 Create the File system information sector and its backup copy on a disk. 
       
   866 Note that CFatMountCB is still not in mounted state, so we can not rely on it.
       
   867 
       
   868 @leave System wide error codes
       
   869 */
       
   870 void CFatFormatCB::CreateFSInfoSectorL()
       
   871 	{
       
   872 	__PRINT1(_L("CFatFormatCB::CreateFSInfoSectorL() drv:%d"), DriveNumber());
       
   873 	
       
   874     ASSERT(Is32BitFat()); //-- Actually, CFatMount shall be in a consistent state.
       
   875 
       
   876     TFSInfo fsInfo;
       
   877 	TBuf8<KSizeOfFSInfo> fsInfoSecBuf;
       
   878     
       
   879     const TUint32 freeSectors  = iMaxDiskSectors - (iReservedSectors + (iNumberOfFats * iSectorsPerFat));
       
   880     const TUint32 freeClusters = (freeSectors / iSectorsPerCluster) - 1; //-- 1st cluster is taken by empty Root Dir on FAT32
       
   881     const TUint32 nextFreeClust = iRootClusterNum+1; 
       
   882 
       
   883     fsInfo.SetFreeClusterCount(freeClusters);
       
   884     fsInfo.SetNextFreeCluster(nextFreeClust);
       
   885 
       
   886     fsInfo.Externalize(fsInfoSecBuf); //-- put data to the sector buffer
       
   887 
       
   888     User::LeaveIfError(LocalDrive()->Write(KFSInfoSectorNum*iBytesPerSector, fsInfoSecBuf)); //-- main FSInfo Sector
       
   889     User::LeaveIfError(LocalDrive()->Write(KBkFSInfoSectorNum*iBytesPerSector, fsInfoSecBuf)); //-- Backup FSInfo Sector
       
   890 
       
   891 	}
       
   892 
       
   893 /**
       
   894 Create the reserved boot sector and its backup copy on a disk. 
       
   895 These are located at sectors 2 & 8
       
   896 
       
   897 @leave System wide error codes
       
   898 */
       
   899 void CFatFormatCB::CreateReservedBootSectorL()
       
   900 	{
       
   901 	__PRINT1(_L("CFatFormatCB::CreateReserveBootSectorL() drv:%d"), DriveNumber());
       
   902 	
       
   903     ASSERT(Is32BitFat());
       
   904 
       
   905     TFatBootSector bootSector;
       
   906 
       
   907 	User::LeaveIfError(FatMount().DoWriteBootSector(KReservedBootSectorNum*KDefaultSectorSize, bootSector));
       
   908 	User::LeaveIfError(FatMount().DoWriteBootSector(KBkReservedBootSectorNum*KDefaultSectorSize, bootSector));    
       
   909 	}
       
   910 
       
   911 
       
   912 
       
   913