|
1 /* |
|
2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * CFat32FileSystem is the concrete class which is responsible for |
|
16 * creating a FAT32 image. This class constitutes the method to |
|
17 * create boot sector, FAT Table and data region of a FAT32 Image |
|
18 * @internalComponent |
|
19 * @released |
|
20 * |
|
21 */ |
|
22 |
|
23 #include"fat32filesystem.h" |
|
24 |
|
25 /** |
|
26 Initializes the boot sector of a FAT 32 volume |
|
27 |
|
28 @internalComponent |
|
29 @released |
|
30 |
|
31 @param aPartitionSize partition size in bytes |
|
32 @param aConfigurableFatAttributes ConfigurableFatAttributes |
|
33 */ |
|
34 void CFat32FileSystem::CreateBootSector(Long64 aPartitionSize,ConfigurableFatAttributes* aConfigurableFatAttributes) |
|
35 { |
|
36 //initializes the boot sector values |
|
37 iFAT32BootSector.SetOEMName(); |
|
38 unsigned char* OEMName = iFAT32BootSector.OEMName(); |
|
39 iFAT32BootSector.SetJumpInstruction(); |
|
40 unsigned char* JmpBoot = iFAT32BootSector.JumpInstruction(); |
|
41 iFAT32BootSector.SetBytesPerSector(aConfigurableFatAttributes->iDriveSectorSize); |
|
42 unsigned short BytesPerSector = (unsigned short)iFAT32BootSector.BytesPerSector(); |
|
43 iFAT32BootSector.ComputeSectorsPerCluster(aPartitionSize); |
|
44 unsigned char SectorsPerCluster = iFAT32BootSector.SectorsPerCluster(); |
|
45 iFAT32BootSector.SetReservedSectors(); |
|
46 unsigned short ReservedSectors = iFAT32BootSector.ReservedSectors(); |
|
47 iFAT32BootSector.SetNumberOfFats(aConfigurableFatAttributes->iDriveNoOfFATs); |
|
48 unsigned char NumFats = iFAT32BootSector.NumberOfFats(); |
|
49 iFAT32BootSector.SetRootDirEntries(); |
|
50 unsigned short RootDirEntries = iFAT32BootSector.RootDirEntries(); |
|
51 iFAT32BootSector.ComputeTotalSectors(aPartitionSize); |
|
52 unsigned short LowSectors = iFAT32BootSector.LowSectorsCount(); |
|
53 iFAT32BootSector.SetMedia(); |
|
54 unsigned char Media = iFAT32BootSector.Media(); |
|
55 iFAT32BootSector.ComputeFatSectors(aPartitionSize); |
|
56 unsigned short FatSectors = iFAT32BootSector.FatSectors(); |
|
57 iFAT32BootSector.SetSectorsPerTrack(); |
|
58 unsigned short SectorPerTrack = iFAT32BootSector.SectorsPerTrack(); |
|
59 iFAT32BootSector.SetNumberOfHeads(); |
|
60 unsigned short NumberOfHeads = iFAT32BootSector.NumberOfHeads(); |
|
61 iFAT32BootSector.SetHiddenSectors(); |
|
62 unsigned int HiddenSectors = iFAT32BootSector.HiddenSectors(); |
|
63 unsigned int HighSectorsCount = iFAT32BootSector.HighSectorsCount(); |
|
64 unsigned int FatSectors32 = iFAT32BootSector.FatSectors32(); |
|
65 iFAT32BootSector.SetExtFlags(); |
|
66 unsigned short ExtFlags = iFAT32BootSector.ExtFlags(); |
|
67 iFAT32BootSector.SetFileSystemVersion(); |
|
68 unsigned short FileSystemVersion = iFAT32BootSector.FileSystemVersion(); |
|
69 iFAT32BootSector.SetRootCluster(); |
|
70 unsigned int RootCluster = iFAT32BootSector.RootCluster(); |
|
71 iFAT32BootSector.SetFSInfo(); |
|
72 unsigned short FSInfo = iFAT32BootSector.FSInfo(); |
|
73 iFAT32BootSector.SetBackUpBootSector(); |
|
74 unsigned short BackUpBootSector = iFAT32BootSector.BackUpBootSector(); |
|
75 iFAT32BootSector.SetFutureReserved(); |
|
76 unsigned char* FutureReserved = iFAT32BootSector.FutureReserved(); |
|
77 iFAT32BootSector.SetBootSectorDriveNumber(); |
|
78 unsigned char BootSectorDriveNumber = iFAT32BootSector.BootSectorDriveNumber(); |
|
79 iFAT32BootSector.SetReservedByte(); |
|
80 unsigned char ReservedByte = iFAT32BootSector.ReservedByte(); |
|
81 iFAT32BootSector.SetBootSignature(); |
|
82 unsigned char BootSignature = iFAT32BootSector.BootSignature(); |
|
83 iFAT32BootSector.SetVolumeId(); |
|
84 unsigned int VolumeId = iFAT32BootSector.VolumeId(); |
|
85 iFAT32BootSector.SetVolumeLab(aConfigurableFatAttributes->iDriveVolumeLabel); |
|
86 unsigned char* VolumeLab = iFAT32BootSector.VolumeLab(); |
|
87 iFAT32BootSector.SetFileSysType(); |
|
88 unsigned char* FileSystemType = iFAT32BootSector.FileSysType(); |
|
89 |
|
90 //copying of boot sector values in to the array |
|
91 iData = new unsigned char[BytesPerSector]; |
|
92 unsigned int pos = 0; |
|
93 memcpy(&iData[pos],JmpBoot,3); |
|
94 pos += 3; |
|
95 memcpy(&iData[pos],OEMName,8); |
|
96 pos += 8; |
|
97 memcpy(&iData[pos],&BytesPerSector,2); |
|
98 pos += 2; |
|
99 memcpy(&iData[pos],&SectorsPerCluster,1); |
|
100 pos += 1; |
|
101 memcpy(&iData[pos],&ReservedSectors,2); |
|
102 pos += 2; |
|
103 memcpy(&iData[pos],&NumFats,1); |
|
104 pos += 1; |
|
105 memcpy(&iData[pos],&RootDirEntries,2); |
|
106 pos += 2; |
|
107 memcpy(&iData[pos],&LowSectors,2); |
|
108 pos += 2; |
|
109 memcpy(&iData[pos],&Media,1); |
|
110 pos += 1; |
|
111 memcpy(&iData[pos],&FatSectors,2); |
|
112 pos += 2; |
|
113 memcpy(&iData[pos],&SectorPerTrack,2); |
|
114 pos += 2; |
|
115 memcpy(&iData[pos],&NumberOfHeads,2); |
|
116 pos += 2; |
|
117 memcpy(&iData[pos],&HiddenSectors,4); |
|
118 pos += 4; |
|
119 memcpy(&iData[pos],&HighSectorsCount,4); |
|
120 pos += 4; |
|
121 memcpy(&iData[pos],&FatSectors32,4); |
|
122 pos += 4; |
|
123 memcpy(&iData[pos],&ExtFlags,2); |
|
124 pos += 2; |
|
125 memcpy(&iData[pos],&FileSystemVersion,2); |
|
126 pos += 2; |
|
127 memcpy(&iData[pos],&RootCluster,4); |
|
128 pos += 4; |
|
129 memcpy(&iData[pos],&FSInfo,2); |
|
130 pos += 2; |
|
131 memcpy(&iData[pos],&BackUpBootSector,2); |
|
132 pos += 2; |
|
133 memcpy(&iData[pos],FutureReserved,12); |
|
134 pos += 12; |
|
135 memcpy(&iData[pos],&BootSectorDriveNumber,1); |
|
136 pos += 1; |
|
137 memcpy(&iData[pos],&ReservedByte,1); |
|
138 pos += 1; |
|
139 memcpy(&iData[pos],&BootSignature,1); |
|
140 pos += 1; |
|
141 memcpy(&iData[pos],&VolumeId,4); |
|
142 pos += 4; |
|
143 memcpy(&iData[pos],VolumeLab,11); |
|
144 pos += 11; |
|
145 memcpy(&iData[pos],FileSystemType,8); |
|
146 pos += 8; |
|
147 while(pos < BytesPerSector) |
|
148 { |
|
149 iData[pos] = 0x00; |
|
150 pos++; |
|
151 } |
|
152 // Set sector [510] as 0xAA and [511] as 0x55 to mark the end of boot sector |
|
153 iData[KSizeOfFatBootSector-2] = 0x55; |
|
154 iData[KSizeOfFatBootSector-1] = 0xAA; |
|
155 // It is perfectly ok for the last two bytes of the boot sector to also |
|
156 // have the signature 0xAA55. |
|
157 iData[BytesPerSector-2] = 0x55; |
|
158 iData[BytesPerSector-1] = 0xAA; |
|
159 ComputeClusterSizeInBytes(); |
|
160 ComputeRootDirSectors(); |
|
161 ComputeBytesPerSector(); |
|
162 MessageHandler::ReportMessage (INFORMATION,BOOTSECTORCREATEMSG, "FAT32"); |
|
163 } |
|
164 |
|
165 /** |
|
166 Writes the boot sector of a FAT 32 volume |
|
167 |
|
168 @internalComponent |
|
169 @released |
|
170 |
|
171 @param aOutPutStream handle for the image file |
|
172 */ |
|
173 void CFat32FileSystem::WriteBootSector(ofstream& aOutPutStream) |
|
174 { |
|
175 MessageHandler::ReportMessage (INFORMATION,BOOTSECTORWRITEMSG, "FAT32"); |
|
176 aOutPutStream.write(reinterpret_cast<char*>(&iData[0]),iFAT32BootSector.BytesPerSector()); |
|
177 aOutPutStream.flush(); |
|
178 } |
|
179 |
|
180 /** |
|
181 Creates and writes the FAT Table sector of a FAT 32 volume |
|
182 |
|
183 @internalComponent |
|
184 @released |
|
185 |
|
186 @param aClustersPerEntryMap iDatastructure containing the mapping of clusters allocated to the file. |
|
187 @param aOutPutStream handle for the image file |
|
188 */ |
|
189 void CFat32FileSystem::CreateFatTable(ofstream& aOutPutStream) |
|
190 { |
|
191 //data is written from cluster 2 |
|
192 unsigned int clusterCounter = 2; |
|
193 unsigned int FATSizeInBytes = (iFAT32BootSector.FatSectors32()) * (iFAT32BootSector.BytesPerSector()); |
|
194 // Each FAT32 entries occupies 4 bytes, hence divided by 4 |
|
195 unsigned int totalFatEntries = FATSizeInBytes / 4; |
|
196 //contains the address of FAT Table |
|
197 unsigned int *FatTable = new unsigned int[totalFatEntries]; |
|
198 |
|
199 /**Say cluster 5 starts at 5 and occupies clusters 7 and 9. The FAT table should have the |
|
200 value 7 at cluster location 5, the value 9 at cluster 7 and 'eof' value at cluster 9. |
|
201 Below algorithm serves this algorithm |
|
202 */ |
|
203 int previousCluster; |
|
204 FatTable[0] = KFat32FirstEntry; |
|
205 FatTable[1] = EOF32; |
|
206 Iterator itr = iClustersPerEntry->begin(); |
|
207 while(itr != iClustersPerEntry->end()) |
|
208 { |
|
209 previousCluster = itr->second; |
|
210 if(iClustersPerEntry->count(itr->first) > 1) |
|
211 { |
|
212 for(unsigned int i = 1; i < iClustersPerEntry->count(itr->first); i++) |
|
213 { |
|
214 FatTable[previousCluster] = (++itr)->second; |
|
215 previousCluster = itr->second; |
|
216 ++clusterCounter; |
|
217 } |
|
218 } |
|
219 FatTable[previousCluster] = EOF32; |
|
220 itr++; |
|
221 ++clusterCounter; |
|
222 } |
|
223 // Each FAT32 entries occupies 4 bytes, hence multiply by 4 |
|
224 std::string aFatString(reinterpret_cast<char*>(FatTable),clusterCounter*4); |
|
225 delete[] FatTable; |
|
226 if(clusterCounter < totalFatEntries) |
|
227 { |
|
228 // Each FAT32 entries occupies 4 bytes, hence multiply by 4 |
|
229 aFatString.append((totalFatEntries - clusterCounter)*4, 0); |
|
230 } |
|
231 MessageHandler::ReportMessage (INFORMATION,FATTABLEWRITEMSG, |
|
232 "FAT32"); |
|
233 //Write FAT table multiple times depending on the value of No of FATS set. |
|
234 unsigned int noOfFats = iFAT32BootSector.NumberOfFats(); |
|
235 for(unsigned int i=0; i<noOfFats; i++) |
|
236 { |
|
237 aOutPutStream.write(aFatString.c_str(),aFatString.length()); |
|
238 } |
|
239 aFatString.erase(); |
|
240 aOutPutStream.flush(); |
|
241 } |
|
242 |
|
243 /** |
|
244 FSINfo iData structure specific to FAT32 |
|
245 |
|
246 @internalComponent |
|
247 @released |
|
248 |
|
249 @param aOutPutStream handle for the image file |
|
250 */ |
|
251 void CFat32FileSystem::CreateFSinfoSector(ofstream& aOutPutStream) |
|
252 { |
|
253 int counter = 0; |
|
254 unsigned int bytesPerSector = iFAT32BootSector.BytesPerSector(); |
|
255 FSinfoData = new unsigned char[bytesPerSector]; |
|
256 iFSInfo.SetFSInfo(); |
|
257 memcpy(&FSinfoData[counter], &iFSInfo.FSI_LeadSign,4); |
|
258 counter += 4; |
|
259 memcpy(&FSinfoData[counter], &iFSInfo.FSI_Reserved,480); |
|
260 counter += 480; |
|
261 memcpy(&FSinfoData[counter], &iFSInfo.FSI_StrucSig,4); |
|
262 counter += 4; |
|
263 memcpy(&FSinfoData[counter], &iFSInfo.FSI_Free_Count,4); |
|
264 counter += 4; |
|
265 memcpy(&FSinfoData[counter], &iFSInfo.FSI_Nxt_Free,4); |
|
266 counter += 4; |
|
267 memcpy(&FSinfoData[counter], &iFSInfo.FSI_Reserved2,12); |
|
268 counter += 12; |
|
269 memcpy(&FSinfoData[counter], &iFSInfo.FSI_TrailSig,4); |
|
270 counter += 4; |
|
271 counter += (bytesPerSector-KSizeOfFatBootSector); |
|
272 aOutPutStream.write(reinterpret_cast<char*>(&FSinfoData[0]),counter); |
|
273 aOutPutStream.flush(); |
|
274 } |
|
275 |
|
276 /** |
|
277 Initializes the left over reserved sectors of FAT32 image other than boot sector and FSinfo iData sector(sector 0 and 1) |
|
278 |
|
279 @internalComponent |
|
280 @released |
|
281 |
|
282 @param aOutPutStream handle to file stream |
|
283 */ |
|
284 void CFat32FileSystem::RestReservedSectors(ofstream& aOutPutStream) |
|
285 { |
|
286 unsigned int bytesPerSector = iFAT32BootSector.BytesPerSector(); |
|
287 unsigned char* nullsector = new unsigned char[bytesPerSector]; |
|
288 for(unsigned int counter = 0; counter < bytesPerSector ; counter++) |
|
289 { |
|
290 nullsector[counter] = 0; |
|
291 } |
|
292 nullsector[KSizeOfFatBootSector-2] = 0x55; |
|
293 nullsector[KSizeOfFatBootSector-1] = 0xAA; |
|
294 for(unsigned int sectorcount = 2; sectorcount < (unsigned int)(iFAT32BootSector.ReservedSectors()) - 1; sectorcount++) |
|
295 { |
|
296 // Sector no 6 and 7 contains the duplicate copy of boot sector and FSInfo sector in a FAT32 Image |
|
297 if(sectorcount == KBootBackupSector) |
|
298 { |
|
299 aOutPutStream.write(reinterpret_cast<char*>(&iData[0]),bytesPerSector); |
|
300 aOutPutStream.flush(); |
|
301 } |
|
302 if(sectorcount == KFatBackupSector) |
|
303 { |
|
304 aOutPutStream.write(reinterpret_cast<char*>(&FSinfoData[0]),bytesPerSector); |
|
305 aOutPutStream.flush(); |
|
306 } |
|
307 else |
|
308 { |
|
309 aOutPutStream.write(reinterpret_cast<char*>(&nullsector[0]),bytesPerSector); |
|
310 aOutPutStream.flush(); |
|
311 } |
|
312 } |
|
313 delete[] nullsector; |
|
314 nullsector = NULL; |
|
315 } |
|
316 |
|
317 /** |
|
318 compute the cluster size in bytes,iClusterSize |
|
319 |
|
320 @internalComponent |
|
321 @released |
|
322 */ |
|
323 void CFat32FileSystem::ComputeClusterSizeInBytes() |
|
324 { |
|
325 iClusterSize = iFAT32BootSector.SectorsPerCluster()*iFAT32BootSector.BytesPerSector(); |
|
326 } |
|
327 |
|
328 /** |
|
329 Compute the count of sectors occupied by the root directory,iRootDirSectors. |
|
330 |
|
331 @internalComponent |
|
332 @released |
|
333 */ |
|
334 void CFat32FileSystem::ComputeRootDirSectors() |
|
335 { |
|
336 iRootDirSectors = (iFAT32BootSector.RootDirEntries() * (KDefaultRootDirEntrySize) + |
|
337 (iFAT32BootSector.BytesPerSector() - 1)) / iFAT32BootSector.BytesPerSector(); |
|
338 } |
|
339 |
|
340 /* |
|
341 Initialize the Bytes per Sector variable value. |
|
342 |
|
343 @internalComponent |
|
344 @released |
|
345 */ |
|
346 void CFat32FileSystem::ComputeBytesPerSector() |
|
347 { |
|
348 iBytesPerSector = iFAT32BootSector.BytesPerSector(); |
|
349 } |
|
350 |
|
351 /* |
|
352 Sets the total number of clusters in iData segment of the FAT volume |
|
353 |
|
354 |
|
355 @internalComponent |
|
356 @released |
|
357 |
|
358 @aPartitionSize partition size in bytes |
|
359 */ |
|
360 void CFat32FileSystem::ComputeTotalClusters(Long64 aPartitionSize) |
|
361 { |
|
362 unsigned int totalDataSectors = iFAT32BootSector.TotalSectors(aPartitionSize) - |
|
363 ((iFAT32BootSector.NumberOfFats() * |
|
364 iFAT32BootSector.FatSectors32()) + |
|
365 iRootDirSectors+iFAT32BootSector.ReservedSectors()); |
|
366 |
|
367 iTotalClusters = totalDataSectors / iFAT32BootSector.SectorsPerCluster(); |
|
368 if(iTotalClusters < KMinimumFat32Clusters) |
|
369 { |
|
370 throw ErrorHandler(BOOTSECTORERROR,"Low Partition Size",__FILE__, __LINE__); |
|
371 } |
|
372 else if(iTotalClusters > KMaximumFat32Clusters) |
|
373 { |
|
374 throw ErrorHandler(BOOTSECTORERROR,"high Partition Size",__FILE__, __LINE__); |
|
375 } |
|
376 } |
|
377 /** |
|
378 This methods encapsulates the function call to write a complete FAT32 Image |
|
379 |
|
380 @internalComponent |
|
381 @released |
|
382 |
|
383 @param aPartitionSize partition size in bytes |
|
384 @param aNodeList Directory structure |
|
385 @param aOutPutStream output stream for writing file image |
|
386 @param aImageFileName image file name |
|
387 @param aLogFileName log file name |
|
388 @param aConfigurableFatAttributes ConfigurableFatAttributes |
|
389 */ |
|
390 |
|
391 void CFat32FileSystem::Execute(Long64 aPartitionSize,EntryList aNodeList, |
|
392 ofstream& aOutPutStream,ConfigurableFatAttributes* aConfigurableFatAttributes) |
|
393 { |
|
394 CDirRegion* dirRegionPtr = NULL; |
|
395 try |
|
396 { |
|
397 CreateBootSector(aPartitionSize,aConfigurableFatAttributes); |
|
398 ComputeTotalClusters(aPartitionSize); |
|
399 WriteBootSector(aOutPutStream); |
|
400 dirRegionPtr = new CDirRegion(aNodeList,this); |
|
401 dirRegionPtr->Execute(); |
|
402 iClustersPerEntry = dirRegionPtr->GetClustersPerEntryMap(); |
|
403 CreateFSinfoSector(aOutPutStream); |
|
404 RestReservedSectors(aOutPutStream); |
|
405 CreateFatTable(aOutPutStream); |
|
406 dirRegionPtr->WriteClustersIntoFile(aOutPutStream); |
|
407 delete dirRegionPtr; |
|
408 dirRegionPtr = NULL; |
|
409 } |
|
410 catch(ErrorHandler &aError) |
|
411 { |
|
412 delete dirRegionPtr; |
|
413 dirRegionPtr = NULL; |
|
414 throw ErrorHandler(aError.iMessageIndex,(char*)aError.iSubMessage.c_str(),(char*)aError.iFileName.c_str(),aError.iLineNumber); |
|
415 } |
|
416 /** |
|
417 Irrespective of successful or unsuccessful data drive image generation ROFSBUILD |
|
418 may try to generate images for successive ".oby" file input. |
|
419 During this course unhandled exceptions may cause leaving some memory on heap |
|
420 unused. so the unhandled exceptions handling is used to free the memory allocated |
|
421 on heap. |
|
422 */ |
|
423 catch(...) |
|
424 { |
|
425 delete dirRegionPtr; |
|
426 dirRegionPtr = NULL; |
|
427 throw ErrorHandler(UNKNOWNERROR, __FILE__, __LINE__); |
|
428 } |
|
429 } |
|
430 |
|
431 /** |
|
432 Destructor of class CFat32FileSystem |
|
433 |
|
434 @internalComponent |
|
435 @released |
|
436 */ |
|
437 CFat32FileSystem::~CFat32FileSystem() |
|
438 { |
|
439 delete[] FSinfoData; |
|
440 }; |