userlibandfileserver/fileserver/sfat/sl_fat16.cpp
changeset 43 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     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