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 +