imgtools/romtools/readimage/src/rom_image_reader.cpp
author timothy.murphy@nokia.com
Fri, 30 Apr 2010 16:07:17 +0100
branchfix
changeset 511 7581d432643a
parent 0 044383f39525
child 590 360bd6b35136
permissions -rw-r--r--
fix: support new trace compiler features for preventing clashes. Automatically turn on OST_TRACE_COMPILER_IN_USE macro. Look for trace header in systemincludes. Make directories in makefile parse to prevent clashes during build. Correct path for autogen headers. Correct case issue with autogen headers on Linux.

/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
* @internalComponent 
* @released
*
*/

#include <e32rom.h>
#include "rom_image_reader.h"
#include "r_rom.h"

void InflateUnCompress(unsigned char* source, int sourcesize, unsigned char* dest, int destsize);
RomImageFSEntry::RomImageFSEntry (const char* aName) : iName(aName), iSibling(0), iChildren(0) {
}
RomImageFSEntry::~RomImageFSEntry() {
	if(iChildren){
		delete iChildren;
		iChildren = NULL ;
	}
	if(iSibling){
		delete iSibling ;
		iSibling = NULL ;
	}	
}

//Rom Image header 
RomImageHeader::RomImageHeader(char* aHdr, EImageType aImgType)
{
	switch( aImgType)
	{
	case EROM_IMAGE:
		iLoaderHdr = (TRomLoaderHeader*)aHdr;
		iRomHdr = (TRomHeader*)(aHdr + sizeof(TRomLoaderHeader));
		iExtRomHdr = 0;
		break;

	case EROMX_IMAGE:
		iExtRomHdr = (TExtensionRomHeader*)(aHdr);
		iRomHdr = 0;
		iLoaderHdr = 0;
		break;
        
    case EBAREROM_IMAGE:
        iLoaderHdr = 0;
        iRomHdr = (TRomHeader*)aHdr;
        iExtRomHdr = 0;
        break;
   default:
   		iExtRomHdr = 0;
		iRomHdr = 0;
		iLoaderHdr = 0;
   	break ;
	}
}


void RomImageHeader::DumpRomHdr()
{
    if(iLoaderHdr)
        *out << "ROM Image " << endl << endl;
    else
        *out << "Bare ROM Image" << endl << endl;
	TUint aPos = 0;
	bool aContinue = true;
	
	*out << "Image Signature .................";

    if(iLoaderHdr){
        TText *aRomName =  reinterpret_cast<TText *>(iLoaderHdr) ;
        while (aPos < KRomNameSize) {
            *out << (char)aRomName[aPos++];
        }
    }

	*out << endl << endl;

	DumpInHex("Timestamp", (iRomHdr->iTime >> 32)) ;
	DumpInHex(" ", (iRomHdr->iTime &0xffffffff), aContinue) << endl;

	DumpInHex("RomBase", iRomHdr->iRomBase) << endl;

	DumpInHex("RomSize", iRomHdr->iRomSize) << endl;
	DumpInHex("KernelDataAddress", iRomHdr->iKernDataAddress) << endl;
	DumpInHex("KernelLimit", iRomHdr->iKernelLimit) << endl;
	DumpInHex("PrimaryFile", iRomHdr->iPrimaryFile) << endl;
	DumpInHex("SecondaryFile", iRomHdr->iSecondaryFile) << endl;
	DumpInHex("CheckSum", iRomHdr->iCheckSum) << endl;
	DumpInHex("Hardware", iRomHdr->iHardware) << endl;

	DumpInHex("Language", (TUint)(iRomHdr->iLanguage >> 32));
	DumpInHex(" ", ((TUint)(iRomHdr->iLanguage & 0xffffffff)), aContinue) <<endl;

	DumpInHex("KernelConfigFlags", iRomHdr->iKernelConfigFlags) << endl;
	DumpInHex("RomExceptionSearchTable", iRomHdr->iRomExceptionSearchTable) << endl;
	DumpInHex("RomHeaderSize", iRomHdr->iRomHeaderSize) << endl;
	DumpInHex("RomSectionHeader", iRomHdr->iRomSectionHeader) << endl;
	DumpInHex("TotalSvDataSize", iRomHdr->iTotalSvDataSize) << endl;
	DumpInHex("VariantFile", iRomHdr->iVariantFile) << endl;
	DumpInHex("ExtensionFile", iRomHdr->iExtensionFile) << endl;
	DumpInHex("RelocInfo", iRomHdr->iRelocInfo) << endl;
	DumpInHex("OldTraceMask", iRomHdr->iOldTraceMask) << endl;
	DumpInHex("UserDataAddress", iRomHdr->iUserDataAddress) << endl;
	DumpInHex("TotalUserDataSize", iRomHdr->iTotalUserDataSize) << endl;
	DumpInHex("DebugPort", iRomHdr->iDebugPort) << endl;
	
	DumpInHex("Version", iRomHdr->iVersion.iMajor, false, 2);
	DumpInHex(".", iRomHdr->iVersion.iMinor, aContinue, 2);
	DumpInHex("(" ,iRomHdr->iVersion.iBuild, aContinue, 2);
	*out << ")" << endl;

	DumpInHex("CompressionType", iRomHdr->iCompressionType) << endl;
	DumpInHex("CompressedSize", iRomHdr->iCompressedSize) << endl;
	DumpInHex("UncompressedSize", iRomHdr->iUncompressedSize) << endl;
	DumpInHex("HcrFileAddress", iRomHdr->iHcrFileAddress) << endl;
	
	DumpInHex("DisabledCapabilities", iRomHdr->iDisabledCapabilities[0]);
	DumpInHex(" ", iRomHdr->iDisabledCapabilities[1], aContinue) << endl;

	DumpInHex("TraceMask", iRomHdr->iTraceMask[0]);
	aPos = 1;
	while( aPos < (TUint)KNumTraceMaskWords)
	{
		if(iRomHdr->iTraceMask[aPos])
		{
			DumpInHex(" ", iRomHdr->iTraceMask[aPos++], aContinue);
		}
		else
		{
			DumpInHex(" ", iRomHdr->iTraceMask[aPos++], aContinue, 1);
		}

	}

	*out << endl << endl;

}
void RomImageHeader::DumpRomXHdr()
{
	*out << "Extension ROM Image" << endl << endl;
	bool aContinue = true;
	
	DumpInHex("Timestamp", (iExtRomHdr->iTime >> 32)) ;
	DumpInHex(" ", (iExtRomHdr->iTime &0xffffffff), aContinue) << endl;

	DumpInHex("RomBase", iExtRomHdr->iRomBase) << endl;

	DumpInHex("RomSize", iExtRomHdr->iRomSize) << endl;
	DumpInHex("CheckSum", iExtRomHdr->iCheckSum) << endl;
	
	DumpInHex("Version", iExtRomHdr->iVersion.iMajor, false, 2);
	DumpInHex(".", iExtRomHdr->iVersion.iMinor, aContinue, 2);
	DumpInHex("(" ,iExtRomHdr->iVersion.iBuild, aContinue, 2);
	*out << ")" << endl;

	DumpInHex("CompressionType", iExtRomHdr->iCompressionType) << endl;
	DumpInHex("CompressedSize", iExtRomHdr->iCompressedSize) << endl;
	DumpInHex("UncompressedSize", iExtRomHdr->iUncompressedSize) << endl;
	
	*out << endl << endl;

}
//Rom Image reader
RomImageReader::RomImageReader(const char* aFile, EImageType aImgType) :
ImageReader(aFile), iImageHeader(0),
iRomSize(0),iHeaderBuffer(0),
iRomLayoutData(0),iImgType(aImgType)
{
	iRomImageRootDirEntry = new RomImageDirEntry("");
}

RomImageReader::~RomImageReader()
{
	if(iFile.is_open())
		iFile.close();
	if(iHeaderBuffer)
		delete []iHeaderBuffer;
	if(iRomLayoutData)
		delete []iRomLayoutData;  
	delete iRomImageRootDirEntry;

	
}

void RomImageReader::ReadImage()
{
	if(iFile.is_open()) return ;
	iFile.open(iImgFileName.c_str(), ios::binary | ios::in);
	if( !iFile.is_open() ) {
		throw ImageReaderException(iImgFileName.c_str(), "Cannot open file ");
	}	
	
	TUint headerSize = GetHdrSize() ;	
	if(headerSize > 0){
		iHeaderBuffer = new char[headerSize];
		iFile.read(iHeaderBuffer,headerSize);
	}	
}
 
void RomImageReader::Validate()
{
}

TUint32 RomImageReader::GetImageCompressionType()
{
	if(iImageHeader->iRomHdr )// iImageType == EROM_IMAGE
		return iImageHeader->iRomHdr->iCompressionType;
	else
		return iImageHeader->iExtRomHdr->iCompressionType;
}

 
TLinAddr RomImageReader::GetRomBase()
{
	if(iImageHeader->iRomHdr )// iImageType == EROM_IMAGE
		return iImageHeader->iRomHdr->iRomBase ;
	else
		return iImageHeader->iExtRomHdr->iRomBase;
}

TLinAddr RomImageReader::GetRootDirList()
{
	if(iImageHeader->iRomHdr )// iImageType == EROM_IMAGE
		return iImageHeader->iRomHdr->iRomRootDirectoryList;
	else
		return iImageHeader->iExtRomHdr->iRomRootDirectoryList;
}

TUint RomImageReader::GetHdrSize()
{
	TUint headerSize = 0;
	if(EROM_IMAGE == iImgType){
		headerSize = sizeof(TRomLoaderHeader) + sizeof(TRomHeader);
	}else if(EROMX_IMAGE == iImgType){
		headerSize = sizeof(TExtensionRomHeader);
	}else if(EBAREROM_IMAGE == iImgType){
		headerSize = sizeof(TRomHeader);
	}
	return headerSize;
}
 
 
static const TInt KIOBytes = 0x100000;
// reading a huge buffer at a time is very slow, reading 1MB bytes at a time is much faster
void RomImageReader::ReadData(char* aBuffer, TUint aLength)
{
	TUint readBytes = 0 ;
	while(readBytes < aLength){
		TUint toRead = KIOBytes;
		if(readBytes + toRead > aLength)
			toRead = aLength - readBytes ;
		iFile.read(&aBuffer[readBytes],toRead);
		readBytes += toRead ;
	}	
}
void RomImageReader::ProcessImage()
{
	if(iRomLayoutData) return ;
	iImageHeader = new RomImageHeader(iHeaderBuffer, iImgType);

	iFile.seekg(0, ios::end);
	// fileSize
	TUint fileSize = iFile.tellg(); 

	//let's skip the RomLoaderHeader
	TUint romDataBegin = (EROM_IMAGE == iImgType) ? sizeof(TRomLoaderHeader) : 0 ; 
	iFile.seekg(romDataBegin,ios::beg);	

	if(EROMX_IMAGE == iImgType){// EROMX_IMAGE, just set the iUnpagedRomBuffer		
		if(GetImageCompressionType() == KUidCompressionDeflate){
			TUint32 readLen = fileSize - sizeof(TExtensionRomHeader) ; 
			iRomSize = iImageHeader->iExtRomHdr->iUncompressedSize ;	 
			iRomLayoutData = new char[iRomSize];
			char* temp = new char[readLen];
			// header is not compressed.
			iFile.read(iRomLayoutData,sizeof(TExtensionRomHeader)); 
			ReadData(temp ,readLen);
			TUint8* uncompressDest = reinterpret_cast<TUint8*>(iRomLayoutData + sizeof(TExtensionRomHeader));
			InflateUnCompress(reinterpret_cast<TUint8*>(temp),readLen,uncompressDest,iRomSize - sizeof(TExtensionRomHeader));
			delete []temp ;	 
			
		}else{
			iRomSize = fileSize  ;
			iRomLayoutData = new char[iRomSize]; 
			ReadData(iRomLayoutData,iRomSize);
		}	 
	} // end EROMX_IMAGE
	else {
		 //EROM_IMAGE or EBAREROM_IMAGE
		const TInt KPageSize = 0x1000; 
		TRomHeader *hdr = iImageHeader->iRomHdr; 
		iRomSize = hdr->iUncompressedSize ; 
		iRomLayoutData = new char[iRomSize]; 
		char* curDataPointer = iRomLayoutData ;
		TUint totalReadBytes = 0;
		bool hasPageableSec = (hdr->iPageableRomStart > 0 && hdr->iPageableRomSize > 0) ;
		
		// read data before unpaged 
		ReadData(curDataPointer,hdr->iCompressedUnpagedStart); 
		curDataPointer += hdr->iCompressedUnpagedStart ; 
		totalReadBytes += hdr->iCompressedUnpagedStart;		

		// read the unpaged part, if compressed , then decompress		 
		if(GetImageCompressionType() == KUidCompressionDeflate){
			char* temp = new char[hdr->iUnpagedCompressedSize];
			ReadData(temp,hdr->iUnpagedCompressedSize);
			totalReadBytes += hdr->iUnpagedCompressedSize;
			InflateUnCompress(reinterpret_cast<TUint8*>(temp),hdr->iUnpagedCompressedSize,reinterpret_cast<TUint8*>(curDataPointer) ,hdr->iUnpagedUncompressedSize);
			delete []temp ;			
		}else{
			TUint unpagedSeclen ;
			if(hasPageableSec) { // there is paged section 
				unpagedSeclen = hdr->iPageableRomStart - hdr->iCompressedUnpagedStart;
			}else{
				unpagedSeclen = iRomSize - hdr->iCompressedUnpagedStart;
			}
			ReadData(curDataPointer,unpagedSeclen);			 
			totalReadBytes += unpagedSeclen ;
		}
		curDataPointer = iRomLayoutData + totalReadBytes; 
		//if there is a paged section , read and extract it 

		// read the paged section,
		if(hasPageableSec){		
			if((TUint)(hdr->iPageableRomStart + hdr->iPageableRomSize) > iRomSize){
					throw ImageReaderException("Incorrect values of ROM header fields.", "");
			}
			if(0 == hdr->iRomPageIndex){ //
				// no compression for paged section ,just read it 			 
				iFile.read(curDataPointer,iRomSize - totalReadBytes);
			}
			else{
				//aligment calculation
				TUint pagedSecOffset = (totalReadBytes + KPageSize - 1) & (~(KPageSize - 1));
				if(pagedSecOffset > totalReadBytes){
					// there are gap bytes between unpaged and paged sections
					iFile.read(curDataPointer,pagedSecOffset - totalReadBytes);
					curDataPointer = iRomLayoutData + pagedSecOffset;
				}
				TUint pagedIndexCount = ( hdr->iUncompressedSize + KPageSize - 1) / KPageSize;
				// how many bytes ?
				// the page index table include the unpaged part ;
				TUint firstPagedIndexTblItem = hdr->iPageableRomStart / KPageSize;
			 
				TUint tempBufLen = KPageSize << 8;
				char* readBuffer = new char[tempBufLen]; 
			 
				TUint8* src,*srcNext = NULL;
				SRomPageInfo* pageInfo = reinterpret_cast<SRomPageInfo*>(&iRomLayoutData[hdr->iRomPageIndex]);
				CBytePair bp(EFalse);
				for(TUint i = firstPagedIndexTblItem ; i < pagedIndexCount ; i+= 256){
					TUint endIndex = i + 255 ;
					if(endIndex >= pagedIndexCount)
						endIndex = pagedIndexCount - 1;
					TUint readLen = pageInfo[endIndex].iDataStart + pageInfo[endIndex].iDataSize - pageInfo[i].iDataStart ; 
					iFile.read(readBuffer,readLen);
					src = reinterpret_cast<TUint8*>(readBuffer);
					for(TUint j = i ; j <= endIndex ; j++){
						switch(pageInfo[j].iCompressionType)
						{
						case SRomPageInfo::EBytePair:
							{
							TInt unpacked = bp.Decompress(reinterpret_cast<TUint8*>(curDataPointer), KPageSize, src, pageInfo[j].iDataSize, srcNext);
							if (unpacked < 0) {
								delete []readBuffer;
								throw ImageReaderException("Corrupted BytePair compressed ROM image", "");
							}
							curDataPointer += unpacked;
							break ;
							}
						case SRomPageInfo::ENoCompression:
							memcpy(curDataPointer,src,pageInfo[j].iDataSize);
							curDataPointer +=  pageInfo[j].iDataSize ;
							break ;
						default:
							delete []readBuffer;
							throw ImageReaderException("Undefined compression type", "");
							break ;
						
						}
						src += pageInfo[j].iDataSize; 
					} // end for(TUint j = i ; j <= endIndex ; j++) 
				} // end for(TUint i = firstPagedIndexTblItem ; i < pagedIndexCount ; i+= 256) 
				delete []readBuffer ;
			}// else
			 
		} // if(hasPageableSec)  

	}
	TUint32 offset = GetRootDirList() - GetRomBase(); 
	TRomRootDirectoryList* rootDirList = reinterpret_cast<TRomRootDirectoryList*>(iRomLayoutData + offset );
	TInt dirCount = rootDirList->iNumRootDirs ; 
	string tempName ;
	for(TInt i = 0 ; i < dirCount ; i++) {
		offset = rootDirList->iRootDir[i].iAddressLin - GetRomBase(); 
		TRomDir* romDir = reinterpret_cast<TRomDir*>(iRomLayoutData + offset);		
		Name(tempName,reinterpret_cast<const wchar_t *>(romDir->iEntry.iName),romDir->iEntry.iNameLength); 		 
		BuildDir(romDir, iRomImageRootDirEntry);		 
	}
 
}
 
 
void RomImageReader::BuildDir(TRomDir* aDir, RomImageFSEntry* aPaFSEntry)
{	 
	
	TInt processBytes = 0 ;
	TInt totalDirBytes = aDir->iSize - sizeof(aDir->iSize);
	TRomEntry* entry = &aDir->iEntry;
	RomImageFSEntry *fsEntry ;
	string name ;
	const char* pritableName = "";

	while(processBytes < totalDirBytes){
		Name(name,reinterpret_cast<const wchar_t *>(entry->iName),entry->iNameLength);
		pritableName = name.c_str(); 
		if(entry->iAtt & 0x10) { // is a directory
			fsEntry = new RomImageDirEntry(pritableName); 
			AddChild(aPaFSEntry,fsEntry,NULL);
			TUint offset = entry->iAddressLin - GetRomBase();
			TRomDir* subFolder = reinterpret_cast<TRomDir*>(iRomLayoutData + offset);		 
			BuildDir(subFolder,fsEntry); 
		}
		else{
			fsEntry = new RomImageFileEntry(pritableName); 
			AddChild(aPaFSEntry,fsEntry,entry);
		} 
		// increase the processedBytes
		processBytes += (entry->iNameLength << 1) +  reinterpret_cast<TInt>(entry->iName) - reinterpret_cast<TInt>(entry); 

		//align to next 4 bytes
		processBytes = (processBytes + 3) & ( ~3 ); 
		// get next entry
		entry =  reinterpret_cast<TRomEntry*>( reinterpret_cast<char*>(&aDir->iEntry) + processBytes);
	} 
	
}

void RomImageReader::AddChild(RomImageFSEntry *aParent, RomImageFSEntry *aChild, TRomEntry* aRomEntry)
{
	if(!aParent->iChildren)
		aParent->iChildren = aChild;
	else {
		RomImageFSEntry *aLast = aParent->iChildren;

		while(aLast->iSibling)
			aLast = aLast->iSibling;
		aLast->iSibling = aChild;
	}

	if(!aChild->IsDirectory()) { 
		RomImageFileEntry* file = static_cast<RomImageFileEntry*>(aChild);
		file->iTRomEntryPtr = aRomEntry;

		if(aRomEntry->iAddressLin > GetRomBase()) {
			TUint32 offset = aRomEntry->iAddressLin - GetRomBase();	 
		 
			TRomImageHeader* imgHdr = reinterpret_cast<TRomImageHeader*>(iRomLayoutData + offset);
			 
			file->ImagePtr.iRomFileEntry = imgHdr;

			TUint8 aUid1[4];
			memcpy(aUid1, &file->ImagePtr.iRomFileEntry->iUid1, 4);

			if( ReaderUtil::IsExecutable(aUid1) ) {
				file->iExecutable = true;
			}
			else {
				file->iExecutable = false;
				file->ImagePtr.iDataFileAddr = aRomEntry->iAddressLin;
			}
		}
		else {
			file->ImagePtr.iRomFileEntry = NULL; 
		}
	}

	if(aParent != iRomImageRootDirEntry) {
		aChild->iPath = aParent->iPath;
		aChild->iPath += DIR_SEPARATOR;
		aChild->iPath += aParent->iName.c_str();
	}
}

void RomImageReader::Name(string& aName, const wchar_t* aUnicodeName, TUint aLen)
{
	char* temp = (char*)_alloca((aLen << 1) + 1) ;
	size_t n = wcsrtombs(temp,&aUnicodeName,aLen,NULL);
	if(n == (size_t)-1){ // the unicode string can not be coverted.
		aName = "???";
	}
	temp[n] = 0;
	if(n > 0)
		aName.assign(temp,n) ;
	else
		aName = "";
 
}

void RomImageReader::DumpTree()
{
	RomImageFSEntry* aFsEntry = iRomImageRootDirEntry;
	if( aFsEntry->iChildren ) 
		DumpSubTree(aFsEntry->iChildren); 
}

void RomImageReader::DumpDirStructure()
{
	*out << "Directory Listing" << endl;
	*out << "=================" << endl;
	int aPadding = 0;
	if( iRomImageRootDirEntry ){
		DumpDirStructure(iRomImageRootDirEntry, aPadding);
	}	
	*out << endl << endl;
}

void RomImageReader::DumpDirStructure(RomImageFSEntry* aEntry, int &aPadding)
{
	if(!aEntry)
		return;

	int aPadLen = 2 * aPadding;//scaling for legibility
	for (int i = 0; i < aPadLen; i++)
		*out << " ";

	*out << aEntry->Name() << endl;

	if( aEntry->iChildren){
		aPadding++;
		DumpDirStructure(aEntry->iChildren, aPadding);
		aPadding--;
	}
	DumpDirStructure(aEntry->iSibling, aPadding);
}

void RomImageReader::DumpSubTree(RomImageFSEntry* aFsEntry)
{
	if(!aFsEntry)
		return;

	if( aFsEntry->iChildren ){
		DumpSubTree(aFsEntry->iChildren);
	}

	if( aFsEntry->iSibling )
		DumpSubTree(aFsEntry->iSibling);

	RomImageFSEntry *aEntry = aFsEntry;
	
	if(!aEntry->IsDirectory()) {
		*out << "********************************************************************" << endl;
		*out << "File........................" << aEntry->iPath.c_str() << DIR_SEPARATOR << aEntry->Name() << endl;

		if( ((RomImageFileEntry*)aEntry)->iExecutable )	{
			DumpImage((RomImageFileEntry*)aEntry);
		}
		else{
			*out << "Linear Addr................." << ((RomImageFileEntry*)aEntry)->ImagePtr.iDataFileAddr << endl;
		}
	}
}

void RomImageReader::DumpImage(RomImageFileEntry * aEntry)
{
	bool aContinue = true;

	DumpInHex("Load Address", aEntry->iTRomEntryPtr->iAddressLin) << endl;
	DumpInHex("Size", aEntry->iTRomEntryPtr->iSize) << endl;

	TRomImageHeader		*aRomImgEntry = aEntry->ImagePtr.iRomFileEntry;

	if( !aRomImgEntry )
		return;
	//UIDs
	DumpInHex("Uids", aRomImgEntry->iUid1);
	DumpInHex(" ", aRomImgEntry->iUid2, aContinue);
	DumpInHex(" ", aRomImgEntry->iUid3, aContinue);
	DumpInHex(" ", aRomImgEntry->iUidChecksum, aContinue) << endl;

	DumpInHex("Entry point", aRomImgEntry->iEntryPoint) << endl;
	DumpInHex("Code start addr", aRomImgEntry->iCodeAddress) << endl;
	DumpInHex("Data start addr", aRomImgEntry->iDataAddress) << endl;
	DumpInHex("DataBssLinearBase", aRomImgEntry->iDataBssLinearBase) << endl;
	DumpInHex("Text size", aRomImgEntry->iTextSize) << endl;
	DumpInHex("Code size", aRomImgEntry->iCodeSize) << endl;
	DumpInHex("Data size", aRomImgEntry->iDataSize) << endl;
	DumpInHex("Bss size", (aRomImgEntry->iBssSize)) << endl;
	DumpInHex("Total data size", aRomImgEntry->iTotalDataSize) << endl;
	DumpInHex("Heap min", aRomImgEntry->iHeapSizeMin) << endl;
	DumpInHex("Heap max", aRomImgEntry->iHeapSizeMax) << endl;
	DumpInHex("Stack size", aRomImgEntry->iStackSize) << endl;

	TDllRefTable *aRefTbl = NULL;

	if( aRomImgEntry->iDllRefTable ) {
		TUint32 aOff = (TUint32)aRomImgEntry->iDllRefTable - iImageHeader->iRomHdr->iRomBase;
		aRefTbl = (TDllRefTable*) ((char*)iImageHeader->iRomHdr + aOff);
		TUint32 aVirtualAddr = (TUint32)aRefTbl->iEntry[0];
		DumpInHex("Dll ref table", aVirtualAddr) << endl;
	}

	DumpInHex("Export directory", aRomImgEntry->iExportDir) << endl;
	DumpInHex("Export dir count", aRomImgEntry->iExportDirCount) << endl;
	DumpInHex("Hardware variant", aRomImgEntry->iHardwareVariant) << endl;
	DumpInHex("Flags", aRomImgEntry->iFlags) << endl;
	DumpInHex("Secure ID", aRomImgEntry->iS.iSecureId) << endl;
	DumpInHex("Vendor ID", aRomImgEntry->iS.iVendorId) << endl;

	DumpInHex("Capability", aRomImgEntry->iS.iCaps[1]);
	DumpInHex(" ", aRomImgEntry->iS.iCaps[0], aContinue) << endl;
	
	*out << "Tools Version..............." << dec << (TUint)aRomImgEntry->iToolsVersion.iMajor;
	*out << "." ; 
	out->width(2) ;
	out->fill('0');
	*out << dec << (TUint)aRomImgEntry->iToolsVersion.iMinor ;
	*out << "(" << dec << aRomImgEntry->iToolsVersion.iBuild << ")";
	*out << endl;

	*out << "Module Version.............." << dec << (aRomImgEntry->iModuleVersion >> 16) << endl;
	DumpInHex("Exception Descriptor", aRomImgEntry->iExceptionDescriptor) << endl;
	*out << "Priority...................." << dec << aRomImgEntry->iPriority << endl;

	if( aRefTbl )
		DumpInHex("Dll ref table size", aRefTbl->iNumberOfEntries*8) << endl;
	else
		DumpInHex("Dll ref table size", 0) << endl;

	if( iDisplayOptions & DUMP_E32_IMG_FLAG){
		if(stricmp(iE32ImgFileName.c_str(), aEntry->Name()) == 0){
			TUint aSectionOffset = aRomImgEntry->iCodeAddress - iImageHeader->iRomHdr->iRomBase;
			TUint* aCodeSection = (TUint*)((char*)iImageHeader->iRomHdr + aSectionOffset);
			*out << "\nCode (Size=0x" << hex << aRomImgEntry->iCodeSize << ")" << endl;
			DumpData(aCodeSection, aRomImgEntry->iCodeSize);

			aSectionOffset = aRomImgEntry->iDataAddress - iImageHeader->iRomHdr->iRomBase;
			TUint* aDataSection = (TUint*)((char*)iImageHeader->iRomHdr + aSectionOffset);
			if( aRomImgEntry->iDataSize){
				*out << "\nData (Size=0x" << hex << aRomImgEntry->iDataSize << ")" << endl;
				DumpData(aDataSection, aRomImgEntry->iDataSize);
			}
		}
	}

	*out << endl << endl;
}

void RomImageReader::DumpAttribs(RomImageFSEntry* aFsEntry)
{
 
// a larger rom image cause stack overflow under visual studio if we use recursion algorithm here.
// can gcc compiler guarantee this overflow will never be happen ?
 	if( aFsEntry->iChildren )
		DumpAttribs(aFsEntry->iChildren);

	if(aFsEntry->iSibling)
		DumpAttribs(aFsEntry->iSibling);
	if(aFsEntry->IsDirectory()) return ;
	RomImageFileEntry* file = static_cast<RomImageFileEntry*>(aFsEntry);
	if(!file->iExecutable) return ; 
	TRomImageHeader* aRomImgEntry = file->ImagePtr.iRomFileEntry;

	if( !aRomImgEntry)  return; 
	
	const char* prefix ;
	if(aRomImgEntry->iFlags & KRomImageFlagPrimary){
		prefix = "Primary";
	}
	else if(aRomImgEntry->iFlags & KRomImageFlagVariant){
		prefix = "Variant";
	}
	else if(aRomImgEntry->iFlags & KRomImageFlagExtension){
		prefix = "Extension";
	}
	else if(aRomImgEntry->iFlags & KRomImageFlagDevice){
		prefix = "Device";
	}
	else
		return;

	out->width(10);
	out->fill(' '); 
	*out << left << prefix;
	out->width(40);	
	*out << right << file->Name() << "[" ;
	DumpInHex( "", aRomImgEntry->iHardwareVariant, true) << "] ";
	DumpInHex( " DataSize=", (aRomImgEntry->iBssSize + aRomImgEntry->iDataSize), true) << endl;
	
}

void RomImageReader::Dump()
{
	if( !((iDisplayOptions & EXTRACT_FILES_FLAG) || 
		(iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG) ||
		(iDisplayOptions & EXTRACT_FILE_SET_FLAG)) ) {
		*out << "Image Name................." << iImgFileName.c_str() << endl;

		if( iImageHeader->iRomHdr )
		iImageHeader->DumpRomHdr();
		else
		iImageHeader->DumpRomXHdr();

		DumpAttribs(iRomImageRootDirEntry);
		*out << endl ;

		if(iDisplayOptions & DUMP_VERBOSE_FLAG) {
			DumpDirStructure();
			DumpTree();
		}

		if(iDisplayOptions & DUMP_DIR_ENTRIES_FLAG) {
			DumpDirStructure();
		}
	}
}


/** 
Function iterates through all the entries in the image 
by making a call to TraverseImage function.

@internalComponent
@released
*/
void RomImageReader::ExtractImageContents()
{
	if( (iDisplayOptions & EXTRACT_FILE_SET_FLAG) )
	{
		//TODO:
		ImageReader::ExtractFileSet(iRomLayoutData);
	}

	if( iDisplayOptions & EXTRACT_FILES_FLAG || iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG )
	{
		if(iRomImageRootDirEntry)
		{
			// name of the log file.
			string logFile;
			// output stream for the log file.
			ofstream oFile;
			
			if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG){
				if( ImageReader::iZdrivePath.compare("")){
					// create a string to hold path information.
					string filePath(ImageReader::iZdrivePath);
					string delimiter("\\"); 
					// replace backslash with double backslash. 
					FindAndInsertString(filePath,delimiter,delimiter);
					logFile = filePath;
					// create specified directory.
					CreateSpecifiedDir(&filePath[0],"\\\\");
					logFile.append("\\\\");
					logFile.append(ImageReader::iLogFileName);
				}
				else
				{				
					logFile = ImageReader::iLogFileName;
				}
				// open the specified file in append mode.
				oFile.open(logFile.c_str() ,ios::out|ios::app);

				if(!oFile.is_open()){
					throw ImageReaderException((char*)ImageReader::iLogFileName.c_str(), "Failed to open the log file");
				}
			}
			TraverseImage(iRomImageRootDirEntry,oFile);
			if(oFile.is_open())  oFile.close();  
		}
	}
}


/** 
Function to traverse entire image and check for an entity.If the entity found in the image is a file 
then it makes a call to CheckFileExtension to check for extension.

@internalComponent
@released

@param aEntity		- pointer to the entry in rom image.
@param aFile		- output stream.
*/
void RomImageReader::TraverseImage(RomImageFSEntry*  aEntity,ofstream& aFile)
{
	if(!aEntity->IsDirectory())	{
		CheckFileExtension(aEntity,aFile);
	}
	
 	if (aEntity->iChildren)	{
		TraverseImage(aEntity->iChildren,aFile);
	}

	if (aEntity->iSibling)	{
		TraverseImage(aEntity->iSibling,aFile);
	}
}


/** 
Function to get check extension of the given file.If the extension of the file is "sis"
then call ExtractFile function to extract the file from the image.  

@internalComponent
@released

@param aEntity		- pointer to the entry in rom image.
@param aFile		- output stream.
*/
void RomImageReader::CheckFileExtension(RomImageFSEntry*  aEntity,ofstream& aFile)
{
	RomImageFileEntry*	romEntry = (RomImageFileEntry*)aEntity;
	// get the size of the entity.
	TUint32 size = romEntry->iTRomEntryPtr->iSize;
	// get the offset of the entity.
	TUint32 offset =  romEntry->iTRomEntryPtr->iAddressLin - GetRomBase() ;

	const char* fileName = aEntity->iName.c_str();

	// create a string to hold the path information.
	string romfilePath(romEntry->iPath);
	string forwardSlash("/");
	string slash("\\");  
	//replace slash with double backward slash.
	FindAndReplaceString( romfilePath, forwardSlash, slash );
	
	if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG && iDisplayOptions & EXTRACT_FILES_FLAG ) {
		// get the position.
		size_t pos = aEntity->iName.find_last_of(".");
		
		const char* extName = fileName + ( pos + 1 );
		if ( !stricmp(extName ,"SIS")	||  !stricmp(extName ,"DAT") ) {
			// if the two strings are same then extract the corresponding file.
			ImageReader::ExtractFile(offset,size,fileName,&romfilePath[0],&ImageReader::iZdrivePath[0],iRomLayoutData);
		}
		else {
			LogRomEnrtyToFile(romfilePath.c_str(),fileName,aFile);
		}
	}
	else if( iDisplayOptions & LOG_IMAGE_CONTENTS_FLAG ) {
		LogRomEnrtyToFile(romfilePath.c_str(),fileName,aFile);
	}
	else {
		if(romEntry->iExecutable) {
			size += sizeof(TRomImageHeader);
		}
		// extract the corresponding file. 
		ImageReader::ExtractFile(offset,size,fileName,&romfilePath[0],&ImageReader::iZdrivePath[0],iRomLayoutData);
	}
}


/** 
Function to log the rom entry to a specified file. 

@internalComponent
@released

@param aPath		- Complete path of an entity.
@param aEntityName	- Entity name. 
@param aFile		- output stream.
*/
void RomImageReader::LogRomEnrtyToFile(const char* aPath,const char* aEntityName,ofstream& aFile)
{
	if(aFile.is_open())
	{
		aFile.seekp(0,ios::end);
		aFile<<aPath<<"\\"<<aEntityName<<"\n";
	}
}


/** 
Function to read the directory structure details of te ROM image.  

@internalComponent
@released

@param aEntity		- pointer to the entry in rom image.
@param aFileMap		- map of filename with its size and offset values.
@param aImgSize		- Image size
*/
void RomImageReader::ProcessDirectory(RomImageFSEntry *aEntity, FILEINFOMAP &aFileMap)
{
	if(!aEntity->IsDirectory()) { 

		RomImageFileEntry*	romEntry = (RomImageFileEntry*)aEntity;

		PFILEINFO fileInfo = new FILEINFO;

		// get the size of the entity.
		fileInfo->iSize = romEntry->iTRomEntryPtr->iSize;
		// get the offset of the entity.
		fileInfo->iOffset = (romEntry->iTRomEntryPtr->iAddressLin - GetRomBase()); 

		if(romEntry->iExecutable) {
			fileInfo->iSize += sizeof(TRomImageHeader);
		}

		if((fileInfo->iOffset + fileInfo->iSize) > iRomSize) {
			fileInfo->iOffset = 0;
			fileInfo->iSize = 0;
		}

		string fileName(romEntry->iPath);
		fileName.append(DIR_SEPARATOR);
		fileName.append(aEntity->iName);

		aFileMap[fileName] = fileInfo;
	}
	
 	if (aEntity->iChildren) {
		ProcessDirectory(aEntity->iChildren, aFileMap);
	}

	if (aEntity->iSibling) {
		ProcessDirectory(aEntity->iSibling, aFileMap);
	}
}

/** 
Function to read the directory structure details of te ROM image.  

@internalComponent
@released

@param aFileMap		- map of filename with its size and offset values.
*/
void RomImageReader::GetFileInfo(FILEINFOMAP &aFileMap) {
	ProcessDirectory(iRomImageRootDirEntry, aFileMap);
}

/** 
Function to get the ROM image size.

@internalComponent
@released
*/
TUint32 RomImageReader::GetImageSize() {
	return iRomSize;
}