|
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 * CFat16FileSystem is the concrete class which is responsible for |
|
16 * creating a FAT16 image. This class constitutes the method to |
|
17 * create boot sector, FAT Table and data region of a FAT16 Image |
|
18 * @internalComponent |
|
19 * @released |
|
20 * |
|
21 */ |
|
22 |
|
23 #include"fat16filesystem.h" |
|
24 |
|
25 |
|
26 /** |
|
27 Initializes the boot sector of a FAT 16 volume |
|
28 |
|
29 @internalComponent |
|
30 @released |
|
31 |
|
32 @param aPartitionSize partition size in bytes |
|
33 @param aConfigurableFatAttributes ConfigurableFatAttributes |
|
34 */ |
|
35 void CFat16FileSystem::CreateBootSector(Long64 aPartitionSize,ConfigurableFatAttributes* aConfigurableFatAttributes) |
|
36 { |
|
37 iFAT16BootSector.SetOEMName(); |
|
38 unsigned char* OEMName = iFAT16BootSector.OEMName(); |
|
39 iFAT16BootSector.SetJumpInstruction(); |
|
40 unsigned char* JmpBoot = iFAT16BootSector.JumpInstruction(); |
|
41 iFAT16BootSector.SetBytesPerSector(aConfigurableFatAttributes->iDriveSectorSize); |
|
42 unsigned short BytesPerSector = (unsigned short)iFAT16BootSector.BytesPerSector(); |
|
43 iFAT16BootSector.ComputeSectorsPerCluster(aPartitionSize); |
|
44 unsigned char SectorsPerCluster = iFAT16BootSector.SectorsPerCluster(); |
|
45 iFAT16BootSector.SetReservedSectors(); |
|
46 unsigned short ReservedSectors = iFAT16BootSector.ReservedSectors(); |
|
47 iFAT16BootSector.SetNumberOfFats(aConfigurableFatAttributes->iDriveNoOfFATs); |
|
48 unsigned char NumFats = iFAT16BootSector.NumberOfFats(); |
|
49 iFAT16BootSector.SetRootDirEntries(); |
|
50 unsigned short RootDirEntries = iFAT16BootSector.RootDirEntries(); |
|
51 iFAT16BootSector.ComputeTotalSectors(aPartitionSize); |
|
52 unsigned short LowSectors = iFAT16BootSector.LowSectorsCount(); |
|
53 iFAT16BootSector.SetMedia(); |
|
54 unsigned char Media = iFAT16BootSector.Media(); |
|
55 iFAT16BootSector.ComputeFatSectors(aPartitionSize); |
|
56 unsigned short FatSectors = iFAT16BootSector.FatSectors(); |
|
57 iFAT16BootSector.SetSectorsPerTrack(); |
|
58 unsigned short SectorPerTrack = iFAT16BootSector.SectorsPerTrack(); |
|
59 iFAT16BootSector.SetNumberOfHeads(); |
|
60 unsigned short NumberOfHeads = iFAT16BootSector.NumberOfHeads(); |
|
61 iFAT16BootSector.SetHiddenSectors(); |
|
62 unsigned int HiddenSectors = iFAT16BootSector.HiddenSectors(); |
|
63 unsigned int HighSectorsCount = iFAT16BootSector.HighSectorsCount(); |
|
64 iFAT16BootSector.SetBootSectorDriveNumber(); |
|
65 unsigned char BootSectorDriveNumber = iFAT16BootSector.BootSectorDriveNumber(); |
|
66 iFAT16BootSector.SetReservedByte(); |
|
67 unsigned char ReservedByte = iFAT16BootSector.ReservedByte(); |
|
68 iFAT16BootSector.SetBootSignature(); |
|
69 unsigned char BootSignature = iFAT16BootSector.BootSignature(); |
|
70 iFAT16BootSector.SetVolumeId(); |
|
71 unsigned int VolumeId = iFAT16BootSector.VolumeId(); |
|
72 iFAT16BootSector.SetVolumeLab(aConfigurableFatAttributes->iDriveVolumeLabel); |
|
73 unsigned char* VolumeLab = iFAT16BootSector.VolumeLab(); |
|
74 iFAT16BootSector.SetFileSysType(); |
|
75 unsigned char* FileSysType = iFAT16BootSector.FileSysType(); |
|
76 //copying of boot sector values in to the array |
|
77 iData = new unsigned char[BytesPerSector]; |
|
78 unsigned int pos = 0; |
|
79 memcpy(&iData[pos],JmpBoot,3); |
|
80 pos += 3; |
|
81 memcpy(&iData[pos],OEMName,8); |
|
82 pos += 8; |
|
83 memcpy(&iData[pos],&BytesPerSector,2); |
|
84 pos += 2; |
|
85 memcpy(&iData[pos],&SectorsPerCluster,1); |
|
86 pos += 1; |
|
87 memcpy(&iData[pos],&ReservedSectors,2); |
|
88 pos += 2; |
|
89 memcpy(&iData[pos],&NumFats,1); |
|
90 pos += 1; |
|
91 memcpy(&iData[pos],&RootDirEntries,2); |
|
92 pos += 2; |
|
93 memcpy(&iData[pos],&LowSectors,2); |
|
94 pos += 2; |
|
95 memcpy(&iData[pos],&Media,1); |
|
96 pos += 1; |
|
97 memcpy(&iData[pos],&FatSectors,2); |
|
98 pos += 2; |
|
99 memcpy(&iData[pos],&SectorPerTrack,2); |
|
100 pos += 2; |
|
101 memcpy(&iData[pos],&NumberOfHeads,2); |
|
102 pos += 2; |
|
103 memcpy(&iData[pos],&HiddenSectors,4); |
|
104 pos += 4; |
|
105 memcpy(&iData[pos],&HighSectorsCount,4); |
|
106 pos += 4; |
|
107 memcpy(&iData[pos],&BootSectorDriveNumber,1); |
|
108 pos += 1; |
|
109 memcpy(&iData[pos],&ReservedByte,1); |
|
110 pos += 1; |
|
111 memcpy(&iData[pos],&BootSignature,1); |
|
112 pos += 1; |
|
113 memcpy(&iData[pos],&VolumeId,4); |
|
114 pos += 4; |
|
115 memcpy(&iData[pos],VolumeLab,11); |
|
116 pos += 11; |
|
117 memcpy(&iData[pos],FileSysType,8); |
|
118 pos += 8; |
|
119 while(pos < BytesPerSector) |
|
120 { |
|
121 iData[pos] = 0; |
|
122 pos++; |
|
123 } |
|
124 // Set sector [510] as 0xAA and [511] as 0x55 to mark the end of boot sector |
|
125 iData[KSizeOfFatBootSector-2] = 0x55; |
|
126 iData[KSizeOfFatBootSector-1] = 0xAA; |
|
127 // It is perfectly ok for the last two bytes of the boot sector to also |
|
128 // have the signature 0xAA55. |
|
129 iData[BytesPerSector-2] = 0x55; |
|
130 iData[BytesPerSector-1] = 0xAA; |
|
131 |
|
132 |
|
133 ComputeClusterSizeInBytes(); |
|
134 ComputeRootDirSectors(); |
|
135 ComputeBytesPerSector(); |
|
136 MessageHandler::ReportMessage (INFORMATION,BOOTSECTORCREATEMSG, "FAT16"); |
|
137 } |
|
138 |
|
139 /** |
|
140 Writes the boot sector of a FAT 16 volume |
|
141 @param aOutPutStream handle to file stream |
|
142 |
|
143 @internalComponent |
|
144 @released |
|
145 */ |
|
146 void CFat16FileSystem::WriteBootSector(ofstream& aOutPutStream) |
|
147 { |
|
148 MessageHandler::ReportMessage (INFORMATION,BOOTSECTORWRITEMSG,"FAT16"); |
|
149 aOutPutStream.write(reinterpret_cast<char*>(&iData[0]),iFAT16BootSector.BytesPerSector()); |
|
150 aOutPutStream.flush(); |
|
151 } |
|
152 /** |
|
153 Creates the FAT Table |
|
154 |
|
155 @internalComponent |
|
156 @released |
|
157 |
|
158 @param ofstream |
|
159 */ |
|
160 void CFat16FileSystem::CreateFatTable(ofstream& aOutPutStream) |
|
161 { |
|
162 int FATSizeInBytes = (iFAT16BootSector.FatSectors()) * (iFAT16BootSector.BytesPerSector()); |
|
163 // Each FAT16 entries occupies 2 bytes, hence divided by 2 |
|
164 unsigned int totalFatEntries = FATSizeInBytes / 2; |
|
165 unsigned short *FatTable = new unsigned short[totalFatEntries]; |
|
166 unsigned short int clusterCounter = 1; |
|
167 int previousCluster; |
|
168 FatTable[0] = KFat16FirstEntry; |
|
169 /**Say cluster 5 starts at 5 and occupies clusters 7 and 9. The FAT table should have the |
|
170 value 7 at cluster location 5, the value 9 at cluster 7 and 'eof' value at cluster 9. |
|
171 Below algorithm serves this algorithm |
|
172 */ |
|
173 Iterator itr = iClustersPerEntry->begin(); |
|
174 while(itr != iClustersPerEntry->end()) |
|
175 { |
|
176 previousCluster = itr->second; |
|
177 if(iClustersPerEntry->count(itr->first) > 1) |
|
178 { |
|
179 for(unsigned int i = 1; i < iClustersPerEntry->count(itr->first); i++) |
|
180 { |
|
181 FatTable[previousCluster] = (unsigned short)(++itr)->second; |
|
182 previousCluster = itr->second; |
|
183 ++clusterCounter; |
|
184 } |
|
185 } |
|
186 FatTable[previousCluster] = EOF16; |
|
187 itr++; |
|
188 ++clusterCounter; |
|
189 } |
|
190 // Each FAT16 entries occupies 2 bytes, hence multiply by 2 |
|
191 std::string aFatString(reinterpret_cast<char*>(FatTable),clusterCounter*2); |
|
192 delete[] FatTable; |
|
193 if(clusterCounter < totalFatEntries) |
|
194 { |
|
195 // Each FAT16 entries occupies 2 bytes, hence multiply by 2 |
|
196 aFatString.append((totalFatEntries - clusterCounter)*2, 0); |
|
197 } |
|
198 MessageHandler::ReportMessage (INFORMATION,FATTABLEWRITEMSG, |
|
199 "FAT16"); |
|
200 |
|
201 // Write FAT table multiple times depending upon the No of FATS set. |
|
202 unsigned int noOfFats = iFAT16BootSector.NumberOfFats(); |
|
203 for(unsigned int i=0; i<noOfFats; i++) |
|
204 { |
|
205 aOutPutStream.write(aFatString.c_str(),aFatString.length()); |
|
206 } |
|
207 |
|
208 aFatString.erase(); |
|
209 aOutPutStream.flush(); |
|
210 } |
|
211 |
|
212 /** |
|
213 set the cluster size in bytes,iClusterSize |
|
214 |
|
215 @internalComponent |
|
216 @released |
|
217 */ |
|
218 void CFat16FileSystem::ComputeClusterSizeInBytes() |
|
219 { |
|
220 iClusterSize = (iFAT16BootSector.SectorsPerCluster()) * (iFAT16BootSector.BytesPerSector()); |
|
221 } |
|
222 |
|
223 /** |
|
224 set the count of sectors occupied by the root directory,iRootDirSectors. |
|
225 |
|
226 @internalComponent |
|
227 @released |
|
228 */ |
|
229 void CFat16FileSystem::ComputeRootDirSectors() |
|
230 { |
|
231 iRootDirSectors = (iFAT16BootSector.RootDirEntries() * (KDefaultRootDirEntrySize) + |
|
232 (iFAT16BootSector.BytesPerSector() - 1)) / iFAT16BootSector.BytesPerSector(); |
|
233 } |
|
234 |
|
235 /** |
|
236 Initialize the Bytes per Sector variable value. |
|
237 |
|
238 @internalComponent |
|
239 @released |
|
240 */ |
|
241 void CFat16FileSystem::ComputeBytesPerSector() |
|
242 { |
|
243 iBytesPerSector = iFAT16BootSector.BytesPerSector(); |
|
244 } |
|
245 |
|
246 |
|
247 /** |
|
248 Compute the total number of clusters in Data segment of the FAT volume |
|
249 |
|
250 @internalComponent |
|
251 @released |
|
252 */ |
|
253 void CFat16FileSystem::ComputeTotalClusters(Long64 aPartitionSize) |
|
254 { |
|
255 unsigned long int iTotalDataSectors = iFAT16BootSector.TotalSectors(aPartitionSize) - |
|
256 ((iFAT16BootSector.NumberOfFats() * iFAT16BootSector.FatSectors()) + |
|
257 iRootDirSectors + iFAT16BootSector.ReservedSectors()); |
|
258 iTotalClusters = iTotalDataSectors / iFAT16BootSector.SectorsPerCluster(); |
|
259 if(iTotalClusters < KMinimumFat16Clusters) |
|
260 { |
|
261 throw ErrorHandler(BOOTSECTORERROR,"Low Partition Size",__FILE__,__LINE__); |
|
262 } |
|
263 if(iTotalClusters > KMaximumFat16Clusters) |
|
264 { |
|
265 throw ErrorHandler(BOOTSECTORERROR,"High Partition Size",__FILE__,__LINE__); |
|
266 } |
|
267 |
|
268 } |
|
269 |
|
270 /** |
|
271 This methods encapsulates the function call to write a complete FAT16 Image |
|
272 |
|
273 @internalComponent |
|
274 @released |
|
275 |
|
276 @param aPartitionSize partition size in bytes |
|
277 @param aNodeList Directory structure |
|
278 @param aOutPutStream output stream for writing file image |
|
279 @param aImageFileName image file name |
|
280 @param aLogFileName log file name |
|
281 @param aConfigurableFatAttributes ConfigurableFatAttributes |
|
282 */ |
|
283 |
|
284 void CFat16FileSystem::Execute(Long64 aPartitionSize,EntryList aNodeList,ofstream& aOutPutStream, |
|
285 ConfigurableFatAttributes* aConfigurableFatAttributes) |
|
286 { |
|
287 CDirRegion* dirRegionPtr = NULL; |
|
288 try |
|
289 { |
|
290 CreateBootSector(aPartitionSize,aConfigurableFatAttributes); |
|
291 ComputeTotalClusters(aPartitionSize); |
|
292 WriteBootSector(aOutPutStream); |
|
293 dirRegionPtr = new CDirRegion(aNodeList,this); |
|
294 dirRegionPtr->Execute(); |
|
295 iClustersPerEntry = dirRegionPtr->GetClustersPerEntryMap(); |
|
296 CreateFatTable(aOutPutStream); |
|
297 dirRegionPtr ->WriteClustersIntoFile(aOutPutStream); |
|
298 delete dirRegionPtr ; |
|
299 } |
|
300 catch(ErrorHandler &aError) |
|
301 { |
|
302 delete dirRegionPtr; |
|
303 //Re throw the same error message |
|
304 throw ErrorHandler(aError.iMessageIndex,(char*)aError.iSubMessage.c_str(),(char*)aError.iFileName.c_str(),aError.iLineNumber); |
|
305 } |
|
306 /** |
|
307 Irrespective of successful or unsuccessful data drive image generation ROFSBUILD |
|
308 may try to generate images for successive ".oby" file input. |
|
309 During this course unhandled exceptions may cause leaving some memory on heap |
|
310 unused. so the unhandled exceptions handling is used to free the memory allocated |
|
311 on heap. |
|
312 */ |
|
313 catch(...) |
|
314 { |
|
315 delete dirRegionPtr; |
|
316 throw ErrorHandler(UNKNOWNERROR, __FILE__, __LINE__); |
|
317 } |
|
318 } |