|
1 /* |
|
2 * Copyright (c) 2005-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 * @internalComponent |
|
16 * @released |
|
17 * |
|
18 */ |
|
19 |
|
20 #include <e32rom.h> |
|
21 #include "rom_image_reader.h" |
|
22 #include "r_rom.h" |
|
23 |
|
24 void InflateUnCompress(unsigned char* source, int sourcesize, unsigned char* dest, int destsize); |
|
25 RomImageFSEntry::RomImageFSEntry (const char* aName) : iName(aName), iSibling(0), iChildren(0) { |
|
26 } |
|
27 RomImageFSEntry::~RomImageFSEntry() { |
|
28 if(iChildren){ |
|
29 delete iChildren; |
|
30 iChildren = NULL ; |
|
31 } |
|
32 if(iSibling){ |
|
33 delete iSibling ; |
|
34 iSibling = NULL ; |
|
35 } |
|
36 } |
|
37 |
|
38 //Rom Image header |
|
39 RomImageHeader::RomImageHeader(char* aHdr, EImageType aImgType) |
|
40 { |
|
41 switch( aImgType) |
|
42 { |
|
43 case EROM_IMAGE: |
|
44 iLoaderHdr = (TRomLoaderHeader*)aHdr; |
|
45 iRomHdr = (TRomHeader*)(aHdr + sizeof(TRomLoaderHeader)); |
|
46 iExtRomHdr = 0; |
|
47 break; |
|
48 |
|
49 case EROMX_IMAGE: |
|
50 iExtRomHdr = (TExtensionRomHeader*)(aHdr); |
|
51 iRomHdr = 0; |
|
52 iLoaderHdr = 0; |
|
53 break; |
|
54 |
|
55 case EBAREROM_IMAGE: |
|
56 iLoaderHdr = 0; |
|
57 iRomHdr = (TRomHeader*)aHdr; |
|
58 iExtRomHdr = 0; |
|
59 break; |
|
60 default: |
|
61 iExtRomHdr = 0; |
|
62 iRomHdr = 0; |
|
63 iLoaderHdr = 0; |
|
64 break ; |
|
65 } |
|
66 } |
|
67 |
|
68 |
|
69 void RomImageHeader::DumpRomHdr() |
|
70 { |
|
71 if(iLoaderHdr) |
|
72 *out << "ROM Image " << endl << endl; |
|
73 else |
|
74 *out << "Bare ROM Image" << endl << endl; |
|
75 TUint aPos = 0; |
|
76 bool aContinue = true; |
|
77 |
|
78 *out << "Image Signature ................."; |
|
79 |
|
80 if(iLoaderHdr){ |
|
81 TText *aRomName = reinterpret_cast<TText *>(iLoaderHdr) ; |
|
82 while (aPos < KRomNameSize) { |
|
83 *out << (char)aRomName[aPos++]; |
|
84 } |
|
85 } |
|
86 |
|
87 *out << endl << endl; |
|
88 |
|
89 DumpInHex("Timestamp", (iRomHdr->iTime >> 32)) ; |
|
90 DumpInHex(" ", (iRomHdr->iTime &0xffffffff), aContinue) << endl; |
|
91 |
|
92 DumpInHex("RomBase", iRomHdr->iRomBase) << endl; |
|
93 |
|
94 DumpInHex("RomSize", iRomHdr->iRomSize) << endl; |
|
95 DumpInHex("KernelDataAddress", iRomHdr->iKernDataAddress) << endl; |
|
96 DumpInHex("KernelLimit", iRomHdr->iKernelLimit) << endl; |
|
97 DumpInHex("PrimaryFile", iRomHdr->iPrimaryFile) << endl; |
|
98 DumpInHex("SecondaryFile", iRomHdr->iSecondaryFile) << endl; |
|
99 DumpInHex("CheckSum", iRomHdr->iCheckSum) << endl; |
|
100 DumpInHex("Hardware", iRomHdr->iHardware) << endl; |
|
101 |
|
102 DumpInHex("Language", (TUint)(iRomHdr->iLanguage >> 32)); |
|
103 DumpInHex(" ", ((TUint)(iRomHdr->iLanguage & 0xffffffff)), aContinue) <<endl; |
|
104 |
|
105 DumpInHex("KernelConfigFlags", iRomHdr->iKernelConfigFlags) << endl; |
|
106 DumpInHex("RomExceptionSearchTable", iRomHdr->iRomExceptionSearchTable) << endl; |
|
107 DumpInHex("RomHeaderSize", iRomHdr->iRomHeaderSize) << endl; |
|
108 DumpInHex("RomSectionHeader", iRomHdr->iRomSectionHeader) << endl; |
|
109 DumpInHex("TotalSvDataSize", iRomHdr->iTotalSvDataSize) << endl; |
|
110 DumpInHex("VariantFile", iRomHdr->iVariantFile) << endl; |
|
111 DumpInHex("ExtensionFile", iRomHdr->iExtensionFile) << endl; |
|
112 DumpInHex("RelocInfo", iRomHdr->iRelocInfo) << endl; |
|
113 DumpInHex("OldTraceMask", iRomHdr->iOldTraceMask) << endl; |
|
114 DumpInHex("UserDataAddress", iRomHdr->iUserDataAddress) << endl; |
|
115 DumpInHex("TotalUserDataSize", iRomHdr->iTotalUserDataSize) << endl; |
|
116 DumpInHex("DebugPort", iRomHdr->iDebugPort) << endl; |
|
117 |
|
118 DumpInHex("Version", iRomHdr->iVersion.iMajor, false, 2); |
|
119 DumpInHex(".", iRomHdr->iVersion.iMinor, aContinue, 2); |
|
120 DumpInHex("(" ,iRomHdr->iVersion.iBuild, aContinue, 2); |
|
121 *out << ")" << endl; |
|
122 |
|
123 DumpInHex("CompressionType", iRomHdr->iCompressionType) << endl; |
|
124 DumpInHex("CompressedSize", iRomHdr->iCompressedSize) << endl; |
|
125 DumpInHex("UncompressedSize", iRomHdr->iUncompressedSize) << endl; |
|
126 DumpInHex("HcrFileAddress", iRomHdr->iHcrFileAddress) << endl; |
|
127 |
|
128 DumpInHex("DisabledCapabilities", iRomHdr->iDisabledCapabilities[0]); |
|
129 DumpInHex(" ", iRomHdr->iDisabledCapabilities[1], aContinue) << endl; |
|
130 |
|
131 DumpInHex("TraceMask", iRomHdr->iTraceMask[0]); |
|
132 aPos = 1; |
|
133 while( aPos < (TUint)KNumTraceMaskWords) |
|
134 { |
|
135 if(iRomHdr->iTraceMask[aPos]) |
|
136 { |
|
137 DumpInHex(" ", iRomHdr->iTraceMask[aPos++], aContinue); |
|
138 } |
|
139 else |
|
140 { |
|
141 DumpInHex(" ", iRomHdr->iTraceMask[aPos++], aContinue, 1); |
|
142 } |
|
143 |
|
144 } |
|
145 |
|
146 *out << endl << endl; |
|
147 |
|
148 } |
|
149 void RomImageHeader::DumpRomXHdr() |
|
150 { |
|
151 *out << "Extension ROM Image" << endl << endl; |
|
152 bool aContinue = true; |
|
153 |
|
154 DumpInHex("Timestamp", (iExtRomHdr->iTime >> 32)) ; |
|
155 DumpInHex(" ", (iExtRomHdr->iTime &0xffffffff), aContinue) << endl; |
|
156 |
|
157 DumpInHex("RomBase", iExtRomHdr->iRomBase) << endl; |
|
158 |
|
159 DumpInHex("RomSize", iExtRomHdr->iRomSize) << endl; |
|
160 DumpInHex("CheckSum", iExtRomHdr->iCheckSum) << endl; |
|
161 |
|
162 DumpInHex("Version", iExtRomHdr->iVersion.iMajor, false, 2); |
|
163 DumpInHex(".", iExtRomHdr->iVersion.iMinor, aContinue, 2); |
|
164 DumpInHex("(" ,iExtRomHdr->iVersion.iBuild, aContinue, 2); |
|
165 *out << ")" << endl; |
|
166 |
|
167 DumpInHex("CompressionType", iExtRomHdr->iCompressionType) << endl; |
|
168 DumpInHex("CompressedSize", iExtRomHdr->iCompressedSize) << endl; |
|
169 DumpInHex("UncompressedSize", iExtRomHdr->iUncompressedSize) << endl; |
|
170 |
|
171 *out << endl << endl; |
|
172 |
|
173 } |
|
174 //Rom Image reader |
|
175 RomImageReader::RomImageReader(const char* aFile, EImageType aImgType) : |
|
176 ImageReader(aFile), iImageHeader(0), |
|
177 iRomSize(0),iHeaderBuffer(0), |
|
178 iRomLayoutData(0),iImgType(aImgType) |
|
179 { |
|
180 iRomImageRootDirEntry = new RomImageDirEntry(""); |
|
181 } |
|
182 |
|
183 RomImageReader::~RomImageReader() |
|
184 { |
|
185 if(iFile.is_open()) |
|
186 iFile.close(); |
|
187 if(iHeaderBuffer) |
|
188 delete []iHeaderBuffer; |
|
189 if(iRomLayoutData) |
|
190 delete []iRomLayoutData; |
|
191 delete iRomImageRootDirEntry; |
|
192 |
|
193 |
|
194 } |
|
195 |
|
196 void RomImageReader::ReadImage() |
|
197 { |
|
198 if(iFile.is_open()) return ; |
|
199 iFile.open(iImgFileName.c_str(), ios::binary | ios::in); |
|
200 if( !iFile.is_open() ) { |
|
201 throw ImageReaderException(iImgFileName.c_str(), "Cannot open file "); |
|
202 } |
|
203 |
|
204 TUint headerSize = GetHdrSize() ; |
|
205 if(headerSize > 0){ |
|
206 iHeaderBuffer = new char[headerSize]; |
|
207 iFile.read(iHeaderBuffer,headerSize); |
|
208 } |
|
209 } |
|
210 |
|
211 void RomImageReader::Validate() |
|
212 { |
|
213 } |
|
214 |
|
215 TUint32 RomImageReader::GetImageCompressionType() |
|
216 { |
|
217 if(iImageHeader->iRomHdr )// iImageType == EROM_IMAGE |
|
218 return iImageHeader->iRomHdr->iCompressionType; |
|
219 else |
|
220 return iImageHeader->iExtRomHdr->iCompressionType; |
|
221 } |
|
222 |
|
223 |
|
224 TLinAddr RomImageReader::GetRomBase() |
|
225 { |
|
226 if(iImageHeader->iRomHdr )// iImageType == EROM_IMAGE |
|
227 return iImageHeader->iRomHdr->iRomBase ; |
|
228 else |
|
229 return iImageHeader->iExtRomHdr->iRomBase; |
|
230 } |
|
231 |
|
232 TLinAddr RomImageReader::GetRootDirList() |
|
233 { |
|
234 if(iImageHeader->iRomHdr )// iImageType == EROM_IMAGE |
|
235 return iImageHeader->iRomHdr->iRomRootDirectoryList; |
|
236 else |
|
237 return iImageHeader->iExtRomHdr->iRomRootDirectoryList; |
|
238 } |
|
239 |
|
240 TUint RomImageReader::GetHdrSize() |
|
241 { |
|
242 TUint headerSize = 0; |
|
243 if(EROM_IMAGE == iImgType){ |
|
244 headerSize = sizeof(TRomLoaderHeader) + sizeof(TRomHeader); |
|
245 }else if(EROMX_IMAGE == iImgType){ |
|
246 headerSize = sizeof(TExtensionRomHeader); |
|
247 }else if(EBAREROM_IMAGE == iImgType){ |
|
248 headerSize = sizeof(TRomHeader); |
|
249 } |
|
250 return headerSize; |
|
251 } |
|
252 |
|
253 |
|
254 static const TInt KIOBytes = 0x100000; |
|
255 // reading a huge buffer at a time is very slow, reading 1MB bytes at a time is much faster |
|
256 void RomImageReader::ReadData(char* aBuffer, TUint aLength) |
|
257 { |
|
258 TUint readBytes = 0 ; |
|
259 while(readBytes < aLength){ |
|
260 TUint toRead = KIOBytes; |
|
261 if(readBytes + toRead > aLength) |
|
262 toRead = aLength - readBytes ; |
|
263 iFile.read(&aBuffer[readBytes],toRead); |
|
264 readBytes += toRead ; |
|
265 } |
|
266 } |
|
267 void RomImageReader::ProcessImage() |
|
268 { |
|
269 if(iRomLayoutData) return ; |
|
270 iImageHeader = new RomImageHeader(iHeaderBuffer, iImgType); |
|
271 |
|
272 iFile.seekg(0, ios::end); |
|
273 // fileSize |
|
274 TUint fileSize = iFile.tellg(); |
|
275 |
|
276 //let's skip the RomLoaderHeader |
|
277 TUint romDataBegin = (EROM_IMAGE == iImgType) ? sizeof(TRomLoaderHeader) : 0 ; |
|
278 iFile.seekg(romDataBegin,ios::beg); |
|
279 |
|
280 if(EROMX_IMAGE == iImgType){// EROMX_IMAGE, just set the iUnpagedRomBuffer |
|
281 if(GetImageCompressionType() == KUidCompressionDeflate){ |
|
282 TUint32 readLen = fileSize - sizeof(TExtensionRomHeader) ; |
|
283 iRomSize = iImageHeader->iExtRomHdr->iUncompressedSize ; |
|
284 iRomLayoutData = new char[iRomSize]; |
|
285 char* temp = new char[readLen]; |
|
286 // header is not compressed. |
|
287 iFile.read(iRomLayoutData,sizeof(TExtensionRomHeader)); |
|
288 ReadData(temp ,readLen); |
|
289 TUint8* uncompressDest = reinterpret_cast<TUint8*>(iRomLayoutData + sizeof(TExtensionRomHeader)); |
|
290 InflateUnCompress(reinterpret_cast<TUint8*>(temp),readLen,uncompressDest,iRomSize - sizeof(TExtensionRomHeader)); |
|
291 delete []temp ; |
|
292 |
|
293 }else{ |
|
294 iRomSize = fileSize ; |
|
295 iRomLayoutData = new char[iRomSize]; |
|
296 ReadData(iRomLayoutData,iRomSize); |
|
297 } |
|
298 } // end EROMX_IMAGE |
|
299 else { |
|
300 //EROM_IMAGE or EBAREROM_IMAGE |
|
301 const TInt KPageSize = 0x1000; |
|
302 TRomHeader *hdr = iImageHeader->iRomHdr; |
|
303 iRomSize = hdr->iUncompressedSize ; |
|
304 iRomLayoutData = new char[iRomSize]; |
|
305 char* curDataPointer = iRomLayoutData ; |
|
306 TUint totalReadBytes = 0; |
|
307 bool hasPageableSec = (hdr->iPageableRomStart > 0 && hdr->iPageableRomSize > 0) ; |
|
308 |
|
309 // read data before unpaged |
|
310 ReadData(curDataPointer,hdr->iCompressedUnpagedStart); |
|
311 curDataPointer += hdr->iCompressedUnpagedStart ; |
|
312 totalReadBytes += hdr->iCompressedUnpagedStart; |
|
313 |
|
314 // read the unpaged part, if compressed , then decompress |
|
315 if(GetImageCompressionType() == KUidCompressionDeflate){ |
|
316 char* temp = new char[hdr->iUnpagedCompressedSize]; |
|
317 ReadData(temp,hdr->iUnpagedCompressedSize); |
|
318 totalReadBytes += hdr->iUnpagedCompressedSize; |
|
319 InflateUnCompress(reinterpret_cast<TUint8*>(temp),hdr->iUnpagedCompressedSize,reinterpret_cast<TUint8*>(curDataPointer) ,hdr->iUnpagedUncompressedSize); |
|
320 delete []temp ; |
|
321 }else{ |
|
322 TUint unpagedSeclen ; |
|
323 if(hasPageableSec) { // there is paged section |
|
324 unpagedSeclen = hdr->iPageableRomStart - hdr->iCompressedUnpagedStart; |
|
325 }else{ |
|
326 unpagedSeclen = iRomSize - hdr->iCompressedUnpagedStart; |
|
327 } |
|
328 ReadData(curDataPointer,unpagedSeclen); |
|
329 totalReadBytes += unpagedSeclen ; |
|
330 } |
|
331 curDataPointer = iRomLayoutData + totalReadBytes; |
|
332 //if there is a paged section , read and extract it |
|
333 |
|
334 // read the paged section, |
|
335 if(hasPageableSec){ |
|
336 if((TUint)(hdr->iPageableRomStart + hdr->iPageableRomSize) > iRomSize){ |
|
337 throw ImageReaderException("Incorrect values of ROM header fields.", ""); |
|
338 } |
|
339 if(0 == hdr->iRomPageIndex){ // |
|
340 // no compression for paged section ,just read it |
|
341 iFile.read(curDataPointer,iRomSize - totalReadBytes); |
|
342 } |
|
343 else{ |
|
344 //aligment calculation |
|
345 TUint pagedSecOffset = (totalReadBytes + KPageSize - 1) & (~(KPageSize - 1)); |
|
346 if(pagedSecOffset > totalReadBytes){ |
|
347 // there are gap bytes between unpaged and paged sections |
|
348 iFile.read(curDataPointer,pagedSecOffset - totalReadBytes); |
|
349 curDataPointer = iRomLayoutData + pagedSecOffset; |
|
350 } |
|
351 TUint pagedIndexCount = ( hdr->iUncompressedSize + KPageSize - 1) / KPageSize; |
|
352 // how many bytes ? |
|
353 // the page index table include the unpaged part ; |
|
354 TUint firstPagedIndexTblItem = hdr->iPageableRomStart / KPageSize; |
|
355 |
|
356 TUint tempBufLen = KPageSize << 8; |
|
357 char* readBuffer = new char[tempBufLen]; |
|
358 |
|
359 TUint8* src,*srcNext = NULL; |
|
360 SRomPageInfo* pageInfo = reinterpret_cast<SRomPageInfo*>(&iRomLayoutData[hdr->iRomPageIndex]); |
|
361 CBytePair bp(EFalse); |
|
362 for(TUint i = firstPagedIndexTblItem ; i < pagedIndexCount ; i+= 256){ |
|
363 TUint endIndex = i + 255 ; |
|
364 if(endIndex >= pagedIndexCount) |
|
365 endIndex = pagedIndexCount - 1; |
|
366 TUint readLen = pageInfo[endIndex].iDataStart + pageInfo[endIndex].iDataSize - pageInfo[i].iDataStart ; |
|
367 iFile.read(readBuffer,readLen); |
|
368 src = reinterpret_cast<TUint8*>(readBuffer); |
|
369 for(TUint j = i ; j <= endIndex ; j++){ |
|
370 switch(pageInfo[j].iCompressionType) |
|
371 { |
|
372 case SRomPageInfo::EBytePair: |
|
373 { |
|
374 TInt unpacked = bp.Decompress(reinterpret_cast<TUint8*>(curDataPointer), KPageSize, src, pageInfo[j].iDataSize, srcNext); |
|
375 if (unpacked < 0) { |
|
376 delete []readBuffer; |
|
377 throw ImageReaderException("Corrupted BytePair compressed ROM image", ""); |
|
378 } |
|
379 curDataPointer += unpacked; |
|
380 break ; |
|
381 } |
|
382 case SRomPageInfo::ENoCompression: |
|
383 memcpy(curDataPointer,src,pageInfo[j].iDataSize); |
|
384 curDataPointer += pageInfo[j].iDataSize ; |
|
385 break ; |
|
386 default: |
|
387 delete []readBuffer; |
|
388 throw ImageReaderException("Undefined compression type", ""); |
|
389 break ; |
|
390 |
|
391 } |
|
392 src += pageInfo[j].iDataSize; |
|
393 } // end for(TUint j = i ; j <= endIndex ; j++) |
|
394 } // end for(TUint i = firstPagedIndexTblItem ; i < pagedIndexCount ; i+= 256) |
|
395 delete []readBuffer ; |
|
396 }// else |
|
397 |
|
398 } // if(hasPageableSec) |
|
399 |
|
400 } |
|
401 TUint32 offset = GetRootDirList() - GetRomBase(); |
|
402 TRomRootDirectoryList* rootDirList = reinterpret_cast<TRomRootDirectoryList*>(iRomLayoutData + offset ); |
|
403 TInt dirCount = rootDirList->iNumRootDirs ; |
|
404 string tempName ; |
|
405 for(TInt i = 0 ; i < dirCount ; i++) { |
|
406 offset = rootDirList->iRootDir[i].iAddressLin - GetRomBase(); |
|
407 TRomDir* romDir = reinterpret_cast<TRomDir*>(iRomLayoutData + offset); |
|
408 Name(tempName,reinterpret_cast<const wchar_t *>(romDir->iEntry.iName),romDir->iEntry.iNameLength); |
|
409 BuildDir(romDir, iRomImageRootDirEntry); |
|
410 } |
|
411 |
|
412 } |
|
413 |
|
414 |
|
415 void RomImageReader::BuildDir(TRomDir* aDir, RomImageFSEntry* aPaFSEntry) |
|
416 { |
|
417 |
|
418 TInt processBytes = 0 ; |
|
419 TInt totalDirBytes = aDir->iSize - sizeof(aDir->iSize); |
|
420 TRomEntry* entry = &aDir->iEntry; |
|
421 RomImageFSEntry *fsEntry ; |
|
422 string name ; |
|
423 const char* pritableName = ""; |
|
424 |
|
425 while(processBytes < totalDirBytes){ |
|
426 Name(name,reinterpret_cast<const wchar_t *>(entry->iName),entry->iNameLength); |
|
427 pritableName = name.c_str(); |
|
428 if(entry->iAtt & 0x10) { // is a directory |
|
429 fsEntry = new RomImageDirEntry(pritableName); |
|
430 AddChild(aPaFSEntry,fsEntry,NULL); |
|
431 TUint offset = entry->iAddressLin - GetRomBase(); |
|
432 TRomDir* subFolder = reinterpret_cast<TRomDir*>(iRomLayoutData + offset); |
|
433 BuildDir(subFolder,fsEntry); |
|
434 } |
|
435 else{ |
|
436 fsEntry = new RomImageFileEntry(pritableName); |
|
437 AddChild(aPaFSEntry,fsEntry,entry); |
|
438 } |
|
439 // increase the processedBytes |
|
440 processBytes += (entry->iNameLength << 1) + reinterpret_cast<TInt>(entry->iName) - reinterpret_cast<TInt>(entry); |
|
441 |
|
442 //align to next 4 bytes |
|
443 processBytes = (processBytes + 3) & ( ~3 ); |
|
444 // get next entry |
|
445 entry = reinterpret_cast<TRomEntry*>( reinterpret_cast<char*>(&aDir->iEntry) + processBytes); |
|
446 } |
|
447 |
|
448 } |
|
449 |
|
450 void RomImageReader::AddChild(RomImageFSEntry *aParent, RomImageFSEntry *aChild, TRomEntry* aRomEntry) |
|
451 { |
|
452 if(!aParent->iChildren) |
|
453 aParent->iChildren = aChild; |
|
454 else { |
|
455 RomImageFSEntry *aLast = aParent->iChildren; |
|
456 |
|
457 while(aLast->iSibling) |
|
458 aLast = aLast->iSibling; |
|
459 aLast->iSibling = aChild; |
|
460 } |
|
461 |
|
462 if(!aChild->IsDirectory()) { |
|
463 RomImageFileEntry* file = static_cast<RomImageFileEntry*>(aChild); |
|
464 file->iTRomEntryPtr = aRomEntry; |
|
465 |
|
466 if(aRomEntry->iAddressLin > GetRomBase()) { |
|
467 TUint32 offset = aRomEntry->iAddressLin - GetRomBase(); |
|
468 |
|
469 TRomImageHeader* imgHdr = reinterpret_cast<TRomImageHeader*>(iRomLayoutData + offset); |
|
470 |
|
471 file->ImagePtr.iRomFileEntry = imgHdr; |
|
472 |
|
473 TUint8 aUid1[4]; |
|
474 memcpy(aUid1, &file->ImagePtr.iRomFileEntry->iUid1, 4); |
|
475 |
|
476 if( ReaderUtil::IsExecutable(aUid1) ) { |
|
477 file->iExecutable = true; |
|
478 } |
|
479 else { |
|
480 file->iExecutable = false; |
|
481 file->ImagePtr.iDataFileAddr = aRomEntry->iAddressLin; |
|
482 } |
|
483 } |
|
484 else { |
|
485 file->ImagePtr.iRomFileEntry = NULL; |
|
486 } |
|
487 } |
|
488 |
|
489 if(aParent != iRomImageRootDirEntry) { |
|
490 aChild->iPath = aParent->iPath; |
|
491 aChild->iPath += DIR_SEPARATOR; |
|
492 aChild->iPath += aParent->iName.c_str(); |
|
493 } |
|
494 } |
|
495 |
|
496 void RomImageReader::Name(string& aName, const wchar_t* aUnicodeName, TUint aLen) |
|
497 { |
|
498 char* temp = (char*)_alloca((aLen << 1) + 1) ; |
|
499 size_t n = wcsrtombs(temp,&aUnicodeName,aLen,NULL); |
|
500 if(n == (size_t)-1){ // the unicode string can not be coverted. |
|
501 aName = "???"; |
|
502 } |
|
503 temp[n] = 0; |
|
504 if(n > 0) |
|
505 aName.assign(temp,n) ; |
|
506 else |
|
507 aName = ""; |
|
508 |
|
509 } |
|
510 |
|
511 void RomImageReader::DumpTree() |
|
512 { |
|
513 RomImageFSEntry* aFsEntry = iRomImageRootDirEntry; |
|
514 if( aFsEntry->iChildren ) |
|
515 DumpSubTree(aFsEntry->iChildren); |
|
516 } |
|
517 |
|
518 void RomImageReader::DumpDirStructure() |
|
519 { |
|
520 *out << "Directory Listing" << endl; |
|
521 *out << "=================" << endl; |
|
522 int aPadding = 0; |
|
523 if( iRomImageRootDirEntry ){ |
|
524 DumpDirStructure(iRomImageRootDirEntry, aPadding); |
|
525 } |
|
526 *out << endl << endl; |
|
527 } |
|
528 |
|
529 void RomImageReader::DumpDirStructure(RomImageFSEntry* aEntry, int &aPadding) |
|
530 { |
|
531 if(!aEntry) |
|
532 return; |
|
533 |
|
534 int aPadLen = 2 * aPadding;//scaling for legibility |
|
535 for (int i = 0; i < aPadLen; i++) |
|
536 *out << " "; |
|
537 |
|
538 *out << aEntry->Name() << endl; |
|
539 |
|
540 if( aEntry->iChildren){ |
|
541 aPadding++; |
|
542 DumpDirStructure(aEntry->iChildren, aPadding); |
|
543 aPadding--; |
|
544 } |
|
545 DumpDirStructure(aEntry->iSibling, aPadding); |
|
546 } |
|
547 |
|
548 void RomImageReader::DumpSubTree(RomImageFSEntry* aFsEntry) |
|
549 { |
|
550 if(!aFsEntry) |
|
551 return; |
|
552 |
|
553 if( aFsEntry->iChildren ){ |
|
554 DumpSubTree(aFsEntry->iChildren); |
|
555 } |
|
556 |
|
557 if( aFsEntry->iSibling ) |
|
558 DumpSubTree(aFsEntry->iSibling); |
|
559 |
|
560 RomImageFSEntry *aEntry = aFsEntry; |
|
561 |
|
562 if(!aEntry->IsDirectory()) { |
|
563 *out << "********************************************************************" << endl; |
|
564 *out << "File........................" << aEntry->iPath.c_str() << DIR_SEPARATOR << aEntry->Name() << endl; |
|
565 |
|
566 if( ((RomImageFileEntry*)aEntry)->iExecutable ) { |
|
567 DumpImage((RomImageFileEntry*)aEntry); |
|
568 } |
|
569 else{ |
|
570 *out << "Linear Addr................." << ((RomImageFileEntry*)aEntry)->ImagePtr.iDataFileAddr << endl; |
|
571 } |
|
572 } |
|
573 } |
|
574 |
|
575 void RomImageReader::DumpImage(RomImageFileEntry * aEntry) |
|
576 { |
|
577 bool aContinue = true; |
|
578 |
|
579 DumpInHex("Load Address", aEntry->iTRomEntryPtr->iAddressLin) << endl; |
|
580 DumpInHex("Size", aEntry->iTRomEntryPtr->iSize) << endl; |
|
581 |
|
582 TRomImageHeader *aRomImgEntry = aEntry->ImagePtr.iRomFileEntry; |
|
583 |
|
584 if( !aRomImgEntry ) |
|
585 return; |
|
586 //UIDs |
|
587 DumpInHex("Uids", aRomImgEntry->iUid1); |
|
588 DumpInHex(" ", aRomImgEntry->iUid2, aContinue); |
|
589 DumpInHex(" ", aRomImgEntry->iUid3, aContinue); |
|
590 DumpInHex(" ", aRomImgEntry->iUidChecksum, aContinue) << endl; |
|
591 |
|
592 DumpInHex("Entry point", aRomImgEntry->iEntryPoint) << endl; |
|
593 DumpInHex("Code start addr", aRomImgEntry->iCodeAddress) << endl; |
|
594 DumpInHex("Data start addr", aRomImgEntry->iDataAddress) << endl; |
|
595 DumpInHex("DataBssLinearBase", aRomImgEntry->iDataBssLinearBase) << endl; |
|
596 DumpInHex("Text size", aRomImgEntry->iTextSize) << endl; |
|
597 DumpInHex("Code size", aRomImgEntry->iCodeSize) << endl; |
|
598 DumpInHex("Data size", aRomImgEntry->iDataSize) << endl; |
|
599 DumpInHex("Bss size", (aRomImgEntry->iBssSize)) << endl; |
|
600 DumpInHex("Total data size", aRomImgEntry->iTotalDataSize) << endl; |
|
601 DumpInHex("Heap min", aRomImgEntry->iHeapSizeMin) << endl; |
|
602 DumpInHex("Heap max", aRomImgEntry->iHeapSizeMax) << endl; |
|
603 DumpInHex("Stack size", aRomImgEntry->iStackSize) << endl; |
|
604 |
|
605 TDllRefTable *aRefTbl = NULL; |
|
606 |
|
607 if( aRomImgEntry->iDllRefTable ) { |
|
608 TUint32 aOff = (TUint32)aRomImgEntry->iDllRefTable - iImageHeader->iRomHdr->iRomBase; |
|
609 aRefTbl = (TDllRefTable*) ((char*)iImageHeader->iRomHdr + aOff); |
|
610 TUint32 aVirtualAddr = (TUint32)aRefTbl->iEntry[0]; |
|
611 DumpInHex("Dll ref table", aVirtualAddr) << endl; |
|
612 } |
|
613 |
|
614 DumpInHex("Export directory", aRomImgEntry->iExportDir) << endl; |
|
615 DumpInHex("Export dir count", aRomImgEntry->iExportDirCount) << endl; |
|
616 DumpInHex("Hardware variant", aRomImgEntry->iHardwareVariant) << endl; |
|
617 DumpInHex("Flags", aRomImgEntry->iFlags) << endl; |
|
618 DumpInHex("Secure ID", aRomImgEntry->iS.iSecureId) << endl; |
|
619 DumpInHex("Vendor ID", aRomImgEntry->iS.iVendorId) << endl; |
|
620 |
|
621 DumpInHex("Capability", aRomImgEntry->iS.iCaps[1]); |
|
622 DumpInHex(" ", aRomImgEntry->iS.iCaps[0], aContinue) << endl; |
|
623 |
|
624 *out << "Tools Version..............." << dec << (TUint)aRomImgEntry->iToolsVersion.iMajor; |
|
625 *out << "." ; |
|
626 out->width(2) ; |
|
627 out->fill('0'); |
|
628 *out << dec << (TUint)aRomImgEntry->iToolsVersion.iMinor ; |
|
629 *out << "(" << dec << aRomImgEntry->iToolsVersion.iBuild << ")"; |
|
630 *out << endl; |
|
631 |
|
632 *out << "Module Version.............." << dec << (aRomImgEntry->iModuleVersion >> 16) << endl; |
|
633 DumpInHex("Exception Descriptor", aRomImgEntry->iExceptionDescriptor) << endl; |
|
634 *out << "Priority...................." << dec << aRomImgEntry->iPriority << endl; |
|
635 |
|
636 if( aRefTbl ) |
|
637 DumpInHex("Dll ref table size", aRefTbl->iNumberOfEntries*8) << endl; |
|
638 else |
|
639 DumpInHex("Dll ref table size", 0) << endl; |
|
640 |
|
641 if( iDisplayOptions & DUMP_E32_IMG_FLAG){ |
|
642 if(stricmp(iE32ImgFileName.c_str(), aEntry->Name()) == 0){ |
|
643 TUint aSectionOffset = aRomImgEntry->iCodeAddress - iImageHeader->iRomHdr->iRomBase; |
|
644 TUint* aCodeSection = (TUint*)((char*)iImageHeader->iRomHdr + aSectionOffset); |
|
645 *out << "\nCode (Size=0x" << hex << aRomImgEntry->iCodeSize << ")" << endl; |
|
646 DumpData(aCodeSection, aRomImgEntry->iCodeSize); |
|
647 |
|
648 aSectionOffset = aRomImgEntry->iDataAddress - iImageHeader->iRomHdr->iRomBase; |
|
649 TUint* aDataSection = (TUint*)((char*)iImageHeader->iRomHdr + aSectionOffset); |
|
650 if( aRomImgEntry->iDataSize){ |
|
651 *out << "\nData (Size=0x" << hex << aRomImgEntry->iDataSize << ")" << endl; |
|
652 DumpData(aDataSection, aRomImgEntry->iDataSize); |
|
653 } |
|
654 } |
|
655 } |
|
656 |
|
657 *out << endl << endl; |
|
658 } |
|
659 |
|
660 void RomImageReader::DumpAttribs(RomImageFSEntry* aFsEntry) |
|
661 { |
|
662 |
|
663 // a larger rom image cause stack overflow under visual studio if we use recursion algorithm here. |
|
664 // can gcc compiler guarantee this overflow will never be happen ? |
|
665 if( aFsEntry->iChildren ) |
|
666 DumpAttribs(aFsEntry->iChildren); |
|
667 |
|
668 if(aFsEntry->iSibling) |
|
669 DumpAttribs(aFsEntry->iSibling); |
|
670 if(aFsEntry->IsDirectory()) return ; |
|
671 RomImageFileEntry* file = static_cast<RomImageFileEntry*>(aFsEntry); |
|
672 if(!file->iExecutable) return ; |
|
673 TRomImageHeader* aRomImgEntry = file->ImagePtr.iRomFileEntry; |
|
674 |
|
675 if( !aRomImgEntry) return; |
|
676 |
|
677 const char* prefix ; |
|
678 if(aRomImgEntry->iFlags & KRomImageFlagPrimary){ |
|
679 prefix = "Primary"; |
|
680 } |
|
681 else if(aRomImgEntry->iFlags & KRomImageFlagVariant){ |
|
682 prefix = "Variant"; |
|
683 } |
|
684 else if(aRomImgEntry->iFlags & KRomImageFlagExtension){ |
|
685 prefix = "Extension"; |
|
686 } |
|
687 else if(aRomImgEntry->iFlags & KRomImageFlagDevice){ |
|
688 prefix = "Device"; |
|
689 } |
|
690 else |
|
691 return; |
|
692 |
|
693 out->width(10); |
|
694 out->fill(' '); |
|
695 *out << left << prefix; |
|
696 out->width(40); |
|
697 *out << right << file->Name() << "[" ; |
|
698 DumpInHex( "", aRomImgEntry->iHardwareVariant, true) << "] "; |
|
699 DumpInHex( " DataSize=", (aRomImgEntry->iBssSize + aRomImgEntry->iDataSize), true) << endl; |
|
700 |
|
701 } |
|
702 |
|
703 void RomImageReader::Dump() |
|
704 { |
|
705 if( !((iDisplayOptions & EXTRACT_FILES_FLAG) || |
|
706 (iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG) || |
|
707 (iDisplayOptions & EXTRACT_FILE_SET_FLAG)) ) { |
|
708 *out << "Image Name................." << iImgFileName.c_str() << endl; |
|
709 |
|
710 if( iImageHeader->iRomHdr ) |
|
711 iImageHeader->DumpRomHdr(); |
|
712 else |
|
713 iImageHeader->DumpRomXHdr(); |
|
714 |
|
715 DumpAttribs(iRomImageRootDirEntry); |
|
716 *out << endl ; |
|
717 |
|
718 if(iDisplayOptions & DUMP_VERBOSE_FLAG) { |
|
719 DumpDirStructure(); |
|
720 DumpTree(); |
|
721 } |
|
722 |
|
723 if(iDisplayOptions & DUMP_DIR_ENTRIES_FLAG) { |
|
724 DumpDirStructure(); |
|
725 } |
|
726 } |
|
727 } |
|
728 |
|
729 |
|
730 /** |
|
731 Function iterates through all the entries in the image |
|
732 by making a call to TraverseImage function. |
|
733 |
|
734 @internalComponent |
|
735 @released |
|
736 */ |
|
737 void RomImageReader::ExtractImageContents() |
|
738 { |
|
739 if( (iDisplayOptions & EXTRACT_FILE_SET_FLAG) ) |
|
740 { |
|
741 //TODO: |
|
742 ImageReader::ExtractFileSet(iRomLayoutData); |
|
743 } |
|
744 |
|
745 if( iDisplayOptions & EXTRACT_FILES_FLAG || iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG ) |
|
746 { |
|
747 if(iRomImageRootDirEntry) |
|
748 { |
|
749 // name of the log file. |
|
750 string logFile; |
|
751 // output stream for the log file. |
|
752 ofstream oFile; |
|
753 |
|
754 if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG){ |
|
755 if( ImageReader::iZdrivePath.compare("")){ |
|
756 // create a string to hold path information. |
|
757 string filePath(ImageReader::iZdrivePath); |
|
758 string delimiter("\\"); |
|
759 // replace backslash with double backslash. |
|
760 FindAndInsertString(filePath,delimiter,delimiter); |
|
761 logFile = filePath; |
|
762 // create specified directory. |
|
763 CreateSpecifiedDir(&filePath[0],"\\\\"); |
|
764 logFile.append("\\\\"); |
|
765 logFile.append(ImageReader::iLogFileName); |
|
766 } |
|
767 else |
|
768 { |
|
769 logFile = ImageReader::iLogFileName; |
|
770 } |
|
771 // open the specified file in append mode. |
|
772 oFile.open(logFile.c_str() ,ios::out|ios::app); |
|
773 |
|
774 if(!oFile.is_open()){ |
|
775 throw ImageReaderException((char*)ImageReader::iLogFileName.c_str(), "Failed to open the log file"); |
|
776 } |
|
777 } |
|
778 TraverseImage(iRomImageRootDirEntry,oFile); |
|
779 if(oFile.is_open()) oFile.close(); |
|
780 } |
|
781 } |
|
782 } |
|
783 |
|
784 |
|
785 /** |
|
786 Function to traverse entire image and check for an entity.If the entity found in the image is a file |
|
787 then it makes a call to CheckFileExtension to check for extension. |
|
788 |
|
789 @internalComponent |
|
790 @released |
|
791 |
|
792 @param aEntity - pointer to the entry in rom image. |
|
793 @param aFile - output stream. |
|
794 */ |
|
795 void RomImageReader::TraverseImage(RomImageFSEntry* aEntity,ofstream& aFile) |
|
796 { |
|
797 if(!aEntity->IsDirectory()) { |
|
798 CheckFileExtension(aEntity,aFile); |
|
799 } |
|
800 |
|
801 if (aEntity->iChildren) { |
|
802 TraverseImage(aEntity->iChildren,aFile); |
|
803 } |
|
804 |
|
805 if (aEntity->iSibling) { |
|
806 TraverseImage(aEntity->iSibling,aFile); |
|
807 } |
|
808 } |
|
809 |
|
810 |
|
811 /** |
|
812 Function to get check extension of the given file.If the extension of the file is "sis" |
|
813 then call ExtractFile function to extract the file from the image. |
|
814 |
|
815 @internalComponent |
|
816 @released |
|
817 |
|
818 @param aEntity - pointer to the entry in rom image. |
|
819 @param aFile - output stream. |
|
820 */ |
|
821 void RomImageReader::CheckFileExtension(RomImageFSEntry* aEntity,ofstream& aFile) |
|
822 { |
|
823 RomImageFileEntry* romEntry = (RomImageFileEntry*)aEntity; |
|
824 // get the size of the entity. |
|
825 TUint32 size = romEntry->iTRomEntryPtr->iSize; |
|
826 // get the offset of the entity. |
|
827 TUint32 offset = romEntry->iTRomEntryPtr->iAddressLin - GetRomBase() ; |
|
828 |
|
829 const char* fileName = aEntity->iName.c_str(); |
|
830 |
|
831 // create a string to hold the path information. |
|
832 string romfilePath(romEntry->iPath); |
|
833 string forwardSlash("/"); |
|
834 string slash("\\"); |
|
835 //replace slash with double backward slash. |
|
836 FindAndReplaceString( romfilePath, forwardSlash, slash ); |
|
837 |
|
838 if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG && iDisplayOptions & EXTRACT_FILES_FLAG ) { |
|
839 // get the position. |
|
840 size_t pos = aEntity->iName.find_last_of("."); |
|
841 |
|
842 const char* extName = fileName + ( pos + 1 ); |
|
843 if ( !stricmp(extName ,"SIS") || !stricmp(extName ,"DAT") ) { |
|
844 // if the two strings are same then extract the corresponding file. |
|
845 ImageReader::ExtractFile(offset,size,fileName,&romfilePath[0],&ImageReader::iZdrivePath[0],iRomLayoutData); |
|
846 } |
|
847 else { |
|
848 LogRomEnrtyToFile(romfilePath.c_str(),fileName,aFile); |
|
849 } |
|
850 } |
|
851 else if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG ) { |
|
852 LogRomEnrtyToFile(romfilePath.c_str(),fileName,aFile); |
|
853 } |
|
854 else { |
|
855 if(romEntry->iExecutable) { |
|
856 size += sizeof(TRomImageHeader); |
|
857 } |
|
858 // extract the corresponding file. |
|
859 ImageReader::ExtractFile(offset,size,fileName,&romfilePath[0],&ImageReader::iZdrivePath[0],iRomLayoutData); |
|
860 } |
|
861 } |
|
862 |
|
863 |
|
864 /** |
|
865 Function to log the rom entry to a specified file. |
|
866 |
|
867 @internalComponent |
|
868 @released |
|
869 |
|
870 @param aPath - Complete path of an entity. |
|
871 @param aEntityName - Entity name. |
|
872 @param aFile - output stream. |
|
873 */ |
|
874 void RomImageReader::LogRomEnrtyToFile(const char* aPath,const char* aEntityName,ofstream& aFile) |
|
875 { |
|
876 if(aFile.is_open()) |
|
877 { |
|
878 aFile.seekp(0,ios::end); |
|
879 aFile<<aPath<<"\\"<<aEntityName<<"\n"; |
|
880 } |
|
881 } |
|
882 |
|
883 |
|
884 /** |
|
885 Function to read the directory structure details of te ROM image. |
|
886 |
|
887 @internalComponent |
|
888 @released |
|
889 |
|
890 @param aEntity - pointer to the entry in rom image. |
|
891 @param aFileMap - map of filename with its size and offset values. |
|
892 @param aImgSize - Image size |
|
893 */ |
|
894 void RomImageReader::ProcessDirectory(RomImageFSEntry *aEntity, FILEINFOMAP &aFileMap) |
|
895 { |
|
896 if(!aEntity->IsDirectory()) { |
|
897 |
|
898 RomImageFileEntry* romEntry = (RomImageFileEntry*)aEntity; |
|
899 |
|
900 PFILEINFO fileInfo = new FILEINFO; |
|
901 |
|
902 // get the size of the entity. |
|
903 fileInfo->iSize = romEntry->iTRomEntryPtr->iSize; |
|
904 // get the offset of the entity. |
|
905 fileInfo->iOffset = (romEntry->iTRomEntryPtr->iAddressLin - GetRomBase()); |
|
906 |
|
907 if(romEntry->iExecutable) { |
|
908 fileInfo->iSize += sizeof(TRomImageHeader); |
|
909 } |
|
910 |
|
911 if((fileInfo->iOffset + fileInfo->iSize) > iRomSize) { |
|
912 fileInfo->iOffset = 0; |
|
913 fileInfo->iSize = 0; |
|
914 } |
|
915 |
|
916 string fileName(romEntry->iPath); |
|
917 fileName.append(DIR_SEPARATOR); |
|
918 fileName.append(aEntity->iName); |
|
919 |
|
920 aFileMap[fileName] = fileInfo; |
|
921 } |
|
922 |
|
923 if (aEntity->iChildren) { |
|
924 ProcessDirectory(aEntity->iChildren, aFileMap); |
|
925 } |
|
926 |
|
927 if (aEntity->iSibling) { |
|
928 ProcessDirectory(aEntity->iSibling, aFileMap); |
|
929 } |
|
930 } |
|
931 |
|
932 /** |
|
933 Function to read the directory structure details of te ROM image. |
|
934 |
|
935 @internalComponent |
|
936 @released |
|
937 |
|
938 @param aFileMap - map of filename with its size and offset values. |
|
939 */ |
|
940 void RomImageReader::GetFileInfo(FILEINFOMAP &aFileMap) { |
|
941 ProcessDirectory(iRomImageRootDirEntry, aFileMap); |
|
942 } |
|
943 |
|
944 /** |
|
945 Function to get the ROM image size. |
|
946 |
|
947 @internalComponent |
|
948 @released |
|
949 */ |
|
950 TUint32 RomImageReader::GetImageSize() { |
|
951 return iRomSize; |
|
952 } |
|
953 |