os/kernelhwsrv/userlibandfileserver/fileserver/sfat/sl_fat16.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfat/sl_fat16.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,629 @@
     1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// f32\sfat\sl_fat16.cpp
    1.18 +// 
    1.19 +//
    1.20 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    1.21 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    1.22 +//!!
    1.23 +//!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
    1.24 +//!!
    1.25 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    1.26 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    1.27 +
    1.28 +
    1.29 +#include "sl_std.h"
    1.30 +#include "sl_cache.h"
    1.31 +
    1.32 +const TUint KDefFatResvdSec = 1;    ///< default number of FAT12/16 reserved sectors
    1.33 +
    1.34 +/**
    1.35 +Initialize the format parameters for a normal fixed sized disk
    1.36 +Setting set to adhere to Rules of Count of clusters for FAT type
    1.37 +
    1.38 +@param  aDiskSizeInSectors Size of volume in sectors
    1.39 +@return system-wide error code
    1.40 +*/
    1.41 +TInt CFatFormatCB::InitFormatDataForFixedSizeDiskNormal(TInt aDiskSizeInSectors, const TLocalDriveCapsV6& aCaps)
    1.42 +    {
    1.43 +    if( Drive().IsRemovable() )
    1.44 +        iNumberOfFats = KNumberOfFatsExternal;
    1.45 +    else
    1.46 +        iNumberOfFats = KNumberOfFatsInternal;
    1.47 +    
    1.48 +    iReservedSectors=KDefFatResvdSec;       
    1.49 +    if (aDiskSizeInSectors<4084*1) // < 2MB
    1.50 +        {
    1.51 +        iRootDirEntries=128;
    1.52 +        iSectorsPerCluster=1;
    1.53 +        iFileSystemName=KFileSystemName12;
    1.54 +        iSectorsPerFat=MaxFat12Sectors();
    1.55 +        }
    1.56 +    else if (aDiskSizeInSectors<4084*2) // < 4MB (8168 sectors)
    1.57 +        {
    1.58 +        iRootDirEntries=256; 
    1.59 +        iSectorsPerCluster=2;
    1.60 +        iFileSystemName=KFileSystemName12;
    1.61 +        iSectorsPerFat=MaxFat12Sectors();
    1.62 +        }
    1.63 +    else if (aDiskSizeInSectors<4084*4) // < 8MB (16336 sectors)
    1.64 +        {
    1.65 +        iRootDirEntries=512;
    1.66 +        iSectorsPerCluster=4;
    1.67 +        iFileSystemName=KFileSystemName12;
    1.68 +        iSectorsPerFat=MaxFat12Sectors();
    1.69 +        }
    1.70 +    else if (aDiskSizeInSectors<4084*8) // < 16MB (32672 sectors)
    1.71 +        {
    1.72 +        iRootDirEntries=512;
    1.73 +        iSectorsPerCluster=8;
    1.74 +        iFileSystemName=KFileSystemName12;
    1.75 +        iSectorsPerFat=MaxFat12Sectors();
    1.76 +        }
    1.77 +    else    // >= 16Mb - FAT16
    1.78 +        {
    1.79 +        iFileSystemName=KFileSystemName16;
    1.80 +        TInt minSectorsPerCluster=(aDiskSizeInSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
    1.81 +        iRootDirEntries=512;
    1.82 +        iSectorsPerCluster=1;
    1.83 +        while (minSectorsPerCluster>iSectorsPerCluster)
    1.84 +            iSectorsPerCluster<<=1;
    1.85 +        iSectorsPerFat=MaxFat16Sectors();
    1.86 +        }
    1.87 +    
    1.88 +    // Ensure cluster size is a multiple of the block size
    1.89 +    TInt blockSizeInSectors = aCaps.iBlockSize >> iSectorSizeLog2;
    1.90 +    __PRINT1(_L("blockSizeInSectors: %d"),blockSizeInSectors);
    1.91 +    ASSERT(blockSizeInSectors == 0 || IsPowerOf2(blockSizeInSectors));
    1.92 +    if (blockSizeInSectors != 0 && IsPowerOf2(blockSizeInSectors))
    1.93 +        {
    1.94 +        __PRINT1(_L("iSectorsPerCluster (old): %d"),iSectorsPerCluster);
    1.95 +        AdjustClusterSize(blockSizeInSectors);
    1.96 +        __PRINT1(_L("iSectorsPerCluster (new): %d"),iSectorsPerCluster);
    1.97 +        }
    1.98 +    
    1.99 +    // Align first data sector on an erase block boundary if
   1.100 +    // (1) the iEraseBlockSize is specified
   1.101 +    // (2) the start of the partition is already aligned to an erase block boundary, 
   1.102 +    //     i.e. iHiddenSectors is zero or a multiple of iEraseBlockSize
   1.103 +    __PRINT1(_L("iHiddenSectors: %d"),iHiddenSectors);
   1.104 +    TInt eraseblockSizeInSectors = aCaps.iEraseBlockSize >> iSectorSizeLog2;
   1.105 +    __PRINT1(_L("eraseblockSizeInSectors: %d"),eraseblockSizeInSectors);
   1.106 +    ASSERT(eraseblockSizeInSectors == 0 || IsPowerOf2(eraseblockSizeInSectors));    
   1.107 +    ASSERT(eraseblockSizeInSectors == 0 || eraseblockSizeInSectors >= blockSizeInSectors);
   1.108 +    if ((eraseblockSizeInSectors != 0) &&
   1.109 +        (iHiddenSectors % eraseblockSizeInSectors == 0) &&  
   1.110 +        (IsPowerOf2(eraseblockSizeInSectors)) &&
   1.111 +        (eraseblockSizeInSectors >= blockSizeInSectors))
   1.112 +        {
   1.113 +        TInt r = AdjustFirstDataSectorAlignment(eraseblockSizeInSectors);
   1.114 +        ASSERT(r == KErrNone);
   1.115 +        (void) r;
   1.116 +        }
   1.117 +    __PRINT1(_L("iReservedSectors: %d"),iReservedSectors);
   1.118 +    __PRINT1(_L("FirstDataSector: %d"), FirstDataSector());
   1.119 +
   1.120 +    return KErrNone;
   1.121 +    }
   1.122 +
   1.123 +TInt CFatFormatCB::FirstDataSector() const
   1.124 +    {
   1.125 +    TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   1.126 +    return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors;
   1.127 +    }
   1.128 +
   1.129 +void CFatFormatCB::AdjustClusterSize(TInt aRecommendedSectorsPerCluster)
   1.130 +    {
   1.131 +    const TInt KMaxSecPerCluster = 64;  // 32K
   1.132 +    while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2))
   1.133 +        iSectorsPerCluster<<= 1;
   1.134 +    }
   1.135 +
   1.136 +// AdjustFirstDataSectorAlignment()
   1.137 +// Attempts to align the first data sector on an erase block boundary by modifying the
   1.138 +// number of reserved sectors.
   1.139 +TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TInt aEraseBlockSizeInSectors)
   1.140 +    {
   1.141 +    const TBool bFat16 = Is16BitFat();
   1.142 +
   1.143 +    // Save these 2 values in the event of a convergence failure; this should 
   1.144 +    // hopefully never happen, but we will cater for this in release mode to be safe,
   1.145 +    TInt reservedSectorsSaved = iReservedSectors;
   1.146 +    TInt sectorsPerFatSaved = iSectorsPerFat;
   1.147 +
   1.148 +    TInt reservedSectorsOld = 0;
   1.149 +
   1.150 +    // zero for FAT32
   1.151 +    TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   1.152 +    TInt fatSectors = 0;
   1.153 +
   1.154 +    TInt KMaxIterations = 10;
   1.155 +    TInt n;
   1.156 +    for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++)
   1.157 +        {
   1.158 +        reservedSectorsOld = iReservedSectors;
   1.159 +
   1.160 +        iSectorsPerFat = bFat16 ? MaxFat16Sectors() : MaxFat12Sectors();
   1.161 +
   1.162 +        fatSectors = iSectorsPerFat * iNumberOfFats;
   1.163 +
   1.164 +        // calculate number of blocks
   1.165 +        TInt nBlocks = (iReservedSectors + fatSectors + rootDirSectors + aEraseBlockSizeInSectors-1) / aEraseBlockSizeInSectors;
   1.166 +
   1.167 +        iReservedSectors = (nBlocks * aEraseBlockSizeInSectors) - rootDirSectors - fatSectors;
   1.168 +        }
   1.169 +    
   1.170 +    ASSERT(iReservedSectors >= (TInt) KDefFatResvdSec);
   1.171 +
   1.172 +    if ((FirstDataSector() & (aEraseBlockSizeInSectors-1)) == 0)
   1.173 +        {
   1.174 +        return KErrNone;
   1.175 +        }
   1.176 +    else
   1.177 +        {
   1.178 +        iReservedSectors = reservedSectorsSaved;
   1.179 +        iSectorsPerFat = sectorsPerFatSaved;
   1.180 +        return KErrGeneral;
   1.181 +        }
   1.182 +    }
   1.183 +
   1.184 +/**
   1.185 +    Initialize the user specific format parameters for fixed sized disk.
   1.186 +    
   1.187 +    @param  aDiskSizeInSectors disk size in sectors
   1.188 +    @return system-wide error code
   1.189 +*/
   1.190 +TInt  CFatFormatCB::InitFormatDataForFixedSizeDiskUser(TInt aDiskSizeInSectors)
   1.191 +    {
   1.192 +    //-- KErrArgument will be returned if iSpecialInfo().iFATBits isn't one of EFB32, EFB16, EFB32
   1.193 +
   1.194 +    if(iSpecialInfo().iFlags & TLDFormatInfo::EOneFatTable)
   1.195 +        iNumberOfFats = 1;
   1.196 +    else if(iSpecialInfo().iFlags & TLDFormatInfo::ETwoFatTables)
   1.197 +        iNumberOfFats = 2;
   1.198 +    else if(Drive().IsRemovable())
   1.199 +        iNumberOfFats = KNumberOfFatsExternal;
   1.200 +    else 
   1.201 +        iNumberOfFats = KNumberOfFatsInternal;
   1.202 +
   1.203 +
   1.204 +    if(iSpecialInfo().iReservedSectors == 0)
   1.205 +        iReservedSectors = KDefFatResvdSec; //-- user hasn't specified reserved sectors count, use default (FAT12/16)
   1.206 +    else
   1.207 +        iReservedSectors = iSpecialInfo().iReservedSectors;
   1.208 +
   1.209 +
   1.210 +    const TInt KMaxSecPerCluster = 64; 
   1.211 +    const TInt KDefaultSecPerCluster= 8;   //-- default value, if the iSpecialInfo().iSectorsPerCluster isn't specified
   1.212 +    
   1.213 +    iSectorsPerCluster = iSpecialInfo().iSectorsPerCluster;
   1.214 +    if(iSectorsPerCluster <= 0)
   1.215 +        {//-- default value, user hasn't specified TLDFormatInfo::iSectorsPerCluster
   1.216 +        iSectorsPerCluster = KDefaultSecPerCluster; //-- will be adjusted later
   1.217 +        }
   1.218 +    else
   1.219 +        {
   1.220 +        iSectorsPerCluster = Min(1<<Log2(iSectorsPerCluster), KMaxSecPerCluster);
   1.221 +        }
   1.222 +
   1.223 +    //-----------------------------------------
   1.224 +
   1.225 +    if (aDiskSizeInSectors < 4096) // < 2MB
   1.226 +        {
   1.227 +        iSectorsPerCluster = 1;
   1.228 +        iRootDirEntries = 128;
   1.229 +        }
   1.230 +    else if (aDiskSizeInSectors < 8192) // < 4MB
   1.231 +        {
   1.232 +        iSectorsPerCluster = Min(iSectorsPerCluster, 2);
   1.233 +        iRootDirEntries = 256;
   1.234 +        }
   1.235 +    else if (aDiskSizeInSectors < 32768) // < 16MB
   1.236 +        {
   1.237 +        iSectorsPerCluster = Min(iSectorsPerCluster, 4);
   1.238 +        iRootDirEntries = 512;
   1.239 +        }
   1.240 +    else if (aDiskSizeInSectors < 131072) // < 64MB
   1.241 +        {
   1.242 +        iSectorsPerCluster = Min(iSectorsPerCluster, 8);
   1.243 +        iRootDirEntries = 512;
   1.244 +        }
   1.245 +    else    // >= 64Mb
   1.246 +        iRootDirEntries = 512;
   1.247 +
   1.248 +    //-----------------------------------------
   1.249 +
   1.250 +    TLDFormatInfo::TFATBits fatBits = iSpecialInfo().iFATBits;
   1.251 +    if (fatBits == TLDFormatInfo::EFBDontCare)
   1.252 +        {
   1.253 +        const TFatType fatType = SuggestFatType();
   1.254 +        switch(fatType)
   1.255 +            {
   1.256 +            case EFat12:
   1.257 +                fatBits = TLDFormatInfo::EFB12;
   1.258 +                break;
   1.259 +            case EFat16:
   1.260 +                fatBits = TLDFormatInfo::EFB16;
   1.261 +                break;
   1.262 +            case EFat32:
   1.263 +                fatBits = TLDFormatInfo::EFB32;
   1.264 +                break;
   1.265 +            case EInvalid:
   1.266 +                ASSERT(0);
   1.267 +            }
   1.268 +        }
   1.269 +
   1.270 +    TFatType reqFatType(EInvalid); //-- requested FAT type
   1.271 +
   1.272 +    switch (fatBits)
   1.273 +        {
   1.274 +        case TLDFormatInfo::EFB12:
   1.275 +        iFileSystemName=KFileSystemName12;
   1.276 +        iSectorsPerFat=MaxFat12Sectors();
   1.277 +        reqFatType = EFat12;
   1.278 +        break;
   1.279 +
   1.280 +        case TLDFormatInfo::EFB16:
   1.281 +        iFileSystemName=KFileSystemName16;
   1.282 +        iSectorsPerFat=MaxFat16Sectors();
   1.283 +        reqFatType = EFat16;
   1.284 +        break;
   1.285 +        
   1.286 +        case TLDFormatInfo::EFB32:
   1.287 +        __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() FAT32 Not supported!"));
   1.288 +        return KErrNotSupported;
   1.289 +
   1.290 +        default:
   1.291 +        __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() Incorrect FAT type specifier!"));
   1.292 +        return KErrArgument;
   1.293 +        };
   1.294 +
   1.295 +        //-- check if we can format the volume with requested FAT type
   1.296 +        const TFatType fatType = SuggestFatType();
   1.297 +        if(fatType != reqFatType)
   1.298 +        {//-- volume metrics don't correspond to the requested FAT type
   1.299 +            __PRINT(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() FAT type mismatch!"));
   1.300 +            return KErrArgument;
   1.301 +        }
   1.302 +
   1.303 +
   1.304 +    return KErrNone;
   1.305 +    }
   1.306 +
   1.307 +/**
   1.308 +    Initialize the format parameters for a custom fixed sized disk
   1.309 +
   1.310 +    @param  aFormatInfo The custom format parameters
   1.311 +    @return system-wide error code
   1.312 +*/
   1.313 +TInt CFatFormatCB::InitFormatDataForFixedSizeDiskCustom(const TLDFormatInfo& aFormatInfo)
   1.314 +    {
   1.315 +    if(aFormatInfo.iFlags & TLDFormatInfo::EOneFatTable)
   1.316 +        iNumberOfFats = 1;
   1.317 +    else if(aFormatInfo.iFlags & TLDFormatInfo::ETwoFatTables)
   1.318 +        iNumberOfFats = 2;
   1.319 +    else if(Drive().IsRemovable())
   1.320 +        iNumberOfFats = KNumberOfFatsExternal;
   1.321 +    else
   1.322 +        iNumberOfFats = KNumberOfFatsInternal;  
   1.323 +
   1.324 +    iRootDirEntries=512;
   1.325 +
   1.326 +    iSectorsPerCluster = aFormatInfo.iSectorsPerCluster;
   1.327 +    iSectorsPerTrack   = aFormatInfo.iSectorsPerTrack;
   1.328 +    iNumberOfHeads     = aFormatInfo.iNumberOfSides;
   1.329 +    iReservedSectors   = aFormatInfo.iReservedSectors ? aFormatInfo.iReservedSectors : KDefFatResvdSec;
   1.330 +    
   1.331 +    switch (aFormatInfo.iFATBits)
   1.332 +        {
   1.333 +        case TLDFormatInfo::EFB12:
   1.334 +            iFileSystemName = KFileSystemName12;
   1.335 +            iSectorsPerFat  = MaxFat12Sectors();
   1.336 +            break;
   1.337 +
   1.338 +        case TLDFormatInfo::EFB16:
   1.339 +            iFileSystemName = KFileSystemName16;
   1.340 +            iSectorsPerFat  = MaxFat16Sectors();
   1.341 +            break;
   1.342 +
   1.343 +        default:
   1.344 +            {
   1.345 +            TInt64 clusters64 = (aFormatInfo.iCapacity / KDefaultSectorSize) / iSectorsPerCluster;
   1.346 +            TInt clusters = I64LOW(clusters64);
   1.347 +            if (clusters < 4085)
   1.348 +                {
   1.349 +                iFileSystemName = KFileSystemName12;
   1.350 +                iSectorsPerFat  = MaxFat12Sectors();
   1.351 +                }
   1.352 +            else
   1.353 +                {
   1.354 +                iFileSystemName = KFileSystemName16;
   1.355 +                iSectorsPerFat  = MaxFat16Sectors();
   1.356 +                }
   1.357 +            }
   1.358 +        }
   1.359 +
   1.360 +    return KErrNone;
   1.361 +    }
   1.362 +
   1.363 +void CFatFormatCB::RecordOldInfoL()
   1.364 +    {
   1.365 +    __PRINT(_L("CFatFormatCB::RecordOldInfoL"));
   1.366 +    // Check if mount or disk is corrupt
   1.367 +    // This should be stored in member variable because FatMount is remounted
   1.368 +    //  every time RFormat::Next() gets called thus FatMount().Initialised()
   1.369 +    //  will be inconsistent with previous state.
   1.370 +    TLocalDriveCapsV3Buf caps;
   1.371 +    User::LeaveIfError(LocalDrive()->Caps(caps));
   1.372 +    iVariableSize=((caps().iMediaAtt)&KMediaAttVariableSize) ? (TBool)ETrue : (TBool)EFalse;
   1.373 +    iDiskCorrupt = !FatMount().ConsistentState();
   1.374 +    iBadClusters.Reset();
   1.375 +    iBadSectors.Reset();
   1.376 +    if (!iVariableSize && !iDiskCorrupt && (iMode & EQuickFormat))
   1.377 +        {
   1.378 +        iOldFirstFreeSector = FatMount().iFirstFreeByte >> FatMount().SectorSizeLog2();
   1.379 +        iOldSectorsPerCluster = FatMount().SectorsPerCluster();
   1.380 +        
   1.381 +        FatMount().FAT().InvalidateCacheL(); //-- invalidate whole FAT cache
   1.382 +
   1.383 +        const TInt maxClusterNum = FatMount().iUsableClusters + KFatFirstSearchCluster;
   1.384 +
   1.385 +        // Collect bad cluster information from current FAT table
   1.386 +        const TUint32 mark = FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit;
   1.387 +        for (TInt i=KFatFirstSearchCluster; i<maxClusterNum; i++)
   1.388 +            if (FatMount().FAT().ReadL(i) == mark)
   1.389 +                iBadClusters.AppendL(i);
   1.390 +        }
   1.391 +    }
   1.392 +
   1.393 +/**
   1.394 +Create the boot sector on media for the volume. 
   1.395 +
   1.396 +@leave System wide error codes
   1.397 +*/
   1.398 +void CFatFormatCB::CreateBootSectorL()
   1.399 +    {
   1.400 +    __PRINT1(_L("CFatFormatCB::CreateBootSector() drive:%d"),DriveNumber());
   1.401 +
   1.402 +    TFatBootSector bootSector;
   1.403 +
   1.404 +    bootSector.SetVendorID(KDefaultVendorID);
   1.405 +    bootSector.SetBytesPerSector(iBytesPerSector);
   1.406 +    bootSector.SetSectorsPerCluster(iSectorsPerCluster);
   1.407 +    bootSector.SetReservedSectors(iReservedSectors);
   1.408 +    bootSector.SetNumberOfFats(iNumberOfFats);
   1.409 +    bootSector.SetRootDirEntries(iRootDirEntries);
   1.410 +    if (iMaxDiskSectors<(TInt)KMaxTUint16)
   1.411 +        bootSector.SetTotalSectors(iMaxDiskSectors);
   1.412 +    else
   1.413 +        {
   1.414 +        bootSector.SetTotalSectors(0);
   1.415 +        bootSector.SetHugeSectors(iMaxDiskSectors);
   1.416 +        }
   1.417 +    TInt numberOfClusters=iMaxDiskSectors/iSectorsPerCluster;
   1.418 +    if (numberOfClusters>(TInt)KMaxTUint16)
   1.419 +        User::Leave(KErrTooBig);
   1.420 +    bootSector.SetFatSectors(iSectorsPerFat);
   1.421 +    bootSector.SetReservedByte(0);
   1.422 +    TTime timeID;
   1.423 +    timeID.HomeTime();                      //  System time in future?
   1.424 +    bootSector.SetUniqueID(I64LOW(timeID.Int64())); //  Generate UniqueID from time
   1.425 +    bootSector.SetVolumeLabel(_L8(""));
   1.426 +    bootSector.SetFileSysType(iFileSystemName);
   1.427 +// Floppy specific info:
   1.428 +    bootSector.SetJumpInstruction();
   1.429 +    bootSector.SetMediaDescriptor(KBootSectorMediaDescriptor);
   1.430 +    bootSector.SetNumberOfHeads(iNumberOfHeads);
   1.431 +    bootSector.SetHiddenSectors(iHiddenSectors);
   1.432 +    bootSector.SetSectorsPerTrack(iSectorsPerTrack);
   1.433 +    bootSector.SetPhysicalDriveNumber(128);
   1.434 +    bootSector.SetExtendedBootSignature(0x29);
   1.435 +
   1.436 +    
   1.437 +    User::LeaveIfError(FatMount().DoWriteBootSector(KBootSectorNum*bootSector.BytesPerSector(), bootSector));
   1.438 +    }
   1.439 +
   1.440 +//-------------------------------------------------------------------------------------------------------------------
   1.441 +
   1.442 +/**
   1.443 +Format a disk section, called iteratively to erase whole of media, on last iteration
   1.444 +creates an empty volume. If called with quick formatonly erases the Fat leaving the
   1.445 +rest of the volume intact.
   1.446 +
   1.447 +@leave System wide error code
   1.448 +*/
   1.449 +void CFatFormatCB::DoFormatStepL()
   1.450 +    {
   1.451 +    if (iFormatInfo.iFormatIsCurrent==EFalse)
   1.452 +        {
   1.453 +        if (iMode & EForceErase)
   1.454 +            {
   1.455 +            TInt r = FatMount().ErasePassword();
   1.456 +            User::LeaveIfError(r);
   1.457 +            // CFatMountCB::ErasePassword() calls TBusLocalDrive::ForceRemount(), 
   1.458 +            // so need to stop a remount from occurring in next call to :
   1.459 +            // TFsFormatNext::DoRequestL((), TDrive::CheckMount().
   1.460 +            FatMount().Drive().SetChanged(EFalse);
   1.461 +            }
   1.462 +
   1.463 +        RecordOldInfoL();
   1.464 +        InitializeFormatDataL();
   1.465 +        FatMount().DoDismount();
   1.466 +        if (iVariableSize)
   1.467 +            FatMount().ReduceSizeL(0,I64LOW(FatMount().iSize));
   1.468 +        }
   1.469 +    //
   1.470 +    // Blank disk if not EQuickFormat
   1.471 +    //
   1.472 +    if (!iVariableSize && !(iMode & EQuickFormat) && iCurrentStep)
   1.473 +        {
   1.474 +        if (iFormatInfo.iFormatIsCurrent == EFalse)
   1.475 +            {//-- firstly invalidate sectors 0-6 inclusive
   1.476 +            DoZeroFillMediaL(0, 7*iBytesPerSector);
   1.477 +            }
   1.478 +
   1.479 +        TInt ret=FatMount().LocalDrive()->Format(iFormatInfo);
   1.480 +        if (ret!=KErrNone && ret!=KErrEof) // Handle format error
   1.481 +            ret = HandleCorrupt(ret);
   1.482 +        if (ret!=KErrNone && ret!=KErrEof) // KErrEof could be set by LocalDrive()->Format()
   1.483 +            User::Leave(ret);
   1.484 +        if (ret==KErrNone)
   1.485 +            {
   1.486 +            iCurrentStep=100-(100*iFormatInfo.i512ByteSectorsFormatted)/iMaxDiskSectors;
   1.487 +            if (iCurrentStep<=0)
   1.488 +                iCurrentStep=1;
   1.489 +            return;
   1.490 +            }
   1.491 +        }
   1.492 +
   1.493 +    // ReMount since MBR may have been rewritten and partition may have moved / changed size
   1.494 +    TInt ret = LocalDrive()->ForceRemount(0);
   1.495 +    if (ret != KErrNone && ret != KErrNotSupported)
   1.496 +        User::Leave(ret);
   1.497 +
   1.498 +    // MBR may have changed, so need to re-read iHiddenSectors etc.before BPB is written
   1.499 +    InitializeFormatDataL(); 
   1.500 +
   1.501 +    // Translate bad sector number to cluster number which contains that sector
   1.502 +    // This only happens in full format, in quick format they are already cluster numbers
   1.503 +    if (!iVariableSize && !(iMode & EQuickFormat))
   1.504 +        User::LeaveIfError(BadSectorToCluster());
   1.505 +
   1.506 +    //
   1.507 +    // Do the rest of the disk in one lump
   1.508 +    //
   1.509 +    iCurrentStep=0;
   1.510 +    
   1.511 +
   1.512 +    //-- zero-fill media from position 0 to the FAT end, i.e main & backup boot sector, FSInfo and its copy and all FATs
   1.513 +    const TUint32 posFatEnd = ((iSectorsPerFat*iNumberOfFats) + iReservedSectors) * iBytesPerSector; //-- last FAT end position
   1.514 +    
   1.515 +    if (iVariableSize)
   1.516 +        FatMount().EnlargeL(posFatEnd); 
   1.517 +
   1.518 +    DoZeroFillMediaL(0, posFatEnd);
   1.519 +
   1.520 +    //-- Zero fill root directory
   1.521 +    const TInt rootDirSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); 
   1.522 +    const TInt rootDirSize   = iRootDirEntries * KSizeOfFatDirEntry; //-- size in bytes
   1.523 +            
   1.524 +    const TUint32 posRootDirStart = rootDirSector * iBytesPerSector;
   1.525 +    const TUint32 posRootDirEnd   = posRootDirStart + rootDirSize;
   1.526 +
   1.527 +    const TInt numOfRootSectors=(rootDirSize%iBytesPerSector) ? (rootDirSize/iBytesPerSector+1) : (rootDirSize/iBytesPerSector);
   1.528 +    if (iVariableSize)
   1.529 +        FatMount().EnlargeL(iBytesPerSector*numOfRootSectors);
   1.530 +
   1.531 +    DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
   1.532 +
   1.533 +    // Enlarge ram drive to take into account rounding of
   1.534 +    // data start to cluster boundary
   1.535 +    if(iVariableSize && iSectorsPerCluster!=1)
   1.536 +        {
   1.537 +        const TInt firstFreeSector=rootDirSector+numOfRootSectors;
   1.538 +        const TInt firstFreeCluster=firstFreeSector%iSectorsPerCluster ? firstFreeSector/iSectorsPerCluster+1 : firstFreeSector/iSectorsPerCluster;
   1.539 +        const TInt alignedSector=firstFreeCluster*iSectorsPerCluster;
   1.540 +        if(alignedSector!=firstFreeSector)
   1.541 +            FatMount().EnlargeL((alignedSector-firstFreeSector)*iBytesPerSector);
   1.542 +        }
   1.543 +
   1.544 +    //-- FAT[0] must contain media descriptor in the low byte, FAT[1] for fat16/32 may contain some flags
   1.545 +    TBuf8<4> startFat(4);
   1.546 +    startFat.Fill(0xFF);
   1.547 +    
   1.548 +    if(iVariableSize||Is16BitFat()) //-- FAT16 or RAM drive which is always FAT16
   1.549 +        {
   1.550 +        startFat.SetLength(4);
   1.551 +        }
   1.552 +    else //-- FAT12
   1.553 +        {
   1.554 +        startFat.SetLength(3);
   1.555 +        }
   1.556 +     
   1.557 +    startFat[0]=KBootSectorMediaDescriptor; 
   1.558 +
   1.559 +    //-- write FAT[0] and FAT[1] entries to all copies of FAT
   1.560 +    for(TInt i=0;i<iNumberOfFats;i++)
   1.561 +        {
   1.562 +        User::LeaveIfError(LocalDrive()->Write(iBytesPerSector*(iReservedSectors+(iSectorsPerFat*i)),startFat));
   1.563 +        }
   1.564 +
   1.565 +    //-- create boot sectors
   1.566 +    CreateBootSectorL();
   1.567 +
   1.568 +    //-- here we have bad clusters numbers saved by the quick format
   1.569 +    //-- Interpret old bad cluster number to new cluster number and mark new bad clusters
   1.570 +    if (!iVariableSize && iBadClusters.Count()>0)
   1.571 +        {
   1.572 +        //-- Here we need fully mounted volume, so mount it normally.
   1.573 +        FatMount().MountL(EFalse);
   1.574 +
   1.575 +        iBadClusters.Sort();
   1.576 +        TranslateL();
   1.577 +        TInt mark = FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit;
   1.578 +        TInt i;
   1.579 +        
   1.580 +        for (i=0; i<iBadClusters.Count(); ++i)
   1.581 +            FatMount().FAT().WriteL(iBadClusters[i], mark);
   1.582 +        
   1.583 +        FatMount().FAT().FlushL();
   1.584 +#if defined(_DEBUG)
   1.585 +    TInt r=FatMount().CheckDisk();
   1.586 +    __PRINT1(_L("CFatFormatCB::DoFormatStepL() CheckDisk res: %d"),r);
   1.587 +#endif
   1.588 +        }
   1.589 +        else
   1.590 +        {
   1.591 +        //-- We do not need to perform full mount in this case, the TDrive object will be marked as changed in ~CFormatCB and the
   1.592 +        //-- mount will be closed. Therefore on the first access to it it will be mounted normally.
   1.593 +        FatMount().MountL(ETrue); //-- force mount
   1.594 +        }
   1.595 +
   1.596 +    __PRINT1(_L("CFatFormatCB::DoFormatStepL() Format complete drv:%d"), DriveNumber());
   1.597 +    }
   1.598 +
   1.599 +TInt CFatFormatCB::BadSectorToCluster()
   1.600 +    {
   1.601 +    const TInt sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2);
   1.602 +    TInt firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
   1.603 +
   1.604 +    TInt i, r;
   1.605 +    for (i=0; i<iBadSectors.Count(); ++i)
   1.606 +        {
   1.607 +        TInt badSector = iBadSectors[i];
   1.608 +        // Check in rare case that corrupt in critical area
   1.609 +        // which includes bootsector, FAT table, (and root dir if not FAT32)
   1.610 +        if (badSector < firstFreeSector)
   1.611 +            {
   1.612 +            if (badSector == 0) // Boot sector corrupt
   1.613 +                return KErrCorrupt;
   1.614 +            if (badSector < iReservedSectors) // Harmless in reserved area
   1.615 +                continue;
   1.616 +            // Extend reserved area to cover bad sector
   1.617 +            iReservedSectors = badSector + 1;
   1.618 +            firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
   1.619 +            continue;
   1.620 +            }
   1.621 +
   1.622 +        // Figure out bad cluster number and record it
   1.623 +        TInt cluster = (badSector-firstFreeSector)/iSectorsPerCluster + KFatFirstSearchCluster;
   1.624 +        if (iBadClusters.Find(cluster) == KErrNotFound)
   1.625 +            {
   1.626 +            if ((r=iBadClusters.Append(cluster)) != KErrNone)
   1.627 +                return r;
   1.628 +            }
   1.629 +        }
   1.630 +    return KErrNone;
   1.631 +    }
   1.632 +