imgtools/romtools/readimage/src/rom_image_reader.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     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