imgtools/romtools/rombuild/r_rom.cpp
changeset 2 39c28ec933dd
equal deleted inserted replaced
1:820b22e13ff1 2:39c28ec933dd
       
     1 /*
       
     2 * Copyright (c) 1996-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 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32std.h>
       
    20 #include <e32std_private.h>
       
    21 #include <e32uid.h>
       
    22 #include "h_utl.h"
       
    23 #include <string.h>
       
    24 #include <stdlib.h>
       
    25 
       
    26 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
    27 #include <iomanip>
       
    28 #else //!__MSVCDOTNET__
       
    29 #include <iomanip.h>
       
    30 #endif //__MSVCDOTNET__
       
    31 
       
    32 #include "r_global.h"
       
    33 #include "r_obey.h"
       
    34 #include "r_rom.h"
       
    35 #include "r_dir.h"
       
    36 #include "patchdataprocessor.h"
       
    37 #include "memmap.h"
       
    38 #include "byte_pair.h"
       
    39 
       
    40 const TInt KSpareExports=16;
       
    41 extern TInt gThreadNum;
       
    42 extern char* gDepInfoFile;
       
    43 extern TBool gGenDepGraph;
       
    44 
       
    45 TUint32 DeflateCompressCheck(char *bytes,TInt size,ostream &os);
       
    46 void DeflateCompress(char *bytes,TInt size,ostream &os);
       
    47 void InflateUnCompress(unsigned char* source, int sourcesize,unsigned char* dest, int destsize);
       
    48 
       
    49 EntryQueue* LoadImageWorker::m_queue = NULL;
       
    50 TInt LoadImageWorker::m_errors = 0;
       
    51 TMemModel LoadImageWorker::m_memmodel;
       
    52 boost::mutex LoadImageWorker::m_mutex;
       
    53 LoadImageWorker::LoadImageWorker(EntryQueue* aQueue, TMemModel aMemModel)
       
    54 	{
       
    55 	m_queue = aQueue;
       
    56 	m_memmodel = aMemModel;
       
    57 	}
       
    58 void LoadImageWorker::operator()()
       
    59 	{
       
    60 	while(1)
       
    61 		{
       
    62 		m_mutex.lock();
       
    63 		if(m_queue->size() > 0)
       
    64 			{
       
    65 			TRomBuilderEntry * current = m_queue->front();
       
    66 			m_queue->pop();
       
    67 			m_mutex.unlock();
       
    68 			TInt err = current->OpenImageFile();
       
    69 			if(err)
       
    70 				{
       
    71 				m_mutex.lock();
       
    72 				++m_errors;
       
    73 				m_mutex.unlock();
       
    74 				continue;
       
    75 				}
       
    76 			if(current->iOverrideFlags&KOverrideAddress || current->iHdr->iFlags & KImageFixedAddressExe)
       
    77 				{
       
    78 				if(m_memmodel != E_MM_Multiple && m_memmodel != E_MM_Flexible &&  !current->IsDll())
       
    79 					current->iRomImageFlags |=KRomImageFlagFixedAddressExe;
       
    80 				}
       
    81 			if(gPagedRom)
       
    82 				{
       
    83 				if(current->iHdr->iFlags&KImageCodePaged)
       
    84 					{
       
    85 					current->iRomImageFlags&=~KRomImageFlagCodeUnpaged;
       
    86 					current->iRomImageFlags|=KRomImageFlagCodePaged;
       
    87 					}
       
    88 				if(current->iHdr->iFlags&KImageCodeUnpaged)
       
    89 					{
       
    90 					current->iRomImageFlags|=KRomImageFlagCodeUnpaged;
       
    91 					current->iRomImageFlags&=~KRomImageFlagCodePaged;
       
    92 					}
       
    93 				}
       
    94 			if(current->iHdr->iFlags&KImageDataPaged)
       
    95 				{
       
    96 				current->iRomImageFlags&=~KRomImageFlagDataUnpaged;
       
    97 				current->iRomImageFlags|=KRomImageFlagDataPaged;
       
    98 				}
       
    99 			if(current->iHdr->iFlags&KImageDataUnpaged)
       
   100 				{
       
   101 				current->iRomImageFlags|=KRomImageFlagDataUnpaged;
       
   102 				current->iRomImageFlags&=~KRomImageFlagDataPaged;
       
   103 				}
       
   104 			if(current->iHdr->iFlags&KImageDebuggable)
       
   105 				{
       
   106 				current->iRomImageFlags|=KRomImageDebuggable;
       
   107 				}
       
   108 				else
       
   109 				{
       
   110 				current->iRomImageFlags&=~KRomImageDebuggable;
       
   111 				}
       
   112 			}
       
   113 			else
       
   114 			{
       
   115 			m_mutex.unlock();
       
   116 			break;
       
   117 			}
       
   118 		}
       
   119 	}
       
   120 E32Rom* CompressPageWorker::m_rom = NULL;
       
   121 TInt CompressPageWorker::m_nextpage = 0;
       
   122 TInt CompressPageWorker::m_totalpages = 0;
       
   123 TInt CompressPageWorker::m_pagesize = 0;
       
   124 boost::mutex CompressPageWorker::m_mutex;
       
   125 TInt CompressPageWorker::m_error = 0;
       
   126 CompressPageWorker::CompressPageWorker(E32Rom* aRom, TInt aPageSize, TInt aTotalPages, TInt aNextPage)
       
   127 	{
       
   128 	m_rom = aRom;
       
   129 	m_pagesize = aPageSize;
       
   130 	m_totalpages = aTotalPages;
       
   131 	m_nextpage = aNextPage;
       
   132 	}
       
   133 void CompressPageWorker::operator()()
       
   134 	{
       
   135 	SRomPageInfo* pPageBase = (SRomPageInfo*)((TInt)m_rom->iHeader + m_rom->iHeader->iRomPageIndex);
       
   136 	CBytePair bpe(gFastCompress);
       
   137 	while(1)
       
   138 		{
       
   139 		m_mutex.lock();
       
   140 		TInt currentPageIndex = m_nextpage++;
       
   141 		m_mutex.unlock();
       
   142 		if(currentPageIndex < m_totalpages)
       
   143 			{
       
   144 			TInt inOffset = m_pagesize * currentPageIndex;
       
   145 			TUint8 attrib = (TUint8)SRomPageInfo::EPageable;
       
   146 			SRomPageInfo info ={ (TUint32)inOffset, (TUint16)m_pagesize, (TUint8)SRomPageInfo::EBytePair, attrib };
       
   147 			TUint8* in = (TUint8*) m_rom->iHeader + inOffset;
       
   148 			TUint8* out = in;
       
   149 			TInt outSize = BytePairCompress(out, in, m_pagesize, &bpe);
       
   150 			if(outSize == KErrTooBig)
       
   151 				{
       
   152 				info.iCompressionType = SRomPageInfo::ENoCompression;
       
   153 				memcpy(out, in, m_pagesize);
       
   154 				outSize = m_pagesize;
       
   155 				}
       
   156 				if(outSize < 0 )
       
   157 					{
       
   158 					m_mutex.lock();
       
   159 					m_error = outSize;
       
   160 					m_mutex.unlock();
       
   161 					break;
       
   162 					}
       
   163 				info.iDataSize = (TUint16) outSize;
       
   164 				*(pPageBase + currentPageIndex) = info;
       
   165 				if((currentPageIndex & 255) == 255)
       
   166 					{
       
   167 					m_mutex.lock();
       
   168 					Print(EAlways, ".\n");
       
   169 					m_mutex.unlock();
       
   170 					}
       
   171 				}
       
   172 			else
       
   173 			{
       
   174 			break;
       
   175 			}
       
   176 		}
       
   177 	}
       
   178 	
       
   179 ////////////////////////////////////////////////////////////////////////
       
   180 
       
   181 TAddressRange::TAddressRange() 
       
   182 	: iImagePtr(0), iImageAddr(0), iRunAddr(0), iSize(0) 
       
   183 	{
       
   184 	}
       
   185 
       
   186 void TAddressRange::Append(TAddressRange& aRange)
       
   187 	{ 
       
   188 	if(aRange.iSize) 
       
   189 		{ 
       
   190 		aRange.iImagePtr = iImagePtr;
       
   191 		aRange.iImageAddr = iImageAddr;
       
   192 		aRange.iRunAddr = iRunAddr;
       
   193 		Extend(aRange.iSize); 
       
   194 		} 
       
   195 	}
       
   196 
       
   197 void TAddressRange::Move(TInt aOffset) 
       
   198 	{ 
       
   199 	iImagePtr = static_cast<char*>(iImagePtr) + aOffset; 
       
   200 	iImageAddr += aOffset; 
       
   201 	iRunAddr += aOffset;
       
   202 	}
       
   203 
       
   204 void TAddressRange::Extend(TInt aOffset) 
       
   205 	{ 
       
   206 	Move(aOffset);
       
   207 	iSize += aOffset; 
       
   208 	}
       
   209 
       
   210 ////////////////////////////////////////////////////////////////////////
       
   211 
       
   212 inline TUint32 AlignData(TUint32 anAddr)
       
   213 	{
       
   214 	return ((anAddr+0x0f)&~0x0f);
       
   215 	}
       
   216 
       
   217 TUint32 E32Rom::AlignToPage(TUint32 anAddr)
       
   218 	{
       
   219 	TUint a=(TUint)iObey->iPageSize-1;
       
   220 	return ((anAddr+a)&~a);
       
   221 	}
       
   222 
       
   223 /*
       
   224 Allocate virtual memory for static data in rom.
       
   225 @param aAddr Base address of last allocated memory.
       
   226 @param aSize Size of memory to allocate.
       
   227 @return Address allocated. This is below aAddr.
       
   228 */
       
   229 TUint32 E32Rom::AllocVirtual(TUint32 aAddr,TUint aSize)
       
   230 	{
       
   231 	TInt align = iObey->iVirtualAllocSize;
       
   232 	if(align<0)
       
   233 		{
       
   234 		align = -align; // get correct sign
       
   235 		// -ve align means also align to next power-of-two >= aSize...
       
   236 		while(aSize>(TUint)align)
       
   237 			align <<=1;
       
   238 		}
       
   239 
       
   240 	TUint mask = (TUint)align-1;
       
   241 	aSize = (aSize+mask)&~mask; // round up
       
   242 	aAddr &= ~mask; // round down
       
   243 	return aAddr-aSize;
       
   244 	}
       
   245 
       
   246 TUint32 E32Rom::AlignToChunk(TUint32 anAddr)
       
   247 	{
       
   248 	TUint a=(TUint)iObey->iChunkSize-1;
       
   249 	return ((anAddr+a)&~a);
       
   250 	}
       
   251 
       
   252 COrderedFileList::COrderedFileList(TInt aMaxFiles)
       
   253 	: iCount(0), iMaxFiles(aMaxFiles), iOrderedFiles(NULL)
       
   254 	{}
       
   255 
       
   256 COrderedFileList::~COrderedFileList()
       
   257 	{
       
   258 	iCount=0;
       
   259 	delete[] iOrderedFiles;
       
   260 	}
       
   261 
       
   262 COrderedFileList* COrderedFileList::New(TInt aMaxFiles)
       
   263 	{
       
   264 	COrderedFileList *pL=new COrderedFileList(aMaxFiles);
       
   265 	pL->iOrderedFiles=new TRomBuilderEntry*[aMaxFiles];
       
   266 	return pL;
       
   267 	}
       
   268 
       
   269 void COrderedFileList::Add(TRomBuilderEntry* anEntry)
       
   270 	{
       
   271 	// note: this routine assumes that the set of kernel-mode files
       
   272 	// (primary/extension/device) required by a given variant is linearly ordered by <=
       
   273 	// e.g. can't have three variants {A,B,V1} {A,B,C,V2} {A,C,V3} because B and C
       
   274 	// are unordered with respect to <=, since neither of
       
   275 	// {n | Vn requires B} and {n | Vn requires C} is a subset of the other.
       
   276 	// In a case like this, ROMBUILD may fail to resolve the addresses of some global data
       
   277 	THardwareVariant& v=anEntry->iHardwareVariant;
       
   278 	TInt i=0;
       
   279 	while(i<iCount && v<=iOrderedFiles[i]->iHardwareVariant) i++;
       
   280 	TInt j=iCount;
       
   281 	while(j>i)
       
   282 		{
       
   283 		iOrderedFiles[j]=iOrderedFiles[j-1];
       
   284 		j--;
       
   285 		}
       
   286 	iOrderedFiles[i]=anEntry;
       
   287 	iCount++;
       
   288 	}
       
   289 
       
   290 void GetFileNameAndUid(char *aDllName, TUid &aDllUid, char *aExportName)
       
   291 	{	
       
   292 	strcpy(aDllName, aExportName);
       
   293 	aDllUid=KNullUid;
       
   294 	TInt start;
       
   295 	for (start=0; start<(TInt)strlen(aExportName) && aExportName[start]!='['; start++)
       
   296 		;
       
   297 	if (start==(TInt)strlen(aExportName))
       
   298 		start=KErrNotFound;
       
   299 	TInt end=strlen(aExportName)-1;
       
   300 	while (end>=0)
       
   301 		{
       
   302 		if (aExportName[end]==']')
       
   303 			break;
       
   304 		--end;
       
   305 		}
       
   306 	if (end<0)
       
   307 		end=KErrNotFound;
       
   308 
       
   309 	if ((start!=KErrNotFound) && (end!=KErrNotFound) && (end>start))
       
   310 		{
       
   311 		// Importing from DLL with Uid
       
   312 		char uidStr[0x100];
       
   313 		strcpy(uidStr, "0x");
       
   314 		strncat(uidStr, aExportName+start+1, end-start-1);
       
   315 		#ifdef __TOOLS2__
       
   316 		istringstream val(uidStr);
       
   317 		#else
       
   318 		istrstream val(uidStr,strlen(uidStr));
       
   319 		#endif
       
   320 
       
   321 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
   322 		val >> setbase(0);
       
   323 #endif //__MSVCDOTNET__
       
   324 
       
   325 		TUint32 u;
       
   326 		val >> u;
       
   327 		val.peek();
       
   328 		if (val.eof())
       
   329 			{
       
   330 			aDllUid=TUid::Uid(u);
       
   331 			char *dot=aExportName+strlen(aExportName)-1;
       
   332 			while (dot>=aExportName)
       
   333 				{
       
   334 				if (*dot=='.')
       
   335 					break;
       
   336 				dot--;
       
   337 				}
       
   338 			if (dot<aExportName) // no dot
       
   339 				aDllName[start]=0;
       
   340 			else
       
   341 				{
       
   342 				aDllName[start]=0;
       
   343 				strcat(aDllName, dot);
       
   344 				}
       
   345 			}
       
   346 		}
       
   347 	}
       
   348 
       
   349 E32Rom::E32Rom(CObeyFile *aObey)
       
   350 //
       
   351 // Constructor
       
   352 //
       
   353 	{
       
   354 
       
   355 	iSize=sizeof(TRomLoaderHeader)+aObey->iRomSize;
       
   356 	iObey=aObey;
       
   357 	iPeFiles=NULL;
       
   358 
       
   359 	if(gLowMem)
       
   360 	{
       
   361 		iImageMap = new Memmap();
       
   362 
       
   363 		if(iImageMap == NULL)
       
   364 		{
       
   365 			iSize = 0;
       
   366 			Print(EError, "Out of memory.\n");
       
   367 		}
       
   368 		else
       
   369 		{
       
   370 			iImageMap->SetMaxMapSize(iSize);
       
   371 			if(iImageMap->CreateMemoryMap(0, 0xff) == EFalse)
       
   372 			{
       
   373 				iSize = 0;
       
   374 				Print(EError, "Failed to create image map object");
       
   375 
       
   376 				iImageMap->CloseMemoryMap(ETrue);
       
   377 				delete iImageMap;
       
   378 				iImageMap = NULL;
       
   379 			}
       
   380 			else
       
   381 			{
       
   382 				iData = iImageMap->GetMemoryMapPointer();
       
   383 			}
       
   384 		}
       
   385 	}
       
   386 	else
       
   387 	{
       
   388 		iData=new char [iSize];
       
   389 		if (iData==NULL)
       
   390 			{
       
   391 			iSize=0;
       
   392 			Print(EError, "Out of memory.\n");
       
   393 			}
       
   394 		HMem::Set(iData, 0xff, iSize);
       
   395 	}
       
   396 	iHeader=(TRomHeader *)(iData+sizeof(TRomLoaderHeader));
       
   397 	iExtensionRomHeader=NULL;
       
   398 	iLoaderHeader=(TRomLoaderHeader *)iData;
       
   399 	iSectionPtr=(char *)iHeader+aObey->iSectionStart-aObey->iRomLinearBase+sizeof(TRomSectionHeader);
       
   400 	TheRomHeader=(ImpTRomHeader *)iHeader;
       
   401 	TheRomMem=(TUint32)iHeader;
       
   402 	iNextDataChunkBase=aObey->iKernDataRunAddress;
       
   403 	iTotalSvDataSize=0;
       
   404 	iNextDllDataAddr=aObey->iDllDataTop;
       
   405 	iPrevPrimaryAddress=NULL;
       
   406 	iPrevVariantAddress=NULL;
       
   407 	iVariantFileLists=NULL;
       
   408 	iImportsFixedUp=0;
       
   409 	iBranchesFixedUp=0;
       
   410 	iVtableEntriesFixedUp=0;
       
   411 	iOverhead=0;
       
   412 	}
       
   413 
       
   414 E32Rom::~E32Rom()
       
   415 //
       
   416 // Destructor
       
   417 //
       
   418 	{
       
   419 
       
   420 	if(gLowMem)
       
   421 	{
       
   422 		iImageMap->CloseMemoryMap(ETrue);
       
   423 		delete iImageMap;
       
   424 	}
       
   425 	else
       
   426 		delete iData;
       
   427 	delete [] iPeFiles;
       
   428 	if (iVariantFileLists)
       
   429 		{
       
   430 		TInt i;
       
   431 		for (i=0; i<iObey->iNumberOfVariants; i++)
       
   432 			delete iVariantFileLists[i];
       
   433 		delete [] iVariantFileLists;
       
   434 		}
       
   435 	}
       
   436 
       
   437 TInt E32Rom::Align(TInt aVal)
       
   438 //
       
   439 // Align to romalign
       
   440 //
       
   441 	{
       
   442  	
       
   443 	return ((aVal+iObey->iRomAlign-1)/iObey->iRomAlign)*iObey->iRomAlign;
       
   444 	}
       
   445 
       
   446 TInt E32Rom::LoadContents(char*& anAddr, TRomHeader* aHeader)
       
   447 	{
       
   448 	// Load all the PE/E32Image files
       
   449 	TInt nfiles=iObey->iNumberOfPeFiles;
       
   450 	iPeFiles=new TRomBuilderEntry* [nfiles];
       
   451 	if (!iPeFiles)
       
   452 		return Print(EError, "Out of memory.\n");
       
   453 
       
   454 	TInt r=TranslateFiles();
       
   455 	if (r!=KErrNone)
       
   456 		return r;
       
   457 	
       
   458 	ProcessDllData();
       
   459 
       
   460 	EnumerateVariants();
       
   461 
       
   462 	r=BuildDependenceGraph();
       
   463 	if (r!=KErrNone)
       
   464 		return r;
       
   465 
       
   466 	// Update the ROM image headers with SMP information.
       
   467 	SetSmpFlags();
       
   468 
       
   469 	r=ProcessDependencies();
       
   470 	if (r!=KErrNone)
       
   471 		return r;
       
   472 
       
   473 	char* addr = anAddr;
       
   474 	TRomExceptionSearchTable* exceptionSearchTable = 0;
       
   475 
       
   476 	if(gPagedRom)
       
   477 		{
       
   478 		gDepInfoFile = (char* )malloc(strlen((char *)iObey->iRomFileName) + 1);
       
   479 		strcpy(gDepInfoFile, (char *)iObey->iRomFileName);
       
   480 		iObey->SetArea().DefaultArea()->SortFilesForPagedRom();
       
   481 		// exception search table needs to go at start of ROM to make it not demand paged...
       
   482 		addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable);
       
   483 		}
       
   484 	else if(gGenDepGraph)
       
   485 		{
       
   486 			Print(EWarning, "Not dependence information in an unpaged ROM.");
       
   487 		}
       
   488 
       
   489 	addr=WriteDirectory(addr, aHeader);
       
   490 	// Aligned
       
   491 
       
   492 	TRACE(TSCRATCH,Print(EAlways,"Directory written\n"));
       
   493 
       
   494 	// Stick all the files in ROM
       
   495 
       
   496 	TReloc* relocationTable;
       
   497 	addr = AllocateRelocationTable(addr, relocationTable);
       
   498 	aHeader->iRelocInfo = relocationTable ? ActualToRomAddress(relocationTable) : 0;
       
   499 	// Aligned
       
   500 
       
   501 	TRACE(TSCRATCH,Print(EAlways,"Done AllocateRelocationTable\n"));
       
   502 
       
   503 	CalculateDataAddresses();
       
   504 	addr = LayoutRom(addr);
       
   505 
       
   506 	TRACE(TSCRATCH,Print(EAlways,"Done LayoutRom\n"));
       
   507 
       
   508 	FillInRelocationTable(relocationTable);
       
   509 
       
   510 	TRACE(TSCRATCH,Print(EAlways,"Done FillInRelocationTable\n"));
       
   511 
       
   512 	if(!exceptionSearchTable)
       
   513 		addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable);
       
   514 	ConstructRomExceptionSearchTable(exceptionSearchTable);
       
   515 
       
   516 	TRACE(TSCRATCH,Print(EAlways,"Done ConstructRomExceptionSearchTable\n"));
       
   517 
       
   518 	LinkKernelExtensions(iObey->iExtensions, iObey->iNumberOfExtensions);
       
   519 
       
   520 	TRACE(TSCRATCH,Print(EAlways,"Done LinkKernelExtensions\n"));
       
   521 
       
   522 	r=ResolveDllRefTables();
       
   523 	if (r!=KErrNone)
       
   524 		return r;
       
   525 	r=ResolveImports();
       
   526 	if (r!=KErrNone)
       
   527 		return r;
       
   528 	if (iObey->iCollapseMode>ECollapseNone)
       
   529 		{
       
   530 		r=CollapseImportThunks();
       
   531 		if (r!=KErrNone)
       
   532 			return r;
       
   533 		if (iObey->iCollapseMode>ECollapseImportThunksOnly)
       
   534 			{
       
   535 			r=CollapseBranches();
       
   536 			if (r!=KErrNone)
       
   537 				return r;
       
   538 			}
       
   539 		Print(ELog,"%d imports, %d branches, %d vtable entries fixed up\n",
       
   540 			  iImportsFixedUp,iBranchesFixedUp,iVtableEntriesFixedUp);
       
   541 		}
       
   542 
       
   543 	iSizeUsed=(TInt)addr-(TInt)iHeader;
       
   544 	Print(ELog, "\n%08x of %08x bytes used.\n", iSizeUsed, iSize-sizeof(TRomLoaderHeader));
       
   545 
       
   546 	// round the rom size in the header to a multiple of 1 Megabyte
       
   547 	TInt rounded = ((iSizeUsed+0xfffff)&0xfff00000);
       
   548 	if (rounded < iObey->iRomSize)
       
   549 		iObey->iRomSize = rounded;
       
   550 	iUncompressedSize = iSizeUsed;
       
   551 
       
   552 	anAddr = addr;
       
   553 
       
   554 	return KErrNone;
       
   555 	}
       
   556 
       
   557 
       
   558 void E32Rom::CreatePageIndex(char*& aAddr)
       
   559 	{
       
   560 	iHeader->iRomPageIndex = 0;
       
   561 	if(gPagedRom==0 || gEnableCompress==0)
       
   562 		return;
       
   563 
       
   564 	// Insert space for Rom Page Info table...
       
   565 	iHeader->iRomPageIndex = (TInt)aAddr-(TInt)iHeader;
       
   566 	TInt pageSize = iObey->iPageSize;
       
   567 	TInt numPages = iSize/pageSize+1;
       
   568 	TInt pageInfoSize = numPages*sizeof(SRomPageInfo);
       
   569 	
       
   570 	gPageIndexTableSize = pageInfoSize;		// For accumulate uncompressed un-paged size added Page Index Table
       
   571 		
       
   572 	Print(ELog, "Inserting %d bytes for RomPageInfo at ROM offset 0x%08x\n", pageInfoSize, iHeader->iRomPageIndex);
       
   573 	memset(aAddr,0,pageInfoSize);
       
   574 	iOverhead += pageInfoSize;
       
   575 	aAddr += pageInfoSize;
       
   576 	}
       
   577 
       
   578 TInt E32Rom::SetupPages()
       
   579 	{
       
   580 	iHeader->iPageableRomStart = 0;
       
   581 	iHeader->iPageableRomSize = 0;
       
   582 	iHeader->iDemandPagingConfig = gDemandPagingConfig;
       
   583 
       
   584 	if(!gPagedRom)
       
   585 		return KErrNone;
       
   586 
       
   587 	// Initialise the Rom Page Info for each page which indicates it is uncompressed...
       
   588 	TInt pageSize = iObey->iPageSize;
       
   589 
       
   590 	TInt pagedStartOffset = 0x7fffffff;
       
   591 	TRomBuilderEntry* e = iObey->SetArea().DefaultArea()->iFirstPagedCode;
       
   592 	if(e)
       
   593 		{
       
   594 		// we have paged code...
       
   595 		pagedStartOffset = e->RomEntry()->iAddressLin-iObey->iRomLinearBase;
       
   596 		pagedStartOffset = (pagedStartOffset+pageSize-1)&~(pageSize-1); // round up to next page;
       
   597 		iHeader->iPageableRomStart = pagedStartOffset;
       
   598 		TInt pageableSize = iSizeUsed-pagedStartOffset;
       
   599 		if(pageableSize>0)
       
   600 			iHeader->iPageableRomSize = pageableSize;
       
   601 		}
       
   602 	
       
   603 	return KErrNone;
       
   604 	}
       
   605 
       
   606 TInt E32Rom::CompressPages()
       
   607 	{
       
   608 	
       
   609 	if(!gPagedRom || !gEnableCompress)
       
   610 		return KErrNone;
       
   611 
       
   612 	// Initialise the Rom Page Info for each page which indicates it is uncompressed...
       
   613 	TInt pageSize = iObey->iPageSize;
       
   614 	TInt numPages = (iSizeUsed+pageSize-1)/pageSize;
       
   615 
       
   616 	TInt pagedStartOffset = iHeader->iPageableRomStart;
       
   617 
       
   618 	Print(EAlways, "\nCompressing pages...\n");
       
   619 	TInt inOffset = 0;
       
   620     SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex);
       
   621 	TInt currentIndex = 0;
       
   622 	while(inOffset < pagedStartOffset)
       
   623 		{
       
   624 		
       
   625 		TUint8 attrib = (TUint8)0;
       
   626 		SRomPageInfo info = {(TUint32)inOffset,(TUint16)pageSize,(TUint8)SRomPageInfo::EBytePair,(TUint8)attrib};
       
   627 		info.iDataSize = (TUint16) pageSize;
       
   628 		*pi++ = info;
       
   629 		inOffset += pageSize;
       
   630 		if((currentIndex & 255) == 255)
       
   631 			Print(EAlways, ".\n");
       
   632 		currentIndex++;
       
   633 		}
       
   634 	CompressPageWorker compressworker(this, pageSize, numPages, currentIndex);
       
   635 
       
   636 	boost::thread_group threads;
       
   637 	for(int i = 0; i < gThreadNum; i++)
       
   638 		{
       
   639 		threads.create_thread(compressworker);
       
   640 		}
       
   641 	threads.join_all();
       
   642 	if(compressworker.m_error < 0)
       
   643 	       return compressworker.m_error;
       
   644 	for(;currentIndex < numPages - 1; currentIndex++)
       
   645 		{
       
   646 		pi++;
       
   647 		SRomPageInfo* prev = pi - 1;
       
   648 		TUint8* dest = (TUint8*) iHeader + prev->iDataStart + prev->iDataSize;
       
   649 		TUint8* src = (TUint8*) iHeader + pi->iDataStart;
       
   650 		memcpy(dest, src, pi->iDataSize);
       
   651 		pi->iDataStart = prev->iDataStart + prev->iDataSize;
       
   652 		}
       
   653 	TInt relSize = pi->iDataStart + pi->iDataSize;
       
   654 
       
   655 	memset((TUint8*)iHeader + relSize, 0xff, iSizeUsed - relSize);
       
   656 	TInt compression = (iSizeUsed >= 1000) ? (relSize*10)/(iSizeUsed/1000) : (relSize*10000)/iSizeUsed;
       
   657 	Print(EAlways, "%d.%02d%%\n", compression/100, compression%100);
       
   658 	iSizeUsed = relSize;
       
   659 	return KErrNone;
       
   660 	}
       
   661 
       
   662 TInt E32Rom::CompressPage(SRomPageInfo& aPageInfo, TInt aOutOffset, CBytePair * aBPE)
       
   663 	{
       
   664 	TUint8* in = (TUint8*)iHeader+aPageInfo.iDataStart;
       
   665 	TInt inSize = aPageInfo.iDataSize;
       
   666 	TUint8* out = (TUint8*)iHeader+aOutOffset;
       
   667 	switch(aPageInfo.iCompressionType)
       
   668 		{
       
   669 	case SRomPageInfo::ENoCompression:
       
   670 		memcpy(out,in,inSize);
       
   671 		return inSize;
       
   672 
       
   673 	case SRomPageInfo::EBytePair:
       
   674 		{
       
   675 		TInt r = BytePairCompress(out, in, inSize, aBPE);
       
   676 		if(r!=KErrTooBig)
       
   677 			return r;
       
   678 		// data can't be compressed...
       
   679 		aPageInfo.iCompressionType = SRomPageInfo::ENoCompression;
       
   680 		memcpy(out,in,inSize);
       
   681 		return inSize;
       
   682 		}
       
   683 
       
   684 	default:
       
   685 		Print(EError, "Unsupported page compression type (%d)\n", aPageInfo.iCompressionType);
       
   686 		return KErrNotSupported;
       
   687 		}
       
   688 	}
       
   689 
       
   690 
       
   691 // Avoid "warning" about constant expression
       
   692 static void checksize(const char* aTypeName, int aSize, int aCorrectSize)
       
   693 	{
       
   694 	if (aSize != aCorrectSize)
       
   695 		Print(EError, "sizeof(%s) = %d, should be %d\n", aTypeName, aSize, aCorrectSize);
       
   696 	}
       
   697 
       
   698 TInt E32Rom::CreateExtension(MRomImage* aKernelRom) 
       
   699 	{
       
   700 
       
   701 	// sanity check
       
   702 	checksize("TExtensionRomHeader", sizeof(TExtensionRomHeader), 128);
       
   703 
       
   704 	char *addr=(char *)iHeader;
       
   705 	iExtensionRomHeader=(TExtensionRomHeader*)addr;
       
   706 	addr += sizeof(TExtensionRomHeader);
       
   707 	// Aligned
       
   708 
       
   709 	TRomHeader dummy;
       
   710 	TInt r=LoadContents(addr, &dummy);
       
   711 	if (r!=KErrNone)
       
   712 		{
       
   713 		Print(EError, "LoadContents failed - return code %d\n", r);
       
   714 		return r;
       
   715 		}
       
   716 	iExtensionRomHeader->iRomRootDirectoryList = dummy.iRomRootDirectoryList;
       
   717 
       
   718 	iLoaderHeader->SetUp(iObey);
       
   719 	FinaliseExtensionHeader(aKernelRom);
       
   720 	DisplayExtensionHeader();
       
   721 
       
   722 	return KErrNone;
       
   723 	}
       
   724 	
       
   725 TInt E32Rom::Create()
       
   726 	{
       
   727 
       
   728 	TVariantList::Setup(iObey);
       
   729 	char *addr=(char *)iHeader;
       
   730 	// Aligned
       
   731 
       
   732 	// Put the bootstrap in rom - it contains a hole at offset 0x80 where the 
       
   733 	// TRomHeader information will be placed later
       
   734 
       
   735 	gBootstrapSize = HFile::Read(iObey->iBootFileName, iHeader);
       
   736 	if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
   737 		Print(ELog, "bootstrapSize: 0x%08x, (%d)\n", gBootstrapSize, gBootstrapSize);	
       
   738 	
       
   739 	if (gBootstrapSize==0)
       
   740 		return Print(EError, "Cannot open the bootstrap file '%s'.\n", iObey->iBootFileName);
       
   741 	gBootstrapSize=Align(gBootstrapSize);
       
   742 	addr+=gBootstrapSize;
       
   743 	iOverhead=gBootstrapSize;
       
   744 	// Aligned
       
   745 
       
   746 	CreatePageIndex(addr);
       
   747 
       
   748 	TInt r=LoadContents(addr, iHeader);
       
   749 	if (r!=KErrNone)
       
   750 		{
       
   751 		Print(EError, "LoadContents failed - return code %d\n", r);
       
   752 		return r;
       
   753 		}
       
   754 
       
   755 	r = SetupPages(); // initialize ROM paging info...
       
   756 	if(r!=KErrNone)
       
   757 		{
       
   758 		Print(EError, "Setup pages information failed - return code %d\n", r);
       
   759 		return r;
       
   760 		}
       
   761 	
       
   762 	r = CheckUnpagedMemSize(); // check for unpaged memory overflow
       
   763 	if(r!=KErrNone)
       
   764 	{
       
   765 		return r;
       
   766 	}
       
   767 	
       
   768 	r = CompressPages(); // setup ROM paging info...
       
   769 	if(r!=KErrNone)
       
   770 		{
       
   771 		Print(EError, "CompressPages failed - return code %d\n", r);
       
   772 		return r;
       
   773 		}
       
   774 
       
   775 	iLoaderHeader->SetUp(iObey);
       
   776 	ImpTRomHeader* header = (ImpTRomHeader *)iHeader;
       
   777 	header->SetUp(iObey);
       
   778 	header->iTotalSvDataSize=iTotalSvDataSize;
       
   779 	if (iObey->iMemModel==E_MM_Direct)
       
   780 		{
       
   781 		header->iUserDataAddress=iObey->iDataRunAddress;
       
   782 		header->iTotalUserDataSize=iNextDataChunkBase-iObey->iDataRunAddress;
       
   783 		}
       
   784 	else
       
   785 		{
       
   786 		header->iUserDataAddress=iObey->iDllDataTop;
       
   787 		header->iTotalUserDataSize=iObey->iDllDataTop-iNextDllDataAddr;
       
   788 		}
       
   789 	if (header->iRomSectionHeader)
       
   790 		FinaliseSectionHeader();	// sorts out the second section checksum
       
   791 
       
   792 	header->CheckSum(iObey->iCheckSum);	// finally, sort out the overall checksum
       
   793 
       
   794 	header->Display();
       
   795 
       
   796 	TUint testCheckSum = HMem::CheckSum((TUint *)iHeader, iHeader->iRomSize);
       
   797 	Print(ELog, "Rom 32bit words sum to   %08x\n", testCheckSum);
       
   798 	if (testCheckSum != iObey->iCheckSum)
       
   799 		return Print(EError, "Rom checksum is incorrect: %08x should be %08x\n",
       
   800 					testCheckSum, iObey->iCheckSum);
       
   801 
       
   802 	// 8bit checksum = sum of bytes
       
   803 	// odd/even checksum = checksum of the odd and even halfwords of the image
       
   804 
       
   805 	Print(ELog, "Rom 8bit checksum        %08x\n", HMem::CheckSum8((TUint8 *)iHeader, iHeader->iRomSize));
       
   806 	Print(ELog, "Rom 8bit odd checksum    %08x\n", HMem::CheckSumOdd8((TUint8 *)iHeader, iHeader->iRomSize));
       
   807 	Print(ELog, "Rom 8bit even checksum   %08x\n", HMem::CheckSumEven8((TUint8 *)iHeader, iHeader->iRomSize));
       
   808 
       
   809 	if (iHeader->iPrimaryFile)
       
   810 		{
       
   811 		if (iObey->iKernelModel==ESingleKernel)
       
   812 			{
       
   813 			Print(ELog,"\nPrimary details (Single Kernel):\n");
       
   814 			TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader);
       
   815 			TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader);
       
   816 			Display(hdr);
       
   817 			Print(ELog,"\n");
       
   818 			}
       
   819 		else if (iObey->iKernelModel==EMultipleKernels)
       
   820 			{
       
   821 			Print(ELog,"\nPrimary details (Multiple Kernels):\n");
       
   822 			TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader);
       
   823 			TInt n=1;
       
   824 			FOREVER
       
   825 					{
       
   826 					Print(ELog,"\nKernel %d:\n",n);
       
   827 					TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader);
       
   828 					Display(hdr);
       
   829 					Print(ELog,"\n");
       
   830 					if (!hdr->iNextExtension)
       
   831 						break;
       
   832 					r=(TRomEntry*)(hdr->iNextExtension-iObey->iRomLinearBase+(char*)iHeader);
       
   833 					n++;
       
   834 					}
       
   835 			}
       
   836 		}
       
   837 
       
   838 	return KErrNone;
       
   839 	}
       
   840 
       
   841 char *E32Rom::WriteDirectory(char *aAddr, TRomHeader* aHeader)
       
   842 //
       
   843 // Write the directory structure where appropriate
       
   844 //
       
   845 	{
       
   846 
       
   847 	TLinAddr dirptr=ActualToRomAddress(aAddr);
       
   848 	if (iObey->iSectionPosition==-1)
       
   849 		{
       
   850 		// Just the one rom.  Put the directory structure at aAddr
       
   851 		iDirectorySize=WriteHeadersToRom(aAddr);
       
   852 		aAddr+=Align(iDirectorySize);
       
   853 		}
       
   854 	else
       
   855 		{
       
   856 		// Put the directory structure in the second ROM, after the SectionHeader
       
   857 		// and the second section information for first section files
       
   858 		TInt size=0;
       
   859 		TInt i;
       
   860 		for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
   861 			{
       
   862 			TRomBuilderEntry *file=iPeFiles[i];
       
   863 			if (file->iRomSectionNumber!=0)
       
   864 				break;
       
   865 			TInt size1, size2;
       
   866 			file->SizeInSections(size1,size2);
       
   867 			size+=size2;
       
   868 			}
       
   869 		dirptr=ActualToRomAddress(iSectionPtr)+size;
       
   870 		iDirectorySize=WriteHeadersToRom(RomToActualAddress(dirptr));
       
   871 		}
       
   872 	aHeader->iRomRootDirectoryList=dirptr;
       
   873 	return aAddr;
       
   874 	}
       
   875 
       
   876 void E32Rom::Display(TRomImageHeader *aHdr)
       
   877 //
       
   878 // Print info on a file
       
   879 //
       
   880 	{
       
   881 	TRACE(TAREA, Print(ELog, "+Display header %08x\n", aHdr));
       
   882 	Print(ELog, "Uids:                    %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum);
       
   883 	Print(ELog, "Entry point:             %08x\n", aHdr->iEntryPoint);
       
   884 	Print(ELog, "Code start addr:         %08x\n", aHdr->iCodeAddress);
       
   885 	Print(ELog, "Data start addr:         %08x\n", aHdr->iDataAddress);
       
   886 	Print(ELog, "DataBssLinearBase:       %08x\n", aHdr->iDataBssLinearBase);
       
   887 	Print(ELog, "Text size:               %08x\n", aHdr->iTextSize);
       
   888 	Print(ELog, "Code size:               %08x\n", aHdr->iCodeSize);
       
   889 	Print(ELog, "Data size:               %08x\n", aHdr->iDataSize);
       
   890 	Print(ELog, "BssSize:                 %08x\n", aHdr->iBssSize);
       
   891 	Print(ELog, "Total data size:         %08x\n", aHdr->iTotalDataSize);
       
   892 	Print(ELog, "Heap min:                %08x\n", aHdr->iHeapSizeMin);
       
   893 	Print(ELog, "Heap max:                %08x\n", aHdr->iHeapSizeMax);
       
   894 	Print(ELog, "Stack size:              %08x\n", aHdr->iStackSize);
       
   895 	Print(ELog, "Dll ref table:           %08x\n", aHdr->iDllRefTable);
       
   896 	Print(ELog, "Export directory:        %08x\n", aHdr->iExportDir);
       
   897 	Print(ELog, "Export dir count:        %08x\n", aHdr->iExportDirCount);
       
   898 	Print(ELog, "Hardware variant:        %08x\n", aHdr->iHardwareVariant);
       
   899 	Print(ELog, "Flags:                   %08x\n", aHdr->iFlags);
       
   900 	Print(ELog, "Secure ID:               %08x\n", aHdr->iS.iSecureId);
       
   901 	Print(ELog, "Vendor ID:               %08x\n", aHdr->iS.iVendorId);
       
   902 	Print(ELog, "Capability:              %08x %08x\n", aHdr->iS.iCaps[1], aHdr->iS.iCaps[0]);
       
   903 	Print(ELog, "Tools Version:           %d.%02d(%d)\n", aHdr->iToolsVersion.iMajor, aHdr->iToolsVersion.iMinor, aHdr->iToolsVersion.iBuild);
       
   904 	Print(ELog, "Module Version:          %d.%d\n", aHdr->iModuleVersion>>16, aHdr->iModuleVersion&0x0000ffffu);
       
   905 	Print(ELog, "Exception Descriptor:    %08x\n", aHdr->iExceptionDescriptor);
       
   906 	Print(ELog, "Priority:                %d\n", aHdr->iPriority);
       
   907 	}
       
   908 
       
   909 void E32Rom::DisplaySizes(TPrintType aWhere)
       
   910 	{
       
   911 
       
   912 	Print(aWhere, "Summary of file sizes in rom:\n");
       
   913 	Print(aWhere, "Overhead (bootstrap+gaps+sectioning)\t%d\n", iOverhead);
       
   914 	Print(aWhere, "Overhead (directory size)\t%d\n", iDirectorySize);
       
   915 	TRomBuilderEntry *file=iObey->FirstFile();
       
   916 	while (file)
       
   917 		{
       
   918 		file->DisplaySize(aWhere);
       
   919 		file=iObey->NextFile();
       
   920 		}
       
   921 	Print(aWhere, "\nTotal used\t%d\n", iSizeUsed);
       
   922 	Print(aWhere, "Free\t%d\n", iObey->iRomSize-iSizeUsed);
       
   923 
       
   924 	if (iObey->SetArea().Count() > 1)
       
   925 		{
       
   926 		Print(aWhere, "\nArea summary:\n");
       
   927 		for (NonDefaultAreasIterator it(iObey->SetArea());
       
   928 			 ! it.IsDone();
       
   929 			 it.GoToNext())
       
   930 			{
       
   931 			const Area& a = it.Current();
       
   932 			Print(aWhere, "%s\t used: %d bytes / free: %d bytes\n",
       
   933 				  a.Name(), a.UsedSize(), a.MaxSize()-a.UsedSize());
       
   934 			}
       
   935 		}
       
   936 	}
       
   937 
       
   938 TInt E32Rom::RequiredSize()
       
   939 //
       
   940 // Get the (approximate) required size of the Rom
       
   941 //
       
   942 	{
       
   943 
       
   944 	TInt sum=0;
       
   945 	TRomBuilderEntry *current=iObey->FirstFile();
       
   946 	while (current)
       
   947 		{
       
   948 		if (current->iResource || current->HCRDataFile())
       
   949 			sum+=Align(HFile::GetLength((TText*)current->iFileName));
       
   950 		else
       
   951  			sum+=Align(current->SizeInRom());
       
   952 		current=iObey->NextFile();
       
   953 		}
       
   954 	return sum+iOverhead+Align(iDirectorySize);
       
   955 	}
       
   956 
       
   957 TInt E32Rom::TranslateFiles()
       
   958 //
       
   959 // Load and translate all PE/E32 image files
       
   960 //
       
   961 	{
       
   962 
       
   963 	TInt i=0;
       
   964 	TInt total_errors = 0;
       
   965 	TRomBuilderEntry* current = 0;
       
   966 	EntryQueue imagesQueue;
       
   967 	for (current = iObey->FirstFile(); current; current = iObey->NextFile() )
       
   968 		{	
       
   969 		if ((!current->iResource) && (!current->HCRDataFile()))
       
   970 			{
       
   971 			iPeFiles[i++]=current;
       
   972 			imagesQueue.push(current);
       
   973 			}
       
   974 		}
       
   975 	LoadImageWorker loadworker(&imagesQueue, iObey->iMemModel);
       
   976 	boost::thread_group threads;
       
   977 	for(int i = 0; i < gThreadNum; i++)
       
   978 		{
       
   979 		threads.create_thread(loadworker);
       
   980 		}
       
   981 	threads.join_all();
       
   982 
       
   983 	total_errors = loadworker.m_errors;
       
   984 	if (total_errors)
       
   985 		return KErrGeneral;
       
   986 	for (current = iObey->FirstFile(); current; current = iObey->NextFile() )
       
   987 		{
       
   988 		if ((!current->iResource) && (!current->HCRDataFile()))
       
   989 			{
       
   990 			TInt err = CheckForVersionConflicts(current);
       
   991 			total_errors += err;
       
   992 			}
       
   993 		}
       
   994 	return total_errors ? KErrGeneral : KErrNone;
       
   995 	}
       
   996 
       
   997 const TText FileTypeFile[]=		"File     ";
       
   998 const TText FileTypePrimary[]=	"Primary  ";
       
   999 const TText FileTypeVariant[]=	"Variant  ";
       
  1000 const TText FileTypeExtension[]="Extension";
       
  1001 const TText FileTypeDevice[]=	"Device   ";
       
  1002 
       
  1003 void E32Rom::EnumerateVariants()
       
  1004 	{
       
  1005 	TInt vIndex;
       
  1006 	TInt nFiles=iObey->iNumberOfExtensions+iObey->iNumberOfDevices+3;
       
  1007 	iVariantFileLists=new COrderedFileList*[iObey->iNumberOfVariants];
       
  1008 	for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
       
  1009 		iVariantFileLists[vIndex]=COrderedFileList::New(nFiles);
       
  1010 	for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
       
  1011 		{
       
  1012 		TRomBuilderEntry *variant=iObey->iVariants[vIndex];
       
  1013 		THardwareVariant& v=variant->iHardwareVariant;
       
  1014 		TInt i;
       
  1015 		for (i=0; i<iObey->iNumberOfPrimaries; i++)
       
  1016 			{
       
  1017 			TRomBuilderEntry *primary=iObey->iPrimaries[i];
       
  1018 			if (v<=primary->iHardwareVariant)
       
  1019 				{
       
  1020 				iVariantFileLists[vIndex]->Add(primary);
       
  1021 				break;
       
  1022 				}
       
  1023 			}
       
  1024 		iVariantFileLists[vIndex]->Add(variant);
       
  1025 		for (i=0; i<iObey->iNumberOfExtensions; i++)
       
  1026 			{
       
  1027 			TRomBuilderEntry *ext=iObey->iExtensions[i];
       
  1028 			if (v<=ext->iHardwareVariant)
       
  1029 				{
       
  1030 				iVariantFileLists[vIndex]->Add(ext);
       
  1031 				}
       
  1032 			}
       
  1033 		for (i=0; i<iObey->iNumberOfDevices; i++)
       
  1034 			{
       
  1035 			TRomBuilderEntry *dev=iObey->iDevices[i];
       
  1036 			if (v<=dev->iHardwareVariant)
       
  1037 				{
       
  1038 				iVariantFileLists[vIndex]->Add(dev);
       
  1039 				}
       
  1040 			}
       
  1041 		}
       
  1042 	TUint totalDataBss=0;
       
  1043 	for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
       
  1044 		{
       
  1045 		TRomBuilderEntry *variant=iObey->iVariants[vIndex];
       
  1046 		THardwareVariant& v=variant->iHardwareVariant;
       
  1047 		COrderedFileList& files=*iVariantFileLists[vIndex];
       
  1048 		TInt count=files.Count();
       
  1049 		Print(ELog,"\nVariant %08x, %d Files:\n",v.ReturnVariant(),count); 
       
  1050 		TInt i;
       
  1051 		TUint dataOffset=0;
       
  1052 		for (i=0; i<count; i++)
       
  1053 			{
       
  1054 			TRomBuilderEntry *pF=files[i];
       
  1055 			TUint gap=0;
       
  1056 			if (pF->iDataAlignment>0)
       
  1057 				{
       
  1058 				gap=(pF->iDataAlignment-dataOffset)%(pF->iDataAlignment);
       
  1059 				dataOffset+=gap;
       
  1060 				}
       
  1061 			E32ImageHeader *pH=pF->iHdr;
       
  1062 			if (pF->iDataBssOffset!=0xffffffff && pF->iDataBssOffset!=dataOffset)
       
  1063 				Print(EError,"Conflicting DataBss addresses\n");
       
  1064 			pF->iDataBssOffset=dataOffset;
       
  1065 			TInt dataSize=AlignData(pH->iDataSize+pH->iBssSize);
       
  1066 			const TText* pT=FileTypeFile;
       
  1067 			if (pF->Primary())
       
  1068 				pT=FileTypePrimary;
       
  1069 			if (pF->Variant())
       
  1070 				pT=FileTypeVariant;
       
  1071 			if (pF->Extension())
       
  1072 				pT=FileTypeExtension;
       
  1073 			if (pF->Device())
       
  1074 				pT=FileTypeDevice;
       
  1075 			Print(ELog,"%s %12s[%08x] DataSize=%6x DataOffset=%6x",pT,pF->iName,pF->iHardwareVariant.ReturnVariant(),dataSize,dataOffset);
       
  1076 			if (gap)
       
  1077 				Print(ELog, " (gap %x for %x alignment)\n", gap, pF->iDataAlignment);
       
  1078 			Print(ELog, "\n");
       
  1079 			dataOffset+=dataSize;
       
  1080 			}
       
  1081 		if (dataOffset>totalDataBss)
       
  1082 			totalDataBss=dataOffset;
       
  1083 		}
       
  1084 	Print(ELog,"\nTotal SvData size=%6x\n",totalDataBss);
       
  1085 	iTotalSvDataSize=totalDataBss;
       
  1086 	}
       
  1087 
       
  1088 TInt E32Rom::LoadDataToRom(TRomBuilderEntry *aFile, TAddressRange& aAddress, CBytePair* aBPE)
       
  1089 //
       
  1090 // Load a data file to rom
       
  1091 //
       
  1092 	{
       
  1093 	const char* tn = "resource";
       
  1094 	if (aFile->iNonXIP)
       
  1095 		tn = (aFile->iCompression) ? "compressed executable" : "uncompressed executable";
       
  1096 	Print(ELog,"Reading %s %s to rom linear address %08x\n", tn, aFile->iFileName, aAddress.iImageAddr);
       
  1097 
       
  1098 	TUint32 size=HFile::GetLength((TText*)aFile->iFileName);
       
  1099 	if (size==0)
       
  1100 		{
       
  1101 		Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",aFile->iFileName);
       
  1102 		return size;
       
  1103 		}
       
  1104 
       
  1105 	aFile->iHeaderRange=aAddress;
       
  1106 	char* addr = (char*)aFile->iHeaderRange.iImagePtr;
       
  1107 	const char* src = NULL;
       
  1108 	#ifdef __TOOLS2__
       
  1109 	ostringstream os;
       
  1110 	#else
       
  1111 	ostrstream os;
       
  1112 	#endif
       
  1113 	if (aFile->iNonXIP)
       
  1114 		{
       
  1115 		E32ImageFile f(aBPE);
       
  1116 		TInt r = f.Open(aFile->iFileName);
       
  1117 		// is it really a valid E32ImageFile?
       
  1118 		if (r != KErrNone)
       
  1119 			{
       
  1120 			Print(EWarning, "File '%s' is not a valid executable.  Loading file as data.\n", aFile->iFileName);
       
  1121 			aFile->iNonXIP = EFalse;
       
  1122 			}
       
  1123 		else
       
  1124 			{
       
  1125 			TUint compression = f.iHdr->CompressionType();
       
  1126 			if (compression != aFile->iCompression || aFile->iPreferred)
       
  1127 				{
       
  1128 				if (compression == 0)
       
  1129 					Print(ELog, "Compressing file %s\n", aFile->iFileName);
       
  1130 				else if (aFile->iCompression == 0)
       
  1131 					Print(ELog, "Decompressing file %s\n", aFile->iFileName);
       
  1132 				f.iHdr->iCompressionType = aFile->iCompression;
       
  1133 				if (aFile->iPreferred)
       
  1134 					{
       
  1135 					f.iHdr->iModuleVersion &= ~0xffffu;
       
  1136 					f.iHdr->iModuleVersion |= 0x8000u;
       
  1137 					}
       
  1138 				f.UpdateHeaderCrc();
       
  1139 				}
       
  1140 			Print(ELog, "Compression Method:0x%08x/0x%08x \n", f.iHdr->CompressionType(), aFile->iCompression);
       
  1141 			os << f;
       
  1142 			#ifdef __TOOLS2__
       
  1143 			size = (os.str()).length(); 
       
  1144 			src = (os.str()).c_str();
       
  1145 			#else
       
  1146 			size = os.pcount();
       
  1147 			src = os.str();
       
  1148 			#endif
       
  1149 			}
       
  1150 		}
       
  1151 	if (addr+size>iData+iSize)
       
  1152 		{
       
  1153 		Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName);
       
  1154 		Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize);
       
  1155 		exit(667);
       
  1156 		}
       
  1157 	if (src)
       
  1158 		memcpy(addr, src, size);
       
  1159 	else
       
  1160 		size = HFile::Read((TText*)aFile->iFileName, (TAny *)addr);
       
  1161 	Print(ELog,"Size:                    %08x\n", size);
       
  1162 
       
  1163 	aFile->iHeaderRange.iSize=size;
       
  1164 	aAddress.Extend(aFile->iHeaderRange.iSize);
       
  1165 	return size;
       
  1166 	}
       
  1167 
       
  1168 
       
  1169 void E32Rom::CalculateDataAddresses()
       
  1170 //
       
  1171 //
       
  1172 //
       
  1173 	{
       
  1174 
       
  1175 	TInt i;
       
  1176 	TUint32 maxkern = 0;
       
  1177 	Print(ELog, "\nCalculating kernel limit.\n");
       
  1178 	for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1179 		{
       
  1180 		TRomBuilderEntry* e = iPeFiles[i];
       
  1181 		if (e->Primary())
       
  1182 			{
       
  1183 			// this is a kernel
       
  1184 			TUint32 stack = AlignToPage(e->iHdr->iStackSize);
       
  1185 			TUint32 heap = AlignToPage(e->iHdr->iHeapSizeMax);
       
  1186 			if (stack + heap > maxkern)
       
  1187 				maxkern = stack + heap;
       
  1188 			}
       
  1189 		}
       
  1190 	iObey->iKernelLimit = AlignToChunk(maxkern + iTotalSvDataSize) + iObey->iKernDataRunAddress;
       
  1191 	if (iObey->iMemModel==E_MM_Direct)
       
  1192 		iNextDataChunkBase=iObey->iDataRunAddress;
       
  1193 	else
       
  1194 		iNextDataChunkBase = iObey->iKernelLimit;
       
  1195 	Print(ELog, "\nCalculating data addresses.\n");
       
  1196 	for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1197 		{
       
  1198 		TRACE(TAREA,Print(ELog,"CalculateDataAddresses %d %s\n",i,iPeFiles[i]->iFileName));
       
  1199 		CalculateDataAddress(iPeFiles[i]);
       
  1200 		}
       
  1201 	TRACE(TIMPORT,Print(ELog,"CalculateDataAddresses complete\n"));
       
  1202 
       
  1203 	// On moving model, advance kernel limit past fixed process data areas
       
  1204 	if (iObey->iMemModel==E_MM_Moving)
       
  1205 		iObey->iKernelLimit = iNextDataChunkBase;
       
  1206 	}
       
  1207 
       
  1208 void E32Rom::CalculateDataAddress(TRomBuilderEntry *aFile)
       
  1209 //
       
  1210 // Work out where the .data/.bss will be
       
  1211 //
       
  1212 	{
       
  1213 	TUint32 dataBssSize=aFile->iRomNode->iRomFile->iTotalDataBss;
       
  1214 	TUint32 dataRunAddr;
       
  1215 	if (aFile->Primary())
       
  1216 		{
       
  1217 		dataRunAddr = iObey->iKernDataRunAddress;
       
  1218 		CPU = aFile->iHdr->CpuIdentifier();
       
  1219 		}
       
  1220 	else
       
  1221 		{
       
  1222 		dataRunAddr = iObey->iDataRunAddress;
       
  1223 		if (iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible && (aFile->iHdr->iFlags & KImageFixedAddressExe))	// propagate 'fixed' from PETRAN
       
  1224 			{
       
  1225 			dataRunAddr=0xffffffff;
       
  1226 			}
       
  1227 		}
       
  1228 	if (aFile->iOverrideFlags&KOverrideAddress)
       
  1229 		{
       
  1230 		if ((iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible) || aFile->iRelocationAddress!=0xffffffff)
       
  1231 			dataRunAddr=aFile->iRelocationAddress;
       
  1232 		if (aFile->Extension() || aFile->Variant() || aFile->Device())
       
  1233 			Print(EError, "reloc not permitted with extension/variant/device\n");
       
  1234 		}
       
  1235 	if (!aFile->IsDll() && !aFile->Primary() && (dataRunAddr==0xffffffff || iObey->iMemModel==E_MM_Direct))
       
  1236 		{
       
  1237 		dataRunAddr=iNextDataChunkBase;
       
  1238 		TInt stackreserve=iObey->iDefaultStackReserve;
       
  1239 		if (aFile->iOverrideFlags & KOverrideStackReserve)
       
  1240 			stackreserve=aFile->iStackReserve;
       
  1241 		TInt datsize=AlignToChunk(dataBssSize+stackreserve);
       
  1242 		// Move target data address to next free chunk
       
  1243 		iNextDataChunkBase+=datsize;
       
  1244 		}
       
  1245 	if (aFile->Extension() || aFile->Device() || aFile->Variant())
       
  1246 		{
       
  1247 		dataRunAddr=iObey->iKernDataRunAddress+aFile->iDataBssOffset;
       
  1248 		}
       
  1249 	else if (aFile->IsDll() && dataBssSize!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe<0)
       
  1250 		{
       
  1251 		iNextDllDataAddr = AllocVirtual(iNextDllDataAddr,dataBssSize);
       
  1252 		dataRunAddr=iNextDllDataAddr;
       
  1253 		}
       
  1254 	if (iObey->iMemModel==E_MM_Moving && dataRunAddr==iObey->iDataRunAddress && aFile->Secondary())
       
  1255 		{
       
  1256 		Print(EWarning,"Secondary not fixed\n");
       
  1257 		}
       
  1258 
       
  1259 	TRACE(TAREA, Print(ELog, "Data run address %08x\n", dataRunAddr));
       
  1260 	aFile->iDataBssLinearBase=dataRunAddr;
       
  1261 	}
       
  1262 
       
  1263 void E32Rom::LoadFileToRom(TRomBuilderEntry *aFile)
       
  1264 //
       
  1265 // Load an E32Image/PE file to rom
       
  1266 //
       
  1267 	{
       
  1268 
       
  1269 	char* addr = (char*)aFile->iHeaderRange.iImagePtr;
       
  1270 	TRACE(TAREA, Print(ELog,"+LoadFileToRom addr %08x %08x %08x\n", addr,
       
  1271 					   aFile->iHeaderRange.iImageAddr, aFile->iHeaderRange.iRunAddr));
       
  1272 
       
  1273 	if (addr+aFile->SizeInRom()>iData+iSize) // check this
       
  1274 		{
       
  1275 		Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName);
       
  1276 		Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize);
       
  1277 		exit(666);
       
  1278 		}
       
  1279 
       
  1280 	// check file will not overflow into next ROM
       
  1281 	if (aFile->Primary())
       
  1282 		{
       
  1283 		if (!iPrevPrimaryAddress)
       
  1284 			iHeader->iPrimaryFile=ActualToRomAddress(aFile->RomEntry());
       
  1285 		else if (iObey->iKernelModel==EMultipleKernels)
       
  1286 			{
       
  1287 			((TRomImageHeader*)iPrevPrimaryAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry());
       
  1288 			}
       
  1289 		iPrevPrimaryAddress=addr;
       
  1290 		TRACE(TAREA, Print(ELog, "iHeader->iPrimaryFile = %08x\n", iHeader->iPrimaryFile));
       
  1291 		}
       
  1292 
       
  1293 	// Place the file in rom
       
  1294 	if (aFile->Variant())
       
  1295 		{
       
  1296 		if (iPrevVariantAddress)
       
  1297 			((TRomImageHeader*)iPrevVariantAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry());
       
  1298 		else
       
  1299 			iHeader->iVariantFile=ActualToRomAddress(aFile->RomEntry());
       
  1300 		iPrevVariantAddress=addr;
       
  1301 		}
       
  1302 	if (aFile->IsDll() && aFile->iRomNode->iRomFile->iTotalDataBss!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe>=0)
       
  1303 		{
       
  1304 		TRomFile* f=aFile->iRomNode->iRomFile->iPDeps[0];	// attach process
       
  1305 		aFile->iDataBssLinearBase = f->DataBssLinearBase() + aFile->iRomNode->iRomFile->iDataBssOffsetInExe;
       
  1306 		}
       
  1307 
       
  1308 	aFile->LoadToRom();
       
  1309 	}
       
  1310 
       
  1311 char *E32Rom::LayoutRom(char *romaddr)
       
  1312 //
       
  1313 // Layout the files from the obey file starting at romaddr in the image
       
  1314 // dealing correctly with areas
       
  1315 // Also deals with two section ROMs
       
  1316 //
       
  1317 	{
       
  1318 
       
  1319 	TAddressRange main;
       
  1320 	TAddressRange* mainptr=&main;
       
  1321 	SetImageAddr(main, romaddr);
       
  1322 
       
  1323 	TAddressRange second;
       
  1324 	TAddressRange* secondptr=0;
       
  1325 	if (iObey->iSectionStart != 0)
       
  1326 		{
       
  1327 		SetImageAddr(second,iSectionPtr);
       
  1328 		secondptr = &second;
       
  1329 		}
       
  1330 
       
  1331 	TInt fileCount=0;
       
  1332 
       
  1333 	//
       
  1334 	// Process files in non default areas
       
  1335 	//
       
  1336 
       
  1337         CBytePair bpe(gFastCompress);
       
  1338 	for (NonDefaultAreasIterator areaIt(iObey->SetArea());
       
  1339 		 ! areaIt.IsDone();
       
  1340 		 areaIt.GoToNext())
       
  1341 		{
       
  1342 		Area& currentArea = areaIt.Current();
       
  1343 		currentArea.SetSrcBaseAddr(mainptr->iImageAddr);
       
  1344 
       
  1345 		mainptr->iRunAddr = currentArea.DestBaseAddr();
       
  1346 
       
  1347 		for (FilesInAreaIterator fileIt(currentArea);
       
  1348 			 ! fileIt.IsDone();
       
  1349 			 fileIt.GoToNext())
       
  1350 			{
       
  1351 			TRomBuilderEntry* currentFile = fileIt.Current();
       
  1352 
       
  1353 			LayoutFile(currentFile, *mainptr, secondptr, &bpe);
       
  1354 		
       
  1355 			TUint overflow;
       
  1356 			if (! currentArea.ExtendSrcLimitAddr(mainptr->iImageAddr, overflow))
       
  1357 				{
       
  1358 				Print(EError, "Can't fit '%s' in area '%s'\n", currentFile->iFileName, currentArea.Name());
       
  1359 				Print(EError, "Area overflowed by 0x%x bytes.\n", overflow);
       
  1360 				exit(666);
       
  1361 				}
       
  1362 
       
  1363 			++fileCount;
       
  1364 			assert(iObey->iSectionPosition == -1 || fileCount < iObey->iSectionPosition);
       
  1365 			}
       
  1366 
       
  1367 		TInt offset=(char*)mainptr->iImagePtr-romaddr;
       
  1368 		mainptr->Extend(Align(offset)-offset);
       
  1369 		} // for every non default area
       
  1370 
       
  1371 
       
  1372 	//
       
  1373 	// Process files in default area
       
  1374 	//
       
  1375 
       
  1376 	mainptr->iRunAddr = mainptr->iImageAddr;
       
  1377 
       
  1378 	for (FilesInAreaIterator fileIt(*(iObey->SetArea().DefaultArea()));
       
  1379 		 ! fileIt.IsDone();
       
  1380 		 fileIt.GoToNext())
       
  1381 		{
       
  1382 		if (fileCount==iObey->iSectionPosition)
       
  1383 			{
       
  1384 			// skip rest of first section and pick up after the
       
  1385 			// information already accumulated in the second section
       
  1386 			NextRom(mainptr, secondptr);
       
  1387 			mainptr = secondptr;
       
  1388 			secondptr = 0;
       
  1389 			}
       
  1390 
       
  1391 		LayoutFile(fileIt.Current(), *mainptr, secondptr, &bpe);
       
  1392 
       
  1393 		++fileCount;
       
  1394 		}
       
  1395 
       
  1396 	// align to likely position of next file
       
  1397 	TInt offset=(char*)mainptr->iImagePtr-romaddr;
       
  1398 	offset = Align(offset)-offset;
       
  1399 	mainptr->Extend(offset);
       
  1400 	iOverhead +=offset;
       
  1401 
       
  1402 	return (char*)mainptr->iImagePtr;
       
  1403  	}
       
  1404 
       
  1405 void E32Rom::LayoutFile(TRomBuilderEntry* current, TAddressRange& aMain, TAddressRange* aSecond, CBytePair * aBPE)
       
  1406 //
       
  1407 // Work out where to place a file in ROM and set up the 
       
  1408 // appropriate TAddressRange information
       
  1409 //
       
  1410 	{
       
  1411 	TInt alignment = iObey->iRomAlign;
       
  1412 	if (current->iAlignment > alignment)
       
  1413 		alignment = current->iAlignment;
       
  1414 
       
  1415 	if (alignment)
       
  1416 		{
       
  1417 		// Align this file on a boundary
       
  1418 		TUint32 romaddr=aMain.iRunAddr;
       
  1419 		TInt i=romaddr & (alignment-1);
       
  1420 		TInt gap=0;
       
  1421 		if (i!=0)
       
  1422 			gap=alignment-i;
       
  1423 		if (current->iAlignment)
       
  1424 			Print(ELog, "\nAlign to %08x.  Skipped %d bytes\n", romaddr+gap, gap);
       
  1425 		aMain.Extend(gap);
       
  1426 		iOverhead += gap;
       
  1427 		}
       
  1428 
       
  1429 	if (current->iCodeAlignment != 0)
       
  1430 		{
       
  1431 		TUint32 runaddr=aMain.iRunAddr + sizeof(TRomImageHeader);
       
  1432 		TInt i=runaddr & (current->iCodeAlignment-1);
       
  1433 		TInt gap=0;
       
  1434 		if (i!=0)
       
  1435 			gap=current->iCodeAlignment-i;
       
  1436 		Print(ELog, "\nCode Align to %08x.  Skipped %d bytes\n", runaddr+gap, gap);
       
  1437 		aMain.Extend(gap);
       
  1438 		iOverhead += gap;
       
  1439 		}
       
  1440 
       
  1441 	Print(ELog,"\n********************************************************************\n");
       
  1442 
       
  1443 	if (current->iPatched)
       
  1444 		Print(ELog, "[Patched file]\n");
       
  1445 
       
  1446 	if (current->iResource)
       
  1447 		{
       
  1448 		TInt size=LoadDataToRom(current, aMain, aBPE);
       
  1449 		if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
       
  1450 			return;		// first section has overflowed
       
  1451 		current->FixupRomEntries(size);
       
  1452 		return;
       
  1453 		}
       
  1454 	if(current->HCRDataFile()){	
       
  1455 		TInt size=LoadDataToRom(current, aMain, aBPE);		
       
  1456 		if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
       
  1457 			return;		// first section has overflowed
       
  1458 		current->FixupRomEntries(size);
       
  1459 		iHeader->iHcrFileAddress =  current->iHeaderRange.iImageAddr ;
       
  1460 		TRACE(TAREA, Print(ELog, "iHeader->iHcrFileAddress = %08x\n", iHeader->iHcrFileAddress));		 
       
  1461 		return ;
       
  1462 	}
       
  1463 	Print(ELog,"Processing file %s\n",current->iFileName);
       
  1464 
       
  1465 	if (current->Primary())
       
  1466 		{
       
  1467 		Print(ELog, "[Primary]\n");
       
  1468 		}
       
  1469 
       
  1470 	if (current->Secondary())
       
  1471 		{
       
  1472 		iHeader->iSecondaryFile=ActualToRomAddress(current->RomEntry());
       
  1473 		Print(ELog, "[Secondary]\n");
       
  1474 		}
       
  1475 
       
  1476 	// Section 1 things
       
  1477 	//
       
  1478 	// TRomImageHeader, text, export directory, data
       
  1479 
       
  1480 	aMain.Append(current->iHeaderRange);
       
  1481 	aMain.Append(current->iCodeSection);
       
  1482 	aMain.Append(current->iDataSection);
       
  1483 
       
  1484 	// section 2 things
       
  1485 	//
       
  1486 	// dll ref table
       
  1487 
       
  1488 	if (aSecond != 0)
       
  1489 		{
       
  1490 		// two section ROM - split image between both sections
       
  1491 		aSecond->Append(current->iExportDirSection);
       
  1492 		aSecond->Append(current->iDllRefTableRange);
       
  1493 		}
       
  1494 	else
       
  1495 		{
       
  1496 		// default placement in first section
       
  1497 		aMain.Append(current->iExportDirSection);
       
  1498 		aMain.Append(current->iDllRefTableRange);
       
  1499 		}
       
  1500 
       
  1501 	TInt section1size = aMain.iRunAddr-current->iCodeSection.iRunAddr;
       
  1502 
       
  1503 	if (aMain.iRunAddr == aMain.iImageAddr)
       
  1504 		{
       
  1505 		Print(ELog, "Load Address:            %08x\n", current->iHeaderRange.iImageAddr);
       
  1506 		}
       
  1507 	else
       
  1508 		{
       
  1509 		Print(ELog, "Rom Address:             %08x\n", current->iHeaderRange.iImageAddr);
       
  1510 		Print(ELog, "Area Address:            %08x\n", current->iHeaderRange.iRunAddr);
       
  1511 		}
       
  1512 	Print(ELog,     "Size:                    %08x\n", section1size);
       
  1513 
       
  1514 	if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
       
  1515 		return;		// first section has overflowed
       
  1516 
       
  1517 	LoadFileToRom(current);
       
  1518 	Display(current->iRomImageHeader);
       
  1519 	Print(ELog,     "Dll ref table size:      %08x\n", current->iDllRefTableRange.iSize);
       
  1520 	Print(ELog,     "Compression:             %08x\n", current->iCompression);
       
  1521 	Print(ELog,     "\n");
       
  1522 
       
  1523 	current->FixupRomEntries(section1size);	
       
  1524 	}
       
  1525 
       
  1526 static int CompareAddresses(const void * arg1, const void * arg2) 
       
  1527 	{ 
       
  1528 	return (* (TUint32 *)arg1) < (* (TUint32 *)arg2) ? -1: 1; 
       
  1529 	}
       
  1530 
       
  1531 char *E32Rom::ReserveRomExceptionSearchTable(char *anAddr, TRomExceptionSearchTable*& exceptionSearchTable)
       
  1532 	{
       
  1533 	TRomExceptionSearchTable *pT = (TRomExceptionSearchTable *)anAddr;
       
  1534 	exceptionSearchTable = pT;
       
  1535 	if (iExtensionRomHeader)
       
  1536 		{
       
  1537 		iExtensionRomHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr);
       
  1538 		}
       
  1539 	else
       
  1540 		{
       
  1541 		iHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr);
       
  1542 		}
       
  1543 	TLinAddr * addr = &pT->iEntries[0];
       
  1544 	int numEntries = 0;
       
  1545 	int errors = 0;
       
  1546 	// Count number of entries needed
       
  1547 	for (int i = 0; i < iObey->iNumberOfPeFiles; i++)
       
  1548 		{
       
  1549 		TUint32 xd = iPeFiles[i]->iHdr->iExceptionDescriptor;
       
  1550 		if ((xd & 1) && (xd != 0xffffffffu))
       
  1551 			{
       
  1552 			numEntries++;
       
  1553 			}
       
  1554 		else if (!iPeFiles[i]->iHdr->iExceptionDescriptor)
       
  1555 			{
       
  1556 #ifdef __REJECT_NON_EXCEPTION_AWARE_BINARIES__
       
  1557 			Print(EError, "Executable not exception aware: %s\n", iPeFiles[i]->iName);
       
  1558 			errors++;
       
  1559 #else
       
  1560 			Print(ELog, "Executable not exception aware: %s\n", iPeFiles[i]->iName);
       
  1561 #endif
       
  1562 			}
       
  1563 		}
       
  1564 	if (errors > 0) exit(666);
       
  1565 	// NB we add one to numEntries to allow space for a fencepost value (see below for more)
       
  1566 	int spaceNeeded = sizeof(pT->iNumEntries) + sizeof(pT->iEntries[0])*(numEntries+1);
       
  1567 	int delta = (int)(addr+spaceNeeded) - (int)(iData+iSize);
       
  1568 	// Check we've got enough room
       
  1569 	if (delta > 0)
       
  1570 		{
       
  1571 		Print(EError, "Can't fit Rom Exception Search Table in Rom.\n");
       
  1572 		Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", delta);
       
  1573 		exit(666);
       
  1574 		}
       
  1575 	pT->iNumEntries = numEntries;
       
  1576 	return anAddr+spaceNeeded;
       
  1577 	}
       
  1578 	
       
  1579 void E32Rom::ConstructRomExceptionSearchTable(TRomExceptionSearchTable* exceptionSearchTable)
       
  1580 	{
       
  1581 	TRomExceptionSearchTable *pT = exceptionSearchTable;
       
  1582 	TLinAddr * addr = &pT->iEntries[0];
       
  1583 	// Initialize the table
       
  1584 	int numEntries = pT->iNumEntries;
       
  1585 	TLinAddr fencepost = 0xffffffff;
       
  1586 	if (numEntries)
       
  1587 		{
       
  1588 		TLinAddr fp = 0;
       
  1589 		for (int j = 0; j < iObey->iNumberOfPeFiles; j++)
       
  1590 			{
       
  1591 			TUint32 xd = iPeFiles[j]->iHdr->iExceptionDescriptor;
       
  1592 			if ((xd & 1) && (xd != 0xffffffff))
       
  1593 				{
       
  1594 				// mask out bottom bit set by ELFTRAN.
       
  1595 				xd &= ~1;
       
  1596 				*addr++ = iPeFiles[j]->iHdr->iCodeBase;
       
  1597 				TLinAddr aEDAddr = iPeFiles[j]->iHdr->iCodeBase + xd; 
       
  1598 				// Keep track of greatest code limit so we can use it as the fencepost value
       
  1599 				TExceptionDescriptor * aEDp = (TExceptionDescriptor *)RomToActualAddress(aEDAddr);
       
  1600 				TLinAddr codeLimit = aEDp->iROSegmentLimit;
       
  1601 				if (codeLimit>fp) fp=codeLimit;
       
  1602 				}
       
  1603 			}
       
  1604 		if (fp) fencepost=fp;
       
  1605 		// now check they're in order (they should be).
       
  1606 		int inOrder = 1;
       
  1607 		for (int k=numEntries-1;inOrder && k; k--) 
       
  1608 			{
       
  1609 			inOrder = pT->iEntries[k]>pT->iEntries[k-1]?1:0;
       
  1610 			}
       
  1611 
       
  1612 		if (!inOrder)
       
  1613 			{
       
  1614 			Print(ELog, "Sorting Rom Exception Table.\n");
       
  1615 			qsort(&pT->iEntries[0],numEntries,sizeof(pT->iEntries[0]), CompareAddresses);
       
  1616 			}
       
  1617 		}
       
  1618 	/*
       
  1619 	  Add the fencepost value at the end of the table. This is used to optimize the comparison
       
  1620 	  function passed to bsearch when retrieving values from the search table. It also allows a certain
       
  1621 	  amount of error checking on lookup keys.
       
  1622 	*/
       
  1623 	*addr++ = fencepost;
       
  1624 	}
       
  1625 
       
  1626 void TRomBuilderEntry::SizeInSections(TInt& aSize1, TInt& aSize2)
       
  1627 //
       
  1628 // Exact size of the upper & lower section information
       
  1629 // lower = text + data
       
  1630 // upper = export directory + dllref table
       
  1631 //
       
  1632 	{
       
  1633 	aSize1  = iHeaderRange.iSize;
       
  1634 	aSize1 += iCodeSection.iSize;			// text (including rdata)
       
  1635 	aSize1 += iDataSection.iSize;			// static data
       
  1636 
       
  1637 	aSize2  = iExportDirSection.iSize;		// export directory
       
  1638 	aSize2 += iDllRefTableRange.iSize;	// DLL ref table
       
  1639 	}
       
  1640 
       
  1641 							
       
  1642 void E32Rom::NextRom(TAddressRange* aFirst, TAddressRange* aSecond)
       
  1643 //
       
  1644 // Move on to the next Rom bank, taking the IATs with us
       
  1645 //
       
  1646 	{
       
  1647 
       
  1648 	Print(ELog,"\n####################################################################\n");
       
  1649 	TInt gap=iObey->iSectionStart-aFirst->iImageAddr;
       
  1650 	if (gap<0)
       
  1651 		{
       
  1652 		Print(EError, "First section overflowed by %08x bytes\n", -gap);
       
  1653 		exit(669);
       
  1654 		}
       
  1655 	iOverhead+=gap+sizeof(TRomSectionHeader);
       
  1656 	Print(ELog, "[Next rom section]\n");
       
  1657 	Print(ELog, "Skipping %08x bytes\n", gap);
       
  1658 	Print(ELog, "LinAddr:                 %08x\n", iObey->iSectionStart);
       
  1659 	Print(ELog, "First section tables:    %08x\n", iObey->iSectionStart+sizeof(TRomSectionHeader));
       
  1660 	TInt size=aSecond->iImageAddr-iObey->iSectionStart;
       
  1661 	Print(ELog, "Tables size:             %08x\n", size-sizeof(TRomSectionHeader));
       
  1662 	Print(ELog, "Rom Directory            %08x\n", iHeader->iRomRootDirectoryList);
       
  1663 	Print(ELog, "Rom Directory size       %08x\n", iDirectorySize);
       
  1664 
       
  1665 	if (aSecond->iImageAddr != iHeader->iRomRootDirectoryList)
       
  1666 		{
       
  1667 		Print(EError, "Second section has overwritten the Rom directory\n");
       
  1668 		exit(669);
       
  1669 		}
       
  1670 	aSecond->Extend(iDirectorySize);
       
  1671 
       
  1672 	Print(ELog, "\n");
       
  1673 	}
       
  1674 
       
  1675 TInt E32Rom::ResolveDllRefTables()
       
  1676 //
       
  1677 //
       
  1678 //
       
  1679 	{
       
  1680 
       
  1681 	Print(ELog, "\nResolving Dll reference tables.\n");
       
  1682 	TInt i;
       
  1683 	TInt err = KErrNone;
       
  1684 	for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1685 		{
       
  1686 		TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables %d\n",i));
       
  1687 		TInt r=iPeFiles[i]->ResolveDllRefTable(*this);
       
  1688 		if (r!=KErrNone)
       
  1689 			err=r;
       
  1690 		}
       
  1691 	TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables complete\n"));
       
  1692 	return err;
       
  1693 	}
       
  1694 
       
  1695 
       
  1696 TInt E32Rom::BuildDependenceGraph()
       
  1697 	{
       
  1698 	Print(ELog, "\nBuilding dependence graph.\n");
       
  1699 	TInt i;
       
  1700 	TInt err = KErrNone;
       
  1701 	for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1702 		{
       
  1703 		TRACE(TIMPORT,Print(ELog,"BuildDep %d\n",i));
       
  1704 		TRomBuilderEntry* e=iPeFiles[i];
       
  1705 		TInt r=e->BuildDependenceGraph(*this);
       
  1706 		if (r!=KErrNone)
       
  1707 			err=r;
       
  1708 		if (!e->IsDll())
       
  1709 			{
       
  1710 			if (e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0)
       
  1711 				e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataPresent);	// EXE with static data
       
  1712 			}
       
  1713 		else if ((e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0) && !e->Variant() && !e->Extension())
       
  1714 			{
       
  1715 			// requires normal case DLL data initialisation
       
  1716 			e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataInit|KRomImageFlagDataPresent);
       
  1717 			}
       
  1718 		}
       
  1719 	TRACE(TIMPORT,Print(ELog,"BuildDep complete\n"));
       
  1720 
       
  1721 	if(!gPagedRom)
       
  1722 		return err;
       
  1723 
       
  1724 	Print(ELog,"\n");
       
  1725 
       
  1726 	return err;
       
  1727 	}
       
  1728 
       
  1729 #define MARK_BEEN_HERE	1
       
  1730 #define MARK_KEEP		2
       
  1731 #define	MARK_EXE		4
       
  1732 #define MARK_CHECKED	8
       
  1733 void E32Rom::UnmarkGraph(TInt aMark)
       
  1734 	{
       
  1735 	TRomNode* x = 0;
       
  1736 	for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable)
       
  1737 		x->iRomFile->iMark &= ~aMark;
       
  1738 	}
       
  1739 
       
  1740 void E32Rom::FindMarked(TInt aMarkMask, TInt aMark, TRomFile**& aList)
       
  1741 	{
       
  1742 	UnmarkGraph(MARK_CHECKED);
       
  1743 	TRomNode* x = 0;
       
  1744 	aMarkMask |= MARK_CHECKED;
       
  1745 	aMark &= ~MARK_CHECKED;
       
  1746 	for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable)
       
  1747 		{
       
  1748 		TRomFile* e = x->iRomFile;
       
  1749 		if ((e->iMark&aMarkMask)==aMark)
       
  1750 			{
       
  1751 			*aList++=e;
       
  1752 			e->iMark |= MARK_CHECKED;
       
  1753 			}
       
  1754 		}
       
  1755 	}
       
  1756 
       
  1757 TInt TRomFile::MarkDeps()
       
  1758 	{
       
  1759 	TInt n=0;
       
  1760 	TInt i;
       
  1761 	for (i=0; i<iNumDeps; ++i)
       
  1762 		{
       
  1763 		TRomFile* e=iDeps[i];
       
  1764 		if (!(e->iMark & MARK_BEEN_HERE))
       
  1765 			{
       
  1766 			e->iMark|=MARK_BEEN_HERE;
       
  1767 			++n;
       
  1768 			n+=e->MarkDeps();
       
  1769 			TUint32 flg = RomImageFlags();
       
  1770 			TUint32 eflg = e->RomImageFlags();
       
  1771 			if (eflg & KRomImageFlagDataPresent)
       
  1772 				iRbEntry->iRomImageFlags |= KRomImageFlagDataPresent;
       
  1773 			TBool e_is_dll = eflg & KImageDll;
       
  1774 			if ((flg & KImageDll) && e_is_dll && (eflg & KRomImageFlagDataInit))
       
  1775 				iRbEntry->iRomImageFlags |= KRomImageFlagDataInit;
       
  1776 			if (!e_is_dll)
       
  1777 				e->iMark|=MARK_EXE;
       
  1778 			if (eflg&KRomImageFlagData)
       
  1779 				e->iMark|=MARK_KEEP;
       
  1780 			}
       
  1781 		}
       
  1782 	return n;
       
  1783 	}
       
  1784 
       
  1785 TInt TRomFile::FindRouteTo(TRomFile* aDest, TRomFile** aStack, TInt aIndex)
       
  1786 	{
       
  1787 	TInt i;
       
  1788 	for (i=0; i<iNumDeps; ++i)
       
  1789 		{
       
  1790 		TRomFile* e=iDeps[i];
       
  1791 		if (e == aDest)
       
  1792 			return aIndex;
       
  1793 		if (!(e->iMark & MARK_BEEN_HERE))
       
  1794 			{
       
  1795 			e->iMark|=MARK_BEEN_HERE;
       
  1796 			aStack[aIndex] = e;
       
  1797 			TInt r = e->FindRouteTo(aDest, aStack, aIndex+1);
       
  1798 			if (r >= 0)
       
  1799 				return r;
       
  1800 			}
       
  1801 		}
       
  1802 	return KErrNotFound;
       
  1803 	}
       
  1804 
       
  1805 void E32Rom::ListRouteTo(TRomFile* aStart, TRomFile* aDest, TInt aNDeps)
       
  1806 	{
       
  1807 	TRomNode* rootdir = iObey->iRootDirectory;
       
  1808 	TRomFile** stack = new TRomFile*[aNDeps];
       
  1809 	UnmarkGraph();
       
  1810 	TInt depth = aStart->FindRouteTo(aDest, stack, 0);
       
  1811 	assert(depth >= 0);
       
  1812 	Print(EAlways, "\t--->%s\n", (const char*)TModuleName(*aDest, rootdir));
       
  1813 	while(--depth >= 0)
       
  1814 		Print(EAlways, "\tvia %s\n", (const char*)TModuleName(*stack[depth], rootdir));
       
  1815 	delete[] stack;
       
  1816 	}
       
  1817 
       
  1818 TInt E32Rom::ProcessDependencies()
       
  1819 	{
       
  1820 	TInt i;
       
  1821 	TInt errors = 0;
       
  1822 	for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1823 		{
       
  1824 		TRomBuilderEntry* e=iPeFiles[i];
       
  1825 		TRomNode* rn = e->iRomNode;
       
  1826 		TRomFile* rf = rn->iRomFile;
       
  1827 		UnmarkGraph();
       
  1828 		TInt n=rf->MarkDeps();
       
  1829 		rf->iNumPDeps=n;
       
  1830 		if (n)
       
  1831 			{
       
  1832 			rf->iPDeps=new TRomFile* [n];
       
  1833 			if (!rf->iPDeps)
       
  1834 				return KErrNoMemory;
       
  1835 			TRomFile** l=rf->iPDeps;
       
  1836 			FindMarked(MARK_EXE, MARK_EXE, l);
       
  1837 			TInt nx=l-rf->iPDeps;
       
  1838 			if (!e->IsDll() && (nx>1 || (nx==1 && l[-1]!=rf)))
       
  1839 				{
       
  1840 				Print(EError,"EXE %s links to the following other EXEs:\n", e->iFileName);
       
  1841 				TInt j;
       
  1842 				for (j=0; j<nx; ++j)
       
  1843 					{
       
  1844 					if (rf->iPDeps[j] != rf)
       
  1845 						ListRouteTo(rf, rf->iPDeps[j], n);
       
  1846 					}
       
  1847 				++errors;
       
  1848 				continue;
       
  1849 				}
       
  1850 			else if (nx>1)
       
  1851 				{
       
  1852 				Print(EError,"DLL %s links to more than one EXE:\n",e->iFileName);
       
  1853 				TInt j;
       
  1854 				for (j=0; j<nx; ++j)
       
  1855 					ListRouteTo(rf, rf->iPDeps[j], n);
       
  1856 				++errors;
       
  1857 				continue;
       
  1858 				}
       
  1859 			if (nx)
       
  1860 				e->iRomImageFlags|=KRomImageFlagExeInTree;
       
  1861 			FindMarked(MARK_KEEP|MARK_EXE, MARK_KEEP, l);
       
  1862 			rf->iNumPDeps=l-rf->iPDeps;
       
  1863 			if (rf->iNumPDeps)
       
  1864 				{
       
  1865 				e->iDllRefTableRange.iSize=(rf->iNumPDeps-1)*sizeof(TRomImageHeader*)+sizeof(TDllRefTable);
       
  1866 				if (e->IsDll() && rf->iTotalDataBss)
       
  1867 					{
       
  1868 					TRomFile* f=rf->iPDeps[0];	// first dependency, EXE if there is one
       
  1869 					TUint fflg = f->RomImageFlags();
       
  1870 					TBool f_is_dll = fflg & KImageDll;
       
  1871 					if (!f_is_dll)
       
  1872 						{
       
  1873 						// DLL with data/bss depends on EXE
       
  1874 						if ((fflg & KRomImageFlagFixedAddressExe) || iObey->iMemModel==E_MM_Direct)
       
  1875 							{
       
  1876 							// assign the DLL data address in the EXE bss section
       
  1877 							rf->iDataBssOffsetInExe=f->iTotalDataBss;
       
  1878 							f->iTotalDataBss+=rf->iTotalDataBss;
       
  1879 							}
       
  1880 						}
       
  1881 					else if (iObey->iMemModel==E_MM_Direct)
       
  1882 						{
       
  1883 						Print(EError, "DLL with data/bss must have attach process specified\n");
       
  1884 						return KErrGeneral;
       
  1885 						}
       
  1886 					}
       
  1887 				}
       
  1888 			else
       
  1889 				{
       
  1890 				delete[] rf->iPDeps;
       
  1891 				rf->iPDeps=NULL;
       
  1892 				}
       
  1893 			}
       
  1894 		if (!rf->iNumPDeps)
       
  1895 			e->iDllRefTableRange.iSize=0;
       
  1896 		}
       
  1897 	if (iObey->iMemModel == E_MM_Moving)
       
  1898 		{
       
  1899 		// On moving model only, we must verify that no fixed process links to a
       
  1900 		// DLL with data/bss which is attached to a fixed process.
       
  1901 		// On multiple model there is no restriction.
       
  1902 		// On direct model all DLLs with data/bss must specify an attach process
       
  1903 		// and the error will show up as one EXE depending on another.
       
  1904 		for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1905 			{
       
  1906 			TRomBuilderEntry* e=iPeFiles[i];
       
  1907 			TRomNode* rn = e->iRomNode;
       
  1908 			TRomFile* rf = rn->iRomFile;
       
  1909 			TUint rif = rf->RomImageFlags();
       
  1910 			if (e->IsDll() || e->Primary() || !(rif & KRomImageFlagFixedAddressExe))
       
  1911 				continue;	// only need to check fixed address user mode EXEs
       
  1912 			TInt n = rf->iNumPDeps;
       
  1913 			TInt j;
       
  1914 			for (j=0; j<n; ++j)
       
  1915 				{
       
  1916 				TRomFile* f = rf->iPDeps[j];
       
  1917 				TUint fflg = f->RomImageFlags();
       
  1918 				if ((fflg & KImageDll) && (f->iDataBssOffsetInExe < 0))
       
  1919 					{
       
  1920 					// fixed user EXE links to DLL with data/bss and no attach process
       
  1921 					Print(EError,"Fixed EXE %s links to DLL with data/bss and no attach process:\n", e->iFileName);
       
  1922 					ListRouteTo(rf, rf->iPDeps[j], n);
       
  1923 					++errors;
       
  1924 					}
       
  1925 				}
       
  1926 			}
       
  1927 		}
       
  1928 	if (errors)
       
  1929 		return KErrGeneral;
       
  1930 
       
  1931 	STRACE(TIMPORT, 
       
  1932 		{
       
  1933 		for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1934 			{
       
  1935 			TRomBuilderEntry* e=iPeFiles[i];
       
  1936 			TRomNode* rn = e->iRomNode;
       
  1937 			TRomFile* rf = rn->iRomFile;
       
  1938 			Print(ELog,"File %s: PN=%d\n",e->iFileName,rf->iNumPDeps);
       
  1939 			TInt j;
       
  1940 			for (j=0; j<rf->iNumPDeps; ++j)
       
  1941 				{
       
  1942 				TRomFile* f=rf->iPDeps[j];
       
  1943 				Print(ELog,"\t%s\n", (const char*)TModuleName(*f, iObey->iRootDirectory));
       
  1944 				}
       
  1945 			}
       
  1946 		})
       
  1947 	return KErrNone;
       
  1948 	}
       
  1949 
       
  1950 void E32Rom::SetSmpFlags()
       
  1951     {
       
  1952 	if (gLogLevel & LOG_LEVEL_SMP_INFO)
       
  1953 		{
       
  1954 		Print(ELog,"\nComputing SMP properties. The following components are SMP-unsafe:\n");
       
  1955 		}
       
  1956 
       
  1957 	bool is_all_safe = 1;
       
  1958 
       
  1959 	for (int i = 0; i < iObey->iNumberOfPeFiles; i++)
       
  1960 		{
       
  1961 		TRomBuilderEntry* e = iPeFiles[i];
       
  1962 
       
  1963         if ( e->iRomNode->iRomFile->ComputeSmpSafe(e) )
       
  1964 			{
       
  1965 			e->iRomImageFlags |= KRomImageSMPSafe;
       
  1966 			}
       
  1967 		else
       
  1968 			{
       
  1969 			is_all_safe = 0;
       
  1970 			e->iRomImageFlags &= ~KRomImageSMPSafe;
       
  1971 			}
       
  1972 		}
       
  1973 
       
  1974 	if ( (gLogLevel & LOG_LEVEL_SMP_INFO) && is_all_safe)
       
  1975 		{
       
  1976 		Print(ELog,"There are no unsafe components.");
       
  1977 		}
       
  1978     }
       
  1979 
       
  1980 TInt E32Rom::ResolveImports()
       
  1981 //
       
  1982 // Fix the import address table for each of the files in rom
       
  1983 //	
       
  1984 	{
       
  1985 
       
  1986 	Print(ELog, "Resolving Imports.\n");
       
  1987 	TInt i;
       
  1988 	for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  1989 		{
       
  1990 		TInt r=iPeFiles[i]->FixupImports(*this);
       
  1991 		if (r!=KErrNone)
       
  1992 			return r;
       
  1993 		}
       
  1994 	return KErrNone;
       
  1995 	}
       
  1996 
       
  1997 char *E32Rom::RomToActualAddress(TUint aPtr)
       
  1998 	{
       
  1999 	return (char *)(aPtr-iObey->iRomLinearBase+(TUint)iHeader);
       
  2000 	}
       
  2001 
       
  2002 TUint E32Rom::ActualToRomAddress(TAny *aPtr)
       
  2003 	{
       
  2004 	return ((TUint)aPtr)-(TUint32)iHeader+iObey->iRomLinearBase;
       
  2005 	}
       
  2006 
       
  2007 void E32Rom::SetImageAddr(TAddressRange& aRange, TAny* aPtr, TUint32 aRunOffset)
       
  2008 	{
       
  2009 	aRange.iImagePtr=aPtr;
       
  2010 	aRange.iImageAddr=ActualToRomAddress(aPtr);
       
  2011 	aRange.iRunAddr=aRange.iImageAddr+aRunOffset;
       
  2012 	}
       
  2013 
       
  2014 void E32Rom::SetImageAddr(TAddressRange& aRange, TUint aAddr, TUint32 aRunOffset)
       
  2015 	{
       
  2016 	aRange.iImagePtr=RomToActualAddress(aAddr);
       
  2017 	aRange.iImageAddr=aAddr;
       
  2018 	aRange.iRunAddr=aAddr+aRunOffset;
       
  2019 	}
       
  2020 
       
  2021 TRomNode* E32Rom::FindImageFileByName(const TDllFindInfo& aInfo, TBool aPrintDiag, TBool& aFallBack)
       
  2022 //
       
  2023 // return the file with the name aName
       
  2024 //
       
  2025 	{
       
  2026 	return iObey->iRootDirectory->FindImageFileByName(aInfo, aPrintDiag, aFallBack);
       
  2027 	}
       
  2028 
       
  2029 TInt E32Rom::CheckForVersionConflicts(const TRomBuilderEntry* a)
       
  2030 	{
       
  2031 	return iObey->iRootDirectory->CheckForVersionConflicts(a);
       
  2032 	}
       
  2033 
       
  2034 TRomNode* E32Rom::CopyDirectory(TRomNode*& aLastExecutable)
       
  2035 	{
       
  2036 	return iObey->iRootDirectory->CopyDirectory(aLastExecutable, 0);
       
  2037 	}
       
  2038 
       
  2039 TInt E32Rom::CollapseImportThunks()
       
  2040 //
       
  2041 // Collapse 3-word import thunks into a single branch
       
  2042 //	
       
  2043 	{
       
  2044 
       
  2045 	Print(ELog, "\nCollapsing Import Thunks.\n");
       
  2046 	TInt i;
       
  2047 	for (i=0; i<iObey->iNumberOfPeFiles; i++)
       
  2048 		{
       
  2049 		if (iPeFiles[i]->iHdr->iImportOffset)
       
  2050 			{
       
  2051 			TInt r=CollapseImportThunks(iPeFiles[i]);
       
  2052 			if (r!=KErrNone)
       
  2053 				return r;
       
  2054 			}
       
  2055 		}
       
  2056 	return KErrNone;
       
  2057 	}
       
  2058 
       
  2059 TInt E32Rom::WriteImages(TInt aHeaderType)
       
  2060 	{
       
  2061 	if (aHeaderType < 0)
       
  2062 		aHeaderType = 1;
       
  2063 	ofstream romFile((const char *)iObey->iRomFileName,ios::binary);
       
  2064 	if (!romFile)
       
  2065 		return Print(EError,"Cannot open ROM file %s for output\n",iObey->iRomFileName);
       
  2066 	Write(romFile, aHeaderType);
       
  2067 	romFile.close();
       
  2068 
       
  2069 	// Write out the odd/even 16-bits of the images
       
  2070 
       
  2071 	char sname[256];
       
  2072 	if (iObey->iRomOddFileName)
       
  2073 		{
       
  2074 		strcpy(sname, (const char*)iObey->iRomOddFileName);
       
  2075 		if (strcmp(sname, "*")==0)
       
  2076 			{
       
  2077 			// use romname with ".odd" appended.
       
  2078 			sprintf(sname,"%s.odd",(const char *)iObey->iRomFileName);
       
  2079 			}
       
  2080 		ofstream oFile(sname,ios::binary);
       
  2081 		if (!oFile)
       
  2082 			return Print(EError,"Cannot open file %s for output\n",sname);
       
  2083 		Print(EAlways, "Writing odd half words to file %s\n",sname);
       
  2084 		WriteOdd(oFile);
       
  2085 		oFile.close();
       
  2086 		}
       
  2087 	if (iObey->iRomEvenFileName)
       
  2088 		{
       
  2089 		strcpy(sname, (const char*)iObey->iRomEvenFileName);
       
  2090 		if (strcmp(sname, "*")==0)
       
  2091 			{
       
  2092 			// use romname with ".even" appended.
       
  2093 			sprintf(sname,"%s.even",(const char *)iObey->iRomFileName);
       
  2094 			}
       
  2095 		ofstream oFile(sname,ios::binary);
       
  2096 		if (!oFile)
       
  2097 			return Print(EError,"Cannot open file %s for output\n",sname);
       
  2098 		Print(EAlways, "Writing even half words to file %s\n",sname);
       
  2099 		WriteEven(oFile);
       
  2100 		oFile.close();
       
  2101 		}
       
  2102 
       
  2103 	// Write out the ROM in the SREC or S19 format
       
  2104 
       
  2105 	if (iObey->iSRecordFileName)
       
  2106 		{
       
  2107 		strcpy(sname, (const char*)iObey->iSRecordFileName);
       
  2108 		if (strcmp(sname, "*")==0)
       
  2109 			{
       
  2110 			// use romname with ".srec" appended.
       
  2111 			sprintf(sname,"%s.srec",(const char *)iObey->iRomFileName);
       
  2112 			}
       
  2113 		ofstream sFile(sname,ios::binary);
       
  2114 		if (!romFile)
       
  2115 			return Print(EError,"Cannot open file %s for output\n",sname);
       
  2116 		Print(EAlways, "Writing S record format to file %s\n",sname);
       
  2117 		WriteSRecord(sFile);
       
  2118 		sFile.close();
       
  2119 		}
       
  2120 	return KErrNone;
       
  2121 	}
       
  2122 
       
  2123 void E32Rom::WriteOdd(ofstream &os)
       
  2124 	{
       
  2125 	char *ptr=(char *)iHeader+2;
       
  2126 	TInt i;
       
  2127 	for (i=2; i<iObey->iRomSize; i+=4, ptr+=4)
       
  2128 		os.write(ptr, 2);
       
  2129 	}
       
  2130 
       
  2131 void E32Rom::WriteEven(ofstream &os)
       
  2132 	{
       
  2133 	char *ptr=(char *)iHeader;
       
  2134 	TInt i;
       
  2135 	for (i=0; i<iObey->iRomSize; i+=4, ptr+=4)
       
  2136 		os.write(ptr, 2);
       
  2137 	}
       
  2138 
       
  2139 void E32Rom::SetCompressionInfo(TUint aCompressionType, TUint aCompressedSize, TUint aUncompressedSize)
       
  2140 	{
       
  2141 
       
  2142 	if (iExtensionRomHeader)
       
  2143 		{
       
  2144 		iExtensionRomHeader->iCompressionType=aCompressionType;
       
  2145 		iExtensionRomHeader->iCompressedSize=aCompressedSize;
       
  2146 		iExtensionRomHeader->iUncompressedSize=aUncompressedSize;
       
  2147 		}
       
  2148 	else
       
  2149 		{
       
  2150 		iHeader->iCompressionType=aCompressionType;
       
  2151 		iHeader->iCompressedSize=aCompressedSize;
       
  2152 		iHeader->iUncompressedSize=aUncompressedSize;
       
  2153 		}
       
  2154 	}
       
  2155 
       
  2156 void E32Rom::Write(ofstream &os, TInt aHeaderType)
       
  2157 //
       
  2158 // Output a rom image
       
  2159 //
       
  2160 	{
       
  2161 
       
  2162 	const char *compressed=gEnableCompress ? " compressed" : " uncompressed"; 
       
  2163 
       
  2164 	switch (aHeaderType)
       
  2165 		{
       
  2166 	case 0:
       
  2167 		Print(EAlways, "\nWriting%s Rom image without",compressed);
       
  2168 		break;
       
  2169 	case 1:
       
  2170 	default:
       
  2171 		Print(EAlways, "\nWriting%sRom image with repro",compressed);
       
  2172 		os.write(iData, sizeof(TRomLoaderHeader));
       
  2173 		break;
       
  2174 	case 2:
       
  2175 		Print(EAlways, "\nWriting%s Rom image with PE-COFF",compressed);
       
  2176 			{
       
  2177 			unsigned char coffhead[0x58] = {0};  // zero all the elements
       
  2178 
       
  2179 			// fill in the constant bits
       
  2180 			// this is supposed to be simple, remember
       
  2181 			coffhead[1] = 0x0a;
       
  2182 			coffhead[2] = 0x01;
       
  2183 			coffhead[0x10] = 0x1c;
       
  2184 			coffhead[0x12] = 0x0f;
       
  2185 			coffhead[0x13] = 0xa1;
       
  2186 			coffhead[0x14] = 0x0b;
       
  2187 			coffhead[0x15] = 0x01;
       
  2188 			coffhead[0x26] = 0x40;
       
  2189 			coffhead[0x2a] = 0x40;
       
  2190 			coffhead[0x30] = 0x2e;
       
  2191 			coffhead[0x31] = 0x74;
       
  2192 			coffhead[0x32] = 0x65;
       
  2193 			coffhead[0x33] = 0x78;
       
  2194 			coffhead[0x34] = 0x74;
       
  2195 			coffhead[0x3a] = 0x40;
       
  2196 			coffhead[0x3e] = 0x40;
       
  2197 			coffhead[0x44] = 0x58;
       
  2198 			coffhead[0x54] = 0x20;
       
  2199 
       
  2200 			// now fill in the text segment size
       
  2201 			TUint32 * p0x18 = reinterpret_cast<TUint32 *>(&coffhead[0x18]);
       
  2202 			*p0x18 = ALIGN4K(iSizeUsed);
       
  2203 			TUint32 * p0x40 = reinterpret_cast<TUint32 *>(&coffhead[0x40]);
       
  2204 			*p0x40 = ALIGN4K(iSizeUsed);
       
  2205 
       
  2206 
       
  2207 			os.write(reinterpret_cast<char *>(coffhead), sizeof(coffhead));
       
  2208 			}
       
  2209 		break;
       
  2210 		}
       
  2211 	Print(EAlways, " header to file %s\n", iObey->iRomFileName);
       
  2212 	
       
  2213 	iHeader->iUnpagedCompressedSize   = 0;
       
  2214 	iHeader->iUnpagedUncompressedSize = iHeader->iPageableRomStart;
       
  2215 	iHeader->iCompressedUnpagedStart =  gBootstrapSize + gPageIndexTableSize;	// AttilaV calculate uncompressed un-paged size 
       
  2216 	
       
  2217 	if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2218 		{
       
  2219 		Print(ELog, "iUnpagedCompressedSize  :0x%08x (%d)\n",     iHeader->iUnpagedCompressedSize);
       
  2220 		Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n",   iHeader->iUnpagedUncompressedSize);
       
  2221 		
       
  2222 		Print(ELog, "iExtensionRomHeader     :%d\n",     iExtensionRomHeader);
       
  2223 		Print(ELog, "iCompressionType        :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));	
       
  2224 		Print(ELog, "iCompressedSize         :0x%08x (%d)\n",     (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize  : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize  : iHeader->iCompressedSize ));
       
  2225 		Print(ELog, "iUncompressedSize       :0x%08x (%d)\n\n",   (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
       
  2226 	
       
  2227 		Print(ELog, "iPageableRomStart       :0x%08x (%d)\n",   iHeader->iPageableRomStart, iHeader->iPageableRomStart );
       
  2228 		Print(ELog, "iPageableRomSize        :0x%08x (%d)\n",   iHeader->iPageableRomSize, iHeader->iPageableRomSize  );
       
  2229 		Print(ELog, "iRomPageIndex           :0x%08x (%d)\n",   iHeader->iRomPageIndex, iHeader->iRomPageIndex );
       
  2230 	
       
  2231 		Print(ELog, "iSizeUsed               :0x%08x (%d)\n",   iSizeUsed, iSizeUsed );
       
  2232 		Print(ELog, "Linear base address     :0x%08x\n",iHeader->iRomBase); 
       
  2233 		Print(ELog, "Size:                    0x%08x\n",iHeader->iRomSize);
       
  2234 		}
       
  2235 
       
  2236 	if ( gPagedRom && gCompressUnpaged)
       
  2237 		{
       
  2238 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2239 			Print(ELog, "Write out compressed un-paged and paged sections\n\n");
       
  2240 		ImpTRomHeader* header = (ImpTRomHeader *)iHeader;
       
  2241 		
       
  2242 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2243 			{
       
  2244 			Print(ELog, "Header:\n");
       
  2245 			header->Display();
       
  2246 			}
       
  2247 		
       
  2248 		streampos headerpos=os.tellp();
       
  2249 		
       
  2250 		// Write out uncompressed un-paged part (bootstrap + Page Index Table)
       
  2251 		os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart);
       
  2252 		
       
  2253 		// write out the compressed unpaged part
       
  2254 		int srcsize=iHeader->iPageableRomStart - iHeader->iCompressedUnpagedStart;		
       
  2255 		
       
  2256 		int rawimagelen=DeflateCompressCheck(((char *)iHeader)+iHeader->iCompressedUnpagedStart,srcsize,os);
       
  2257 		iHeader->iUnpagedCompressedSize = rawimagelen;
       
  2258 		iHeader->iUnpagedUncompressedSize = srcsize ;
       
  2259 		
       
  2260 		// align to 4kbyte boundary if neccessary
       
  2261 		TUint32 distanceFrom4kBoundary = ((~(iHeader->iCompressedUnpagedStart + rawimagelen /*+ sizeof(TRomLoaderHeader)*/ )) & 0xfff) + 1;
       
  2262 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2263 			Print(ELog, "distanceFrom4kBoundary  :0x%08x (%d)\n", distanceFrom4kBoundary, distanceFrom4kBoundary);
       
  2264 		char filer[0x1000];
       
  2265 		memset( filer, 0, 0x1000);
       
  2266 		os.write((char *)filer, distanceFrom4kBoundary);
       
  2267 		
       
  2268 		
       
  2269 		// write out the paged part
       
  2270 		os.write((char *)iHeader + iHeader->iPageableRomStart, ALIGN4K(iSizeUsed - iHeader->iPageableRomStart));
       
  2271 		
       
  2272 		// update size and compression information of paged-part
       
  2273 		SetCompressionInfo(KUidCompressionDeflate, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize));
       
  2274 		
       
  2275 		// Calculate starting index of the Pageable Rom Start
       
  2276 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2277 			{
       
  2278 			Print(ELog, "iPageableRomStart				: %d (0x%08x)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart);
       
  2279 			Print(ELog, "iCompressedUnpagedStart			: %d (0x%08x)\n", iHeader->iCompressedUnpagedStart, iHeader->iCompressedUnpagedStart);
       
  2280 			Print(ELog, "rawimagelen						: %d (0x%08x)\n", rawimagelen, rawimagelen);
       
  2281 			}
       
  2282 		
       
  2283 		TInt displacement = iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary; 
       
  2284 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2285 			Print(ELog, "new iPageableRomStart			: %d (0x%08x)\n", (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary), (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary));
       
  2286 		displacement = iHeader->iPageableRomStart-displacement;
       
  2287 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2288 			Print(ELog, "displacement					: %d (0x%08x)\n", displacement, displacement);
       
  2289 		
       
  2290 		SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex);
       
  2291 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2292 			Print(ELog, "First Pageable page info[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize);
       
  2293 		
       
  2294 		TInt startPageableIndex = (iHeader->iPageableRomStart) / (iObey->iPageSize);
       
  2295 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2296 			{
       
  2297 			Print(ELog, "iObey->iPageSize				: %d (0x%08x)\n", iObey->iPageSize, iObey->iPageSize);
       
  2298 			Print(ELog, "startPageableIndex				: %d (0x%08x)\n", startPageableIndex, startPageableIndex);
       
  2299 			}
       
  2300 		pi += startPageableIndex;
       
  2301 		
       
  2302 		
       
  2303 		while ( 0 != pi->iDataStart)
       
  2304 			{
       
  2305 				if (H.iVerbose) Print(ELog, "\t\tinfo[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize);		
       
  2306 				
       
  2307 				pi->iDataStart -= displacement;
       
  2308 				
       
  2309 				if (H.iVerbose) Print(ELog, "\t\tinfo[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize);		
       
  2310 				
       
  2311 				++pi;
       
  2312 			}
       
  2313 		
       
  2314 		
       
  2315 		
       
  2316 		// Rewrite the header with updated info
       
  2317 		#ifdef __TOOLS2__
       
  2318 		os.seekp(headerpos); 
       
  2319 		#else
       
  2320 		os.seekp(headerpos,ios::beg);
       
  2321 		#endif
       
  2322 		
       
  2323 		// Rewrite uncompressed un-paged part (bootstrap + Page Index Table)
       
  2324 		os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart);
       
  2325 		
       
  2326 		
       
  2327 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2328 			{
       
  2329 			Print(ELog, "iUnpagedCompressedSize  :0x%08x (%d)\n",     iHeader->iUnpagedCompressedSize, iHeader->iUnpagedCompressedSize);
       
  2330 			Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n",   iHeader->iUnpagedUncompressedSize, iHeader->iUnpagedUncompressedSize);
       
  2331 		
       
  2332 			Print(ELog, "iCompressionType        :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));	
       
  2333 			Print(ELog, "iCompressedSize         :0x%08x (%d)\n",     (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize  : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize  : iHeader->iCompressedSize ));
       
  2334 			Print(ELog, "iUncompressedSize       :0x%08x (%d)\n\n",   (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
       
  2335 		
       
  2336 			Print(ELog, "iPageableRomStart       :0x%08x (%d)\n",   iHeader->iPageableRomStart, iHeader->iPageableRomStart );
       
  2337 			Print(ELog, "iPageableRomSize        :0x%08x (%d)\n",   iHeader->iPageableRomSize, iHeader->iPageableRomSize  );
       
  2338 			Print(ELog, "iRomPageIndex           :0x%08x (%d)\n",   iHeader->iRomPageIndex, iHeader->iRomPageIndex );
       
  2339 			Print(ELog, "\t\tinfo(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi->iDataStart, pi->iDataSize, pi->iDataSize);
       
  2340 		
       
  2341 			Print(ELog, "Linear base address:     %08x\n",iHeader->iRomBase); 
       
  2342 			Print(ELog, "Size:                    %08x\n",iHeader->iRomSize);
       
  2343 			}
       
  2344 		
       
  2345 		return;
       
  2346 		}
       
  2347 
       
  2348 	if (!gEnableCompress || gPagedRom || !gCompressUnpaged)
       
  2349 		{
       
  2350 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2351 			Print(ELog, "Writeout uncompressed un-paged and paged sections2\n");
       
  2352 		SetCompressionInfo(KFormatNotCompressed, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize));
       
  2353 		iHeader->iUnpagedCompressedSize = ALIGN4K(iSizeUsed);
       
  2354 		iHeader->iUnpagedUncompressedSize = ALIGN4K(iUncompressedSize);
       
  2355 		
       
  2356 		os.write((char *)iHeader, ALIGN4K(iSizeUsed));
       
  2357 		
       
  2358 		if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2359 			{
       
  2360 			Print(ELog, "iUnpagedCompressedSize  :0x%08x (%d)\n",     iHeader->iUnpagedCompressedSize);
       
  2361 			Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n",   iHeader->iUnpagedUncompressedSize);
       
  2362 		
       
  2363 			Print(ELog, "iCompressionType        :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));	
       
  2364 			Print(ELog, "iCompressedSize         :0x%08x (%d)\n",     (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize  : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize  : iHeader->iCompressedSize ));
       
  2365 			Print(ELog, "iUncompressedSize       :0x%08x (%d)\n\n",   (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
       
  2366 		
       
  2367 			Print(ELog, "iPageableRomStart       :0x%08x (%d)\n",   iHeader->iPageableRomStart, iHeader->iPageableRomStart );
       
  2368 			Print(ELog, "iPageableRomSize        :0x%08x (%d)\n",   iHeader->iPageableRomSize, iHeader->iPageableRomSize  );
       
  2369 			Print(ELog, "iRomPageIndex           :0x%08x (%d)\n",   iHeader->iRomPageIndex, iHeader->iRomPageIndex );
       
  2370 			}
       
  2371 		
       
  2372 		return;
       
  2373 		}
       
  2374 
       
  2375 	// compressed image without paging section
       
  2376 	streampos headerpos=os.tellp();
       
  2377 	int headersize=iExtensionRomHeader ? sizeof(TExtensionRomHeader) : sizeof(TRomHeader);
       
  2378 
       
  2379 	os.write(reinterpret_cast<char*>(iHeader), headersize); // write a dummy header
       
  2380 	// compress the rest of the image
       
  2381 	int srcsize=iSizeUsed - headersize;
       
  2382 	int rawimagelen=DeflateCompressCheck(((char *)iHeader)+headersize,srcsize,os);
       
  2383 	// write the compression info into the header
       
  2384 	SetCompressionInfo(KUidCompressionDeflate, rawimagelen, iUncompressedSize); // doesn't need to be 4K aligned
       
  2385 	iHeader->iCompressedUnpagedStart = headersize; 
       
  2386 	iHeader->iUnpagedCompressedSize = rawimagelen;
       
  2387 	iHeader->iUnpagedUncompressedSize = srcsize;
       
  2388 		
       
  2389 	#ifdef __TOOLS2__
       
  2390 	os.seekp(headerpos); 
       
  2391 	#else
       
  2392 	os.seekp(headerpos,ios::beg);
       
  2393 	#endif
       
  2394 	os.write(reinterpret_cast<char*>(iHeader), headersize);	// write header again with (compressed) size info
       
  2395 	
       
  2396 	if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  2397 		Print(ELog, "\tiSizeUsed:%d, iUncompressedSize:%d, headersize:%d, srcsize:%d, rawimagelen:%d \n",iSizeUsed, iUncompressedSize, headersize, srcsize, rawimagelen);
       
  2398 	}
       
  2399 
       
  2400 TInt E32Rom::Compare(char *anImage, TInt aHeaderType)
       
  2401 	{
       
  2402 	if (aHeaderType < 0)
       
  2403 		aHeaderType = 1;
       
  2404 	ifstream file(anImage, ios::binary);
       
  2405 	if (!file)
       
  2406 		return Print(EError, "Cannot open Rom image '%s' for verification\n", anImage);
       
  2407 	Print(ELog, "\nVerifying ROM against image in %s\n", anImage);
       
  2408 	switch (aHeaderType)
       
  2409 		{
       
  2410 	case 0:
       
  2411 		break;
       
  2412 	case 1:
       
  2413 	default:
       
  2414 		Print(ELog, "Skipping repro header\n");
       
  2415 		file.seekg(sizeof(TRomLoaderHeader));
       
  2416 		break;
       
  2417 	case 2:
       
  2418 		Print(ELog, "Skipping coff header\n");
       
  2419 		file.seekg(0x58);
       
  2420 		break;
       
  2421 		}
       
  2422 	TInt length=ALIGN4K(iSizeUsed);
       
  2423 	if (iObey->iSectionStart != 0)
       
  2424 		{
       
  2425 		length = iObey->iSectionStart-iObey->iRomLinearBase;
       
  2426 		Print(ELog, "Verifying first section (%08x bytes)... ", length);
       
  2427 		}
       
  2428 
       
  2429 	TRomHeader compareHeader;
       
  2430 	file.read((char *)&compareHeader, sizeof(TRomHeader));
       
  2431 	// Arrange different settings for TRomHeader and
       
  2432 	// TRomSectionHeader in the obey file
       
  2433 	// For now just copy across the things that'll change
       
  2434 	compareHeader.iVersion=iHeader->iVersion;
       
  2435 	compareHeader.iTime=iHeader->iTime;
       
  2436 	compareHeader.iTimeHi=(TUint32)(iHeader->iTime >> 32);
       
  2437 	compareHeader.iCheckSum=iHeader->iCheckSum;
       
  2438 	compareHeader.iLanguage=iHeader->iLanguage;
       
  2439 
       
  2440 	if (memcmp(&compareHeader, iHeader, sizeof(TRomHeader))!=0)
       
  2441 		return Print(EError, "Verify failed.\nRom headers are different\n");
       
  2442 
       
  2443 	// Now compare the rest of the image (or first section)
       
  2444 
       
  2445 	TUint *ptr=(TUint *)(iHeader+1);
       
  2446 	TInt i;
       
  2447 	for (i=sizeof(TRomHeader); i<length; i+=4)
       
  2448 		{
       
  2449 		TUint a;
       
  2450 		file.read((char *)&a, sizeof(TUint));
       
  2451 		if (file.eof())
       
  2452 			return Print(EError, "Verify failed.\nDifferent Rom sizes\n");
       
  2453 		if (a!=*ptr)
       
  2454 			return Print(EError, "Verify failed.\nContents differ at Rom address %08x\n", i+iObey->iRomLinearBase);
       
  2455 		ptr++;
       
  2456 		}
       
  2457 	file.close();
       
  2458 	Print(EAlways, "Verify OK\n");
       
  2459 	return KErrNone;
       
  2460 	}
       
  2461 
       
  2462 
       
  2463 char* E32Rom::AllocateRelocationTable(char* aAddr, TReloc*& aRelocTable)
       
  2464 	{
       
  2465 	if(iObey->SetArea().Count() > 1)
       
  2466 		{
       
  2467 		aRelocTable = reinterpret_cast<TReloc*>(aAddr);
       
  2468 
       
  2469 		// Allocate one entry per non default area + 1 sentinel
       
  2470 		// (Count() returns number of non default areas + 1 (the
       
  2471 		// default area))
       
  2472 		TInt size = iObey->SetArea().Count() * sizeof(TReloc);	
       
  2473 		aAddr += Align(size);
       
  2474 		}
       
  2475 	else
       
  2476 		{
       
  2477 		aRelocTable = 0;
       
  2478 		}
       
  2479 
       
  2480 	return aAddr;
       
  2481 	}
       
  2482 
       
  2483 
       
  2484 void E32Rom::FillInRelocationTable(TReloc* aRelocTable)
       
  2485 	{
       
  2486 	TReloc* p = aRelocTable;
       
  2487 	TInt wastedBytes = 0;
       
  2488 
       
  2489 	for (NonDefaultAreasIterator areaIt(iObey->SetArea());
       
  2490 		 ! areaIt.IsDone();
       
  2491 		 areaIt.GoToNext())
       
  2492 		{
       
  2493 		Area& currentArea = areaIt.Current();
       
  2494 
       
  2495 		if (currentArea.UsedSize() > 0)
       
  2496 			{
       
  2497 			p->iLength = currentArea.UsedSize();
       
  2498 			p->iSrc = currentArea.SrcBaseAddr();
       
  2499 			p->iDest = currentArea.DestBaseAddr();
       
  2500 			++p;
       
  2501 			}
       
  2502 		else
       
  2503 			{
       
  2504 			wastedBytes += sizeof(TReloc);
       
  2505 			}
       
  2506 		}
       
  2507 
       
  2508 	if (aRelocTable != 0)
       
  2509 		{
       
  2510 		// Last entry acts as a sentinel
       
  2511 		memset(p, 0, sizeof(*p));
       
  2512 		}
       
  2513 
       
  2514 	if (wastedBytes > 0)
       
  2515 		{
       
  2516  		Print(EWarning, "Some areas are declared but not used\n");
       
  2517  		Print(EWarning, "%d bytes wasted in relocation table\n", wastedBytes);
       
  2518 		}
       
  2519 	}
       
  2520 
       
  2521 
       
  2522 /**
       
  2523  Link together the kernel extensions.
       
  2524 
       
  2525  Must be called only after space has been allocated in the ROM image
       
  2526  for the kernel extension.
       
  2527  */
       
  2528 
       
  2529 void E32Rom::LinkKernelExtensions(TRomBuilderEntry* aExtArray[], TInt aExtCount)
       
  2530 	{
       
  2531 	/**
       
  2532 	 * The kernel extensions should never be linked together as part of extension ROMs.
       
  2533 	 */
       
  2534 	if (!iExtensionRomHeader)
       
  2535 		{
       
  2536 		TLinAddr* pLastNextExtAddr = &(iHeader->iExtensionFile);
       
  2537 
       
  2538 		for (TInt i=0; i<aExtCount; ++i)
       
  2539 			{
       
  2540 			TRomBuilderEntry* curExt = aExtArray[i];
       
  2541 			*pLastNextExtAddr = ActualToRomAddress(curExt->RomEntry());
       
  2542 			pLastNextExtAddr = &(curExt->iRomImageHeader->iNextExtension);
       
  2543 			}
       
  2544 	
       
  2545 		*pLastNextExtAddr = 0;
       
  2546 		}
       
  2547 	}
       
  2548 
       
  2549 void E32Rom::ProcessDllData()
       
  2550 	{
       
  2551 		DllDataEntry *entry = iObey->GetFirstDllDataEntry();
       
  2552 		TRomBuilderEntry	*romEntry;
       
  2553 		TLinAddr* aExportTbl;
       
  2554 		void	*aLocation;
       
  2555 		TUint	aDataAddr;
       
  2556 		while(entry){
       
  2557 			// A Dll data may be patched either via the ordinal number (as in ABIv2), or via
       
  2558 			// the address of the data field (as in ABIv1).
       
  2559 			romEntry = entry->iRomNode->iRomFile->iRbEntry;
       
  2560 			if((TInt)entry->iOrdinal != -1) { 
       
  2561 				
       
  2562 				// const data symbol may belong in the Code section. Get the address of the data field via the 
       
  2563 				// export table. If the address lies within the Code or data section limits, 
       
  2564 				// get the corresponding location and update it.While considering the Data section limits don't 
       
  2565 				// include the Bss section, as it doesn't exist as yet in the image.
       
  2566 				if(entry->iOrdinal < 1 || entry->iOrdinal > (TUint32)romEntry->iOrigHdr->iExportDirCount)
       
  2567 				{
       
  2568 					Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", entry->iOrdinal, romEntry->iName);
       
  2569 					entry = entry->NextDllDataEntry();
       
  2570 					continue;
       
  2571 				}
       
  2572 				aExportTbl = (TLinAddr*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iExportDirOffset);
       
  2573 				aDataAddr = (TInt32)(aExportTbl[entry->iOrdinal - 1] + entry->iOffset);
       
  2574 				
       
  2575 				if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) && 
       
  2576 					(aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \
       
  2577 										romEntry->iOrigHdr->iCodeSize)) )
       
  2578 				{
       
  2579 					char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset);
       
  2580 					aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase));
       
  2581 					memcpy(aLocation, &(entry->iNewValue), entry->iSize);
       
  2582 				}
       
  2583 				else if( (aDataAddr >= romEntry->iOrigHdr->iDataBase) && 
       
  2584 					(aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \
       
  2585 										romEntry->iOrigHdr->iDataSize )) )
       
  2586 				{
       
  2587 					char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset);
       
  2588 					aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase));
       
  2589 					memcpy(aLocation, &(entry->iNewValue), entry->iSize);
       
  2590 				}
       
  2591 				else
       
  2592 				{
       
  2593 					Print(EWarning, "Patchdata failed as address pointed by ordinal %d of DLL %s doesn't lie within Code or Data section limits\n", entry->iOrdinal, romEntry->iName);
       
  2594 				}
       
  2595 				
       
  2596 			}
       
  2597 			else if((TInt)entry->iDataAddress != -1) { 
       
  2598 				// const data symbol may belong in the Code section. If the address lies within the Code
       
  2599 				// or data section limits, get the corresponding location and update it.While considering 
       
  2600 				// the Data section limits don't include the Bss section, as it doesn't exist as yet in the image.
       
  2601 				aDataAddr = (TUint)(entry->iDataAddress + entry->iOffset);
       
  2602 				if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) && 
       
  2603 					(aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \
       
  2604 											romEntry->iOrigHdr->iCodeSize )) )
       
  2605 				{
       
  2606 					char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset);
       
  2607 					aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase));
       
  2608 					memcpy(aLocation, &(entry->iNewValue), entry->iSize);
       
  2609 				}
       
  2610 				else if( (aDataAddr   >= romEntry->iOrigHdr->iDataBase) && 
       
  2611 					(aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \
       
  2612 											romEntry->iOrigHdr->iDataSize )) )
       
  2613 				{
       
  2614 					char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset);
       
  2615 					aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase));
       
  2616 					memcpy(aLocation, &(entry->iNewValue), entry->iSize);
       
  2617 				}
       
  2618 				else
       
  2619 				{
       
  2620 					Print(EWarning, "Patchdata failed as address 0x%x specified for DLL %s doesn't lie within Code or Data section limits\n", entry->iOrdinal, romEntry->iName);
       
  2621 				}
       
  2622 			}
       
  2623 			else {
       
  2624 			}
       
  2625 			entry = entry->NextDllDataEntry();
       
  2626 		}
       
  2627 	}
       
  2628 
       
  2629 TInt E32Rom::CheckUnpagedMemSize()
       
  2630 	{
       
  2631 
       
  2632 	if (H.iVerbose && gPagedRom)
       
  2633 		{
       
  2634 		Print(EDiagnostic, "iMaxUnpagedMemSize 0x%08x (%d)\n", iObey->iMaxUnpagedMemSize, iObey->iMaxUnpagedMemSize);
       
  2635 		}
       
  2636 		
       
  2637 	// Only check if the iMaxUnpagedMemSize is set
       
  2638 	if (iObey->iMaxUnpagedMemSize <= 0) return KErrNone;
       
  2639 	
       
  2640 	// Only for paged rom
       
  2641 	if (!gPagedRom) 
       
  2642 		{
       
  2643 		Print(EWarning, "The unpaged size overflow check is skipped.\n");
       
  2644 		return KErrNone;
       
  2645 		}
       
  2646 	
       
  2647 	if (iHeader->iPageableRomStart > 0)
       
  2648 		{
       
  2649 		if (iHeader->iPageableRomStart > iObey->iMaxUnpagedMemSize) 
       
  2650 			{
       
  2651 			Print(EError, "Unpaged memory size overflow: require 0x%08x (%d) bytes while the maximum size is 0x%08x (%d) bytes\n",
       
  2652 				iHeader->iPageableRomStart, 
       
  2653 				iHeader->iPageableRomStart, 
       
  2654 				iObey->iMaxUnpagedMemSize, 
       
  2655 				iObey->iMaxUnpagedMemSize);
       
  2656 			
       
  2657 			return KErrNoMemory;
       
  2658 			}
       
  2659 		}
       
  2660 	else
       
  2661 		{
       
  2662 		Print(EWarning, "The size of unpaged memory is not available. The unpaged memory overflow checking is skipped.\n");
       
  2663 		}
       
  2664 		
       
  2665 	return KErrNone;
       
  2666 	}
       
  2667 
       
  2668 TRomNode* E32Rom::RootDirectory() 
       
  2669 { 
       
  2670 	return iObey->iRootDirectory; 
       
  2671 }
       
  2672 
       
  2673 TText* E32Rom::RomFileName()
       
  2674 { 
       
  2675 	return iObey->iRomFileName; 
       
  2676 }
       
  2677 
       
  2678 TUint32 E32Rom::RomBase()
       
  2679 {
       
  2680 	return iHeader->iRomBase;
       
  2681 }
       
  2682 
       
  2683 TUint32 E32Rom::RomSize()
       
  2684 {
       
  2685 	return iHeader->iRomSize;
       
  2686 }
       
  2687 
       
  2688 TVersion E32Rom::Version()
       
  2689 {
       
  2690 	return iHeader->iVersion;
       
  2691 }
       
  2692 
       
  2693 TInt64 E32Rom::Time()
       
  2694 {
       
  2695 	return iHeader->iTime;
       
  2696 }
       
  2697 
       
  2698 TUint32 E32Rom::CheckSum()
       
  2699 {
       
  2700 	return iHeader->iCheckSum;
       
  2701 }
       
  2702 
       
  2703 TUint32 E32Rom::DataRunAddress()
       
  2704 {
       
  2705 	return iObey->iDataRunAddress;
       
  2706 }
       
  2707 
       
  2708 TUint32 E32Rom::RomAlign()
       
  2709 {
       
  2710 	return iObey->iRomAlign;
       
  2711 }