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