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