Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\sfat\sl_fmt.cpp
25 // Returns the total available ram from UserHal:: or sets an
26 // arbitrary limit upon the WINS ramdisk.
28 static TInt64 GetRamDiskSizeInBytes()
31 #if defined(__EPOC32__)
32 TMemoryInfoV1Buf memInfo;
33 UserHal::MemoryInfo(memInfo);
34 TUint max = memInfo().iTotalRamInBytes; // not really the correct max
37 const TInt KArbitraryWinsRamDiskSize=0x400000; //-- Default size for a Ram drive, 4MB
38 return(KArbitraryWinsRamDiskSize);
42 CFatFormatCB::CFatFormatCB()
44 __PRINT1(_L("CFatFormatCB::CFatFormatCB() [%x]"),this);
47 CFatFormatCB::~CFatFormatCB()
49 __PRINT1(_L("CFatFormatCB::~CFatFormatCB() [%x]"),this);
54 TInt CFatFormatCB::MaxFat16Sectors() const
56 // Calculate the size of a 16 bit FAT
60 TInt fatSizeInBytes=(2*iMaxDiskSectors)/iSectorsPerCluster+(iBytesPerSector-1);
61 return(fatSizeInBytes/iBytesPerSector);
64 TInt CFatFormatCB::MaxFat12Sectors() const
66 // Calculate the size of a 12 bit FAT
70 TInt maxDiskClusters=iMaxDiskSectors/iSectorsPerCluster;
71 TInt fatSizeInBytes=maxDiskClusters+(maxDiskClusters>>1)+(iBytesPerSector-1);
72 return(fatSizeInBytes/iBytesPerSector);
75 //-------------------------------------------------------------------------------------------------------------------
77 Fill a media range from aStartPos to aEndPos with zeroes.
78 @param aStartPos start media position
79 @param aEndPos end media position
81 void CFatFormatCB::DoZeroFillMediaL(TInt64 aStartPos, TInt64 aEndPos)
83 ASSERT(aStartPos <= aEndPos && aStartPos >=0 && aEndPos >=0);
86 CleanupClosePushL(buf);
88 const TInt KBufMaxSz=32768; //-- zero-buffer Maximal size, bytes
89 const TInt KBufMinSz=512; //-- zero-buffer minimal size, bytes
91 if(buf.CreateMax(KBufMaxSz) != KErrNone)
93 buf.CreateMaxL(KBufMinSz); //-- OOM, try to create smaller buffer
98 TInt64 rem = aEndPos - aStartPos;
101 const TUint32 bytesToWrite=(TUint32)Min(rem, buf.Size());
102 TPtrC8 ptrData(buf.Ptr(), bytesToWrite);
104 User::LeaveIfError(LocalDrive()->Write(aStartPos, ptrData));
106 aStartPos+=bytesToWrite;
110 CleanupStack::PopAndDestroy(&buf);
113 //-------------------------------------------------------------------------------------------------------------------
115 static TInt DiskSizeInSectorsL(TInt64 aSizeInBytes)
117 const TInt64 totalSectors64=aSizeInBytes>>KDefSectorSzLog2;
118 const TInt totalSectors32=I64LOW(totalSectors64);
119 __PRINT2(_L("Disk size:%LU, max disk sectors:%d"),aSizeInBytes, totalSectors32);
120 return totalSectors32;
125 suggest FAT type according to the FAT volume metrics
126 @return calculated FAT type
128 TFatType CFatFormatCB::SuggestFatType() const
130 const TUint32 rootDirSectors = (iRootDirEntries*KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
131 const TUint32 dataSectors = iMaxDiskSectors - (iReservedSectors + (iNumberOfFats * iSectorsPerFat) + rootDirSectors);
132 const TUint32 clusterCnt = dataSectors/ iSectorsPerCluster;
134 //-- magic. see FAT specs for details.
135 if(clusterCnt < 4085)
137 else if(clusterCnt < 65525)
144 Initialize format data.
146 void CFatFormatCB::InitializeFormatDataL()
149 __PRINT1(_L("CFatFormatCB::InitializeFormatDataL() drv:%d"), Drive().DriveNumber());
150 TLocalDriveCapsV6Buf caps;
151 User::LeaveIfError(LocalDrive()->Caps(caps));
152 iVariableSize=((caps().iMediaAtt)&KMediaAttVariableSize) ? (TBool)ETrue : (TBool)EFalse;
154 iBytesPerSector=KDefaultSectorSize;
155 iSectorSizeLog2 = Log2(iBytesPerSector);
156 iHiddenSectors=caps().iHiddenSectors;
161 {// Variable size implies ram disk
162 iMaxDiskSectors=DiskSizeInSectorsL(GetRamDiskSizeInBytes());
163 InitFormatDataForVariableSizeDisk(iMaxDiskSectors);
166 {//-- fixed-size media
167 iMaxDiskSectors=DiskSizeInSectorsL(caps().iSize);
169 __PRINT3(_L("::InitializeFormatDataL() iMode:0x%x, ilen:%d, extrai:%d"), iMode, iSpecialInfo.Length(), caps().iExtraInfo);
171 if(iMode & ESpecialFormat)
173 if(iSpecialInfo.Length())
175 if (caps().iExtraInfo) // conflict between user and media
176 User::Leave(KErrNotSupported);
177 else // User-specified
178 User::LeaveIfError(InitFormatDataForFixedSizeDiskUser(iMaxDiskSectors));
182 if (caps().iExtraInfo)
183 User::LeaveIfError(InitFormatDataForFixedSizeDiskCustom(caps().iFormatInfo));
185 User::LeaveIfError(InitFormatDataForFixedSizeDiskNormal(iMaxDiskSectors, caps()));
188 else //if(iMode & ESpecialFormat)
190 // Normal format with default values
191 // - Media with special format requirements will always use them
192 // even without the ESpecialFormat option.
193 if(caps().iExtraInfo)
194 User::LeaveIfError(InitFormatDataForFixedSizeDiskCustom(caps().iFormatInfo));
196 User::LeaveIfError(InitFormatDataForFixedSizeDiskNormal(iMaxDiskSectors, caps()));
199 } //else(iVariableSize)
203 Initialize the format parameters for a variable sized disk
205 @param aDiskSizeInSectors volume size in sectors
206 @return standard error code
208 TInt CFatFormatCB::InitFormatDataForVariableSizeDisk(TInt aDiskSizeInSectors)
210 iNumberOfFats=2; // 1 FAT 1 Indirection table (FIT)
212 iRootDirEntries=2*(4*KDefaultSectorSize)/sizeof(SFatDirEntry);
213 TInt minSectorsPerCluster=(aDiskSizeInSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
214 iSectorsPerCluster=1;
215 while (minSectorsPerCluster>iSectorsPerCluster)
216 iSectorsPerCluster<<=1;
217 __PRINT1(_L("iSectorsPerCluster = %d"),iSectorsPerCluster);
218 iSectorsPerFat=MaxFat16Sectors();
219 __PRINT1(_L("iSectorsPerFat = %d"),iSectorsPerFat);
220 iFileSystemName=KFileSystemName16;
225 TInt CFatFormatCB::HandleCorrupt(TInt aError)
227 // Handle disk corrupt during format. It needs media driver's support.
228 // Media driver should handle DLocalDrive::EGetLastErrorInfo request in
229 // its Request function, filling in proper error information.
233 __PRINT2(_L("CFatFormatCB::HandleCorrupt(%d) drv:%d"), aError, Drive().DriveNumber());
235 TPckgBuf<TErrorInfo> info;
236 TInt r = LocalDrive()->GetLastErrorInfo(info);
240 __PRINT1(_L("....GetLastErrorInfo() err:%d"), r);
243 if (r == KErrNotSupported)
245 else if (r != KErrNone)
248 __PRINT3(_L("....TErrorInfo iReasonCode:%d, iErrorPos:%LU, iOtherInfo:%d"), info().iReasonCode, info().iErrorPos, info().iOtherInfo);
250 // if no error reported by GetLastErrorInfo(), return the original error
251 if (info().iReasonCode == KErrNone)
254 if (info().iReasonCode!=KErrNone && info().iReasonCode!=TErrorInfo::EBadSector)
255 return info().iReasonCode;
257 // First bad sector met
258 TInt sectorsDone = (TInt)(info().iErrorPos >> iSectorSizeLog2);
259 TInt badSector = iFormatInfo.i512ByteSectorsFormatted + sectorsDone;
260 iBadSectors.Append(badSector);
262 // Update format information
263 iFormatInfo.i512ByteSectorsFormatted += sectorsDone+1;
267 void CFatFormatCB::TranslateL()
269 // Change bad cluster number to new value with regard to new format parameters
272 if (iDiskCorrupt || !(iMode & EQuickFormat))
275 TInt size = 1 << FatMount().ClusterSizeLog2();
276 TUint8* readBuf = new(ELeave) TUint8[size];
277 TPtr8 readBufPtr(readBuf, size);
278 RArray<TInt> newArray;
279 TInt r = DoTranslate(readBufPtr, newArray);
282 User::LeaveIfError(r);
285 #define calcSector(n) (n+oFirstFreeSector-nFirstFreeSector)
286 TInt CFatFormatCB::DoTranslate(TPtr8& aBuf, RArray<TInt>& aArray)
291 // old format parameters
292 TInt oFirstFreeSector = iOldFirstFreeSector;
293 TInt oSectorsPerCluster = iOldSectorsPerCluster;
294 // new format parameters
295 TInt nFirstFreeSector = FatMount().iFirstFreeByte>>FatMount().SectorSizeLog2();
296 TInt nSectorsPerCluster = FatMount().SectorsPerCluster();
298 if (oFirstFreeSector==nFirstFreeSector && oSectorsPerCluster==nSectorsPerCluster)
302 for (i=0; i<iBadClusters.Count(); ++i)
305 Cluster boundary may change due to format parameter change.
306 Old: |-- ... --|----|----|----|----|----|----|----|
308 New: |--- ... ---|------|------|------|------|------|
311 TInt begSector = calcSector((iBadClusters[i]-2)*oSectorsPerCluster);
312 begSector = Max(begSector, nFirstFreeSector);
313 TInt endSector = calcSector(((iBadClusters[i]-1)*oSectorsPerCluster)-1);
314 endSector = Max(endSector, nFirstFreeSector);
315 TInt begCluster = (begSector/iSectorsPerCluster)+KFatFirstSearchCluster;
316 TInt endCluster = (endSector/iSectorsPerCluster)+KFatFirstSearchCluster;
317 if (begCluster == endCluster) // old cluster is in a new cluster
319 if (aArray.Find(begCluster) == KErrNotFound)
320 if ((r=aArray.Append(begCluster)) != KErrNone)
324 // deal with old cluster cross over several new clusters
325 TInt offset = (begSector-(begCluster-2)*iSectorsPerCluster)<<iSectorSizeLog2;
326 TInt len = (endSector-(endCluster-2)*iSectorsPerCluster)<<iSectorSizeLog2;
328 for (j=begCluster; j<=endCluster; ++j)
329 // Because each old bad cluster cross several new clusters,
330 // we have to verify which new cluster is bad really
332 TInt addr = (nFirstFreeSector+(j-2)*iSectorsPerCluster)<<iSectorSizeLog2;
333 TInt clusterLen = (1<<iSectorSizeLog2) * iSectorsPerCluster;
335 r = LocalDrive()->Read(addr+offset,clusterLen-offset,aBuf);
336 else if (j == endCluster && len)
337 r = LocalDrive()->Read(addr,len,aBuf);
339 r = LocalDrive()->Read(addr,clusterLen,aBuf);
340 if (r == KErrCorrupt) // new cluster j is corrupt
341 if ((r=aArray.Append(j)) != KErrNone)
345 // Update iBadClusters with aArray
346 iBadClusters.Reset();
347 for (i=0; i<aArray.Count(); ++i)
348 if ((r=iBadClusters.Append(aArray[i])) != KErrNone)
355 //-------------------------------------------------------------------------------------------------------------------
356 /** override from CFormatCB, additional interfaces implementation */
357 TInt CFatFormatCB::GetInterface(TInt aInterfaceId, TAny*& /*aInterface*/, TAny* aInput)
359 if(aInterfaceId == ESetFmtParameters)
361 return DoProcessTVolFormatParam((const TVolFormatParam_FAT*)aInput);
364 return KErrNotSupported;
367 //-------------------------------------------------------------------------------------------------------------------
369 Process formatting parameters passed as TVolFormatParam_FAT structure.
370 @param apVolFormatParam pointer to the formatting parameters.
371 @return standard error code
373 TInt CFatFormatCB::DoProcessTVolFormatParam(const TVolFormatParam_FAT* apVolFormatParam)
375 if(apVolFormatParam->iUId != TVolFormatParam::KUId || apVolFormatParam->FSNameHash() != TVolFormatParam::CalcFSNameHash(KFileSystemName_FAT))
381 //-- Populate iSpecialInfo with the data taken from apVolFormatParam.
382 //-- for formatting FAT volume iSpecialInfo can hold absolutely all required data from apVolFormatParam.
383 //-- if some additional data from apVolFormatParam are required for some reason, figure out youself how to store and use them.
384 TLDFormatInfo& fmtInfo = iSpecialInfo();
385 new(&fmtInfo) TLDFormatInfo; //-- initialise the structure in the buffer
388 //-- sectors per cluster
389 fmtInfo.iSectorsPerCluster = (TUint16)apVolFormatParam->SectPerCluster();
392 const TFatSubType fatSubType = apVolFormatParam->FatSubType();
394 if(fatSubType != ENotSpecified && fatSubType != EFat12 && fatSubType != EFat16 && fatSubType != EFat32)
398 fmtInfo.iFATBits = (TLDFormatInfo::TFATBits)fatSubType; //-- FAT12/16/32/not specified
400 //-- number of FAT tables
401 switch(apVolFormatParam->NumFATs())
403 case 0: //-- "not specified, default"
407 fmtInfo.iFlags |= TLDFormatInfo::EOneFatTable;
411 fmtInfo.iFlags |= TLDFormatInfo::ETwoFatTables;
414 default: //-- more than KMaxFatTablesSupported is not supported
419 //-- number of reserved sectors
420 fmtInfo.iReservedSectors = (TUint16)apVolFormatParam->ReservedSectors();