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