--- a/imgtools/romtools/rombuild/r_rom.cpp Wed Jun 16 16:51:40 2010 +0300
+++ b/imgtools/romtools/rombuild/r_rom.cpp Wed Jun 23 16:56:47 2010 +0800
@@ -1,2708 +1,2719 @@
-/*
-* Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description:
-*
-*/
-
-
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32uid.h>
-#include "h_utl.h"
-#include <string.h>
-#include <stdlib.h>
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
-#include <iomanip>
-#else //!__MSVCDOTNET__
-#include <iomanip.h>
-#endif //__MSVCDOTNET__
-
-#include "r_global.h"
-#include "r_obey.h"
-#include "r_rom.h"
-#include "r_dir.h"
-#include "patchdataprocessor.h"
-#include "memmap.h"
-#include "byte_pair.h"
-
-const TInt KSpareExports=16;
-extern TInt gThreadNum;
-extern char* gDepInfoFile;
-extern TBool gGenDepGraph;
-
-TUint32 DeflateCompressCheck(char *bytes,TInt size,ostream &os);
-void DeflateCompress(char *bytes,TInt size,ostream &os);
-void InflateUnCompress(unsigned char* source, int sourcesize,unsigned char* dest, int destsize);
-
-EntryQueue* LoadImageWorker::m_queue = NULL;
-TInt LoadImageWorker::m_errors = 0;
-TMemModel LoadImageWorker::m_memmodel;
-boost::mutex LoadImageWorker::m_mutex;
-LoadImageWorker::LoadImageWorker(EntryQueue* aQueue, TMemModel aMemModel)
- {
- m_queue = aQueue;
- m_memmodel = aMemModel;
- }
-void LoadImageWorker::operator()()
- {
- while(1)
- {
- m_mutex.lock();
- if(m_queue->size() > 0)
- {
- TRomBuilderEntry * current = m_queue->front();
- m_queue->pop();
- m_mutex.unlock();
- TInt err = current->OpenImageFile();
- if(err)
- {
- m_mutex.lock();
- ++m_errors;
- m_mutex.unlock();
- continue;
- }
- if(current->iOverrideFlags&KOverrideAddress || current->iHdr->iFlags & KImageFixedAddressExe)
- {
- if(m_memmodel != E_MM_Multiple && m_memmodel != E_MM_Flexible && !current->IsDll())
- current->iRomImageFlags |=KRomImageFlagFixedAddressExe;
- }
- if(gPagedRom)
- {
- if(current->iHdr->iFlags&KImageCodePaged)
- {
- current->iRomImageFlags&=~KRomImageFlagCodeUnpaged;
- current->iRomImageFlags|=KRomImageFlagCodePaged;
- }
- if(current->iHdr->iFlags&KImageCodeUnpaged)
- {
- current->iRomImageFlags|=KRomImageFlagCodeUnpaged;
- current->iRomImageFlags&=~KRomImageFlagCodePaged;
- }
- }
- if(current->iHdr->iFlags&KImageDataPaged)
- {
- current->iRomImageFlags&=~KRomImageFlagDataUnpaged;
- current->iRomImageFlags|=KRomImageFlagDataPaged;
- }
- if(current->iHdr->iFlags&KImageDataUnpaged)
- {
- current->iRomImageFlags|=KRomImageFlagDataUnpaged;
- current->iRomImageFlags&=~KRomImageFlagDataPaged;
- }
- if(current->iHdr->iFlags&KImageDebuggable)
- {
- current->iRomImageFlags|=KRomImageDebuggable;
- }
- else
- {
- current->iRomImageFlags&=~KRomImageDebuggable;
- }
- }
- else
- {
- m_mutex.unlock();
- break;
- }
- }
- }
-E32Rom* CompressPageWorker::m_rom = NULL;
-TInt CompressPageWorker::m_nextpage = 0;
-TInt CompressPageWorker::m_totalpages = 0;
-TInt CompressPageWorker::m_pagesize = 0;
-boost::mutex CompressPageWorker::m_mutex;
-TInt CompressPageWorker::m_error = 0;
-CompressPageWorker::CompressPageWorker(E32Rom* aRom, TInt aPageSize, TInt aTotalPages, TInt aNextPage)
- {
- m_rom = aRom;
- m_pagesize = aPageSize;
- m_totalpages = aTotalPages;
- m_nextpage = aNextPage;
- }
-void CompressPageWorker::operator()()
- {
- SRomPageInfo* pPageBase = (SRomPageInfo*)((TInt)m_rom->iHeader + m_rom->iHeader->iRomPageIndex);
- CBytePair bpe(gFastCompress);
- while(1)
- {
- m_mutex.lock();
- TInt currentPageIndex = m_nextpage++;
- m_mutex.unlock();
- if(currentPageIndex < m_totalpages)
- {
- TInt inOffset = m_pagesize * currentPageIndex;
- TUint8 attrib = (TUint8)SRomPageInfo::EPageable;
- SRomPageInfo info ={ (TUint32)inOffset, (TUint16)m_pagesize, (TUint8)SRomPageInfo::EBytePair, attrib };
- TUint8* in = (TUint8*) m_rom->iHeader + inOffset;
- TUint8* out = in;
- TInt outSize = BytePairCompress(out, in, m_pagesize, &bpe);
- if(outSize == KErrTooBig)
- {
- info.iCompressionType = SRomPageInfo::ENoCompression;
- memcpy(out, in, m_pagesize);
- outSize = m_pagesize;
- }
- if(outSize < 0 )
- {
- m_mutex.lock();
- m_error = outSize;
- m_mutex.unlock();
- break;
- }
- info.iDataSize = (TUint16) outSize;
- *(pPageBase + currentPageIndex) = info;
- if((currentPageIndex & 255) == 255)
- {
- m_mutex.lock();
- Print(EAlways, ".\n");
- m_mutex.unlock();
- }
- }
- else
- {
- break;
- }
- }
- }
-
-////////////////////////////////////////////////////////////////////////
-
-TAddressRange::TAddressRange()
- : iImagePtr(0), iImageAddr(0), iRunAddr(0), iSize(0)
- {
- }
-
-void TAddressRange::Append(TAddressRange& aRange)
- {
- if(aRange.iSize)
- {
- aRange.iImagePtr = iImagePtr;
- aRange.iImageAddr = iImageAddr;
- aRange.iRunAddr = iRunAddr;
- Extend(aRange.iSize);
- }
- }
-
-void TAddressRange::Move(TInt aOffset)
- {
- iImagePtr = static_cast<char*>(iImagePtr) + aOffset;
- iImageAddr += aOffset;
- iRunAddr += aOffset;
- }
-
-void TAddressRange::Extend(TInt aOffset)
- {
- Move(aOffset);
- iSize += aOffset;
- }
-
-////////////////////////////////////////////////////////////////////////
-
-inline TUint32 AlignData(TUint32 anAddr)
- {
- return ((anAddr+0x0f)&~0x0f);
- }
-
-TUint32 E32Rom::AlignToPage(TUint32 anAddr)
- {
- TUint a=(TUint)iObey->iPageSize-1;
- return ((anAddr+a)&~a);
- }
-
-/*
-Allocate virtual memory for static data in rom.
-@param aAddr Base address of last allocated memory.
-@param aSize Size of memory to allocate.
-@return Address allocated. This is below aAddr.
-*/
-TUint32 E32Rom::AllocVirtual(TUint32 aAddr,TUint aSize)
- {
- TInt align = iObey->iVirtualAllocSize;
- if(align<0)
- {
- align = -align; // get correct sign
- // -ve align means also align to next power-of-two >= aSize...
- while(aSize>(TUint)align)
- align <<=1;
- }
-
- TUint mask = (TUint)align-1;
- aSize = (aSize+mask)&~mask; // round up
- aAddr &= ~mask; // round down
- return aAddr-aSize;
- }
-
-TUint32 E32Rom::AlignToChunk(TUint32 anAddr)
- {
- TUint a=(TUint)iObey->iChunkSize-1;
- return ((anAddr+a)&~a);
- }
-
-COrderedFileList::COrderedFileList(TInt aMaxFiles)
- : iCount(0), iMaxFiles(aMaxFiles), iOrderedFiles(NULL)
- {}
-
-COrderedFileList::~COrderedFileList()
- {
- iCount=0;
- delete[] iOrderedFiles;
- }
-
-COrderedFileList* COrderedFileList::New(TInt aMaxFiles)
- {
- COrderedFileList *pL=new COrderedFileList(aMaxFiles);
- pL->iOrderedFiles=new TRomBuilderEntry*[aMaxFiles];
- return pL;
- }
-
-void COrderedFileList::Add(TRomBuilderEntry* anEntry)
- {
- // note: this routine assumes that the set of kernel-mode files
- // (primary/extension/device) required by a given variant is linearly ordered by <=
- // e.g. can't have three variants {A,B,V1} {A,B,C,V2} {A,C,V3} because B and C
- // are unordered with respect to <=, since neither of
- // {n | Vn requires B} and {n | Vn requires C} is a subset of the other.
- // In a case like this, ROMBUILD may fail to resolve the addresses of some global data
- THardwareVariant& v=anEntry->iHardwareVariant;
- TInt i=0;
- while(i<iCount && v<=iOrderedFiles[i]->iHardwareVariant) i++;
- TInt j=iCount;
- while(j>i)
- {
- iOrderedFiles[j]=iOrderedFiles[j-1];
- j--;
- }
- iOrderedFiles[i]=anEntry;
- iCount++;
- }
-
-void GetFileNameAndUid(char *aDllName, TUid &aDllUid, char *aExportName)
- {
- strcpy(aDllName, aExportName);
- aDllUid=KNullUid;
- TInt start;
- for (start=0; start<(TInt)strlen(aExportName) && aExportName[start]!='['; start++)
- ;
- if (start==(TInt)strlen(aExportName))
- start=KErrNotFound;
- TInt end=strlen(aExportName)-1;
- while (end>=0)
- {
- if (aExportName[end]==']')
- break;
- --end;
- }
- if (end<0)
- end=KErrNotFound;
-
- if ((start!=KErrNotFound) && (end!=KErrNotFound) && (end>start))
- {
- // Importing from DLL with Uid
- char uidStr[0x100];
- strcpy(uidStr, "0x");
- strncat(uidStr, aExportName+start+1, end-start-1);
- #ifdef __TOOLS2__
- istringstream val(uidStr);
- #else
- istrstream val(uidStr,strlen(uidStr));
- #endif
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
- val >> setbase(0);
-#endif //__MSVCDOTNET__
-
- TUint32 u;
- val >> u;
- val.peek();
- if (val.eof())
- {
- aDllUid=TUid::Uid(u);
- char *dot=aExportName+strlen(aExportName)-1;
- while (dot>=aExportName)
- {
- if (*dot=='.')
- break;
- dot--;
- }
- if (dot<aExportName) // no dot
- aDllName[start]=0;
- else
- {
- aDllName[start]=0;
- strcat(aDllName, dot);
- }
- }
- }
- }
-
-E32Rom::E32Rom(CObeyFile *aObey)
-//
-// Constructor
-//
- {
-
- iSize=sizeof(TRomLoaderHeader)+aObey->iRomSize;
- iObey=aObey;
- iPeFiles=NULL;
-
- if(gLowMem)
- {
- iImageMap = new Memmap();
-
- if(iImageMap == NULL)
- {
- iSize = 0;
- Print(EError, "Out of memory.\n");
- }
- else
- {
- iImageMap->SetMaxMapSize(iSize);
- if(iImageMap->CreateMemoryMap(0, 0xff) == EFalse)
- {
- iSize = 0;
- Print(EError, "Failed to create image map object");
-
- iImageMap->CloseMemoryMap(ETrue);
- delete iImageMap;
- iImageMap = NULL;
- }
- else
- {
- iData = iImageMap->GetMemoryMapPointer();
- }
- }
- }
- else
- {
- iData=new char [iSize];
- if (iData==NULL)
- {
- iSize=0;
- Print(EError, "Out of memory.\n");
- }
- HMem::Set(iData, 0xff, iSize);
- }
- iHeader=(TRomHeader *)(iData+sizeof(TRomLoaderHeader));
- iExtensionRomHeader=NULL;
- iLoaderHeader=(TRomLoaderHeader *)iData;
- iSectionPtr=(char *)iHeader+aObey->iSectionStart-aObey->iRomLinearBase+sizeof(TRomSectionHeader);
- TheRomHeader=(ImpTRomHeader *)iHeader;
- TheRomMem=(TUint32)iHeader;
- iNextDataChunkBase=aObey->iKernDataRunAddress;
- iTotalSvDataSize=0;
- iNextDllDataAddr=aObey->iDllDataTop;
- iPrevPrimaryAddress=NULL;
- iPrevVariantAddress=NULL;
- iVariantFileLists=NULL;
- iImportsFixedUp=0;
- iBranchesFixedUp=0;
- iVtableEntriesFixedUp=0;
- iOverhead=0;
- }
-
-E32Rom::~E32Rom()
-//
-// Destructor
-//
- {
-
- if(gLowMem)
- {
- iImageMap->CloseMemoryMap(ETrue);
- delete iImageMap;
- }
- else
- delete iData;
- delete [] iPeFiles;
- if (iVariantFileLists)
- {
- TInt i;
- for (i=0; i<iObey->iNumberOfVariants; i++)
- delete iVariantFileLists[i];
- delete [] iVariantFileLists;
- }
- }
-
-TInt E32Rom::Align(TInt aVal)
-//
-// Align to romalign
-//
- {
-
- return ((aVal+iObey->iRomAlign-1)/iObey->iRomAlign)*iObey->iRomAlign;
- }
-
-TInt E32Rom::LoadContents(char*& anAddr, TRomHeader* aHeader)
- {
- // Load all the PE/E32Image files
- TInt nfiles=iObey->iNumberOfPeFiles;
- iPeFiles=new TRomBuilderEntry* [nfiles];
- if (!iPeFiles)
- return Print(EError, "Out of memory.\n");
-
- TInt r=TranslateFiles();
- if (r!=KErrNone)
- return r;
-
- ProcessDllData();
-
- EnumerateVariants();
-
- r=BuildDependenceGraph();
- if (r!=KErrNone)
- return r;
-
- // Update the ROM image headers with SMP information.
- SetSmpFlags();
-
- r=ProcessDependencies();
- if (r!=KErrNone)
- return r;
-
- char* addr = anAddr;
- TRomExceptionSearchTable* exceptionSearchTable = 0;
-
- if(gPagedRom)
- {
- gDepInfoFile = (char* )malloc(strlen((char *)iObey->iRomFileName) + 1);
- strcpy(gDepInfoFile, (char *)iObey->iRomFileName);
- iObey->SetArea().DefaultArea()->SortFilesForPagedRom();
- // exception search table needs to go at start of ROM to make it not demand paged...
- addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable);
- }
- else if(gGenDepGraph)
- {
- Print(EWarning, "Not dependence information in an unpaged ROM.");
- }
-
- addr=WriteDirectory(addr, aHeader);
- // Aligned
-
- TRACE(TSCRATCH,Print(EAlways,"Directory written\n"));
-
- // Stick all the files in ROM
-
- TReloc* relocationTable;
- addr = AllocateRelocationTable(addr, relocationTable);
- aHeader->iRelocInfo = relocationTable ? ActualToRomAddress(relocationTable) : 0;
- // Aligned
-
- TRACE(TSCRATCH,Print(EAlways,"Done AllocateRelocationTable\n"));
-
- CalculateDataAddresses();
- addr = LayoutRom(addr);
-
- TRACE(TSCRATCH,Print(EAlways,"Done LayoutRom\n"));
-
- FillInRelocationTable(relocationTable);
-
- TRACE(TSCRATCH,Print(EAlways,"Done FillInRelocationTable\n"));
-
- if(!exceptionSearchTable)
- addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable);
- ConstructRomExceptionSearchTable(exceptionSearchTable);
-
- TRACE(TSCRATCH,Print(EAlways,"Done ConstructRomExceptionSearchTable\n"));
-
- LinkKernelExtensions(iObey->iExtensions, iObey->iNumberOfExtensions);
-
- TRACE(TSCRATCH,Print(EAlways,"Done LinkKernelExtensions\n"));
-
- r=ResolveDllRefTables();
- if (r!=KErrNone)
- return r;
- r=ResolveImports();
- if (r!=KErrNone)
- return r;
- if (iObey->iCollapseMode>ECollapseNone)
- {
- r=CollapseImportThunks();
- if (r!=KErrNone)
- return r;
- if (iObey->iCollapseMode>ECollapseImportThunksOnly)
- {
- r=CollapseBranches();
- if (r!=KErrNone)
- return r;
- }
- Print(ELog,"%d imports, %d branches, %d vtable entries fixed up\n",
- iImportsFixedUp,iBranchesFixedUp,iVtableEntriesFixedUp);
- }
-
- iSizeUsed=(TInt)addr-(TInt)iHeader;
- Print(ELog, "\n%08x of %08x bytes used.\n", iSizeUsed, iSize-sizeof(TRomLoaderHeader));
-
- // round the rom size in the header to a multiple of 1 Megabyte
- TInt rounded = ((iSizeUsed+0xfffff)&0xfff00000);
- if (rounded < iObey->iRomSize)
- iObey->iRomSize = rounded;
- iUncompressedSize = iSizeUsed;
-
- anAddr = addr;
-
- return KErrNone;
- }
-
-
-void E32Rom::CreatePageIndex(char*& aAddr)
- {
- iHeader->iRomPageIndex = 0;
- if(gPagedRom==0 || gEnableCompress==0)
- return;
-
- // Insert space for Rom Page Info table...
- iHeader->iRomPageIndex = (TInt)aAddr-(TInt)iHeader;
- TInt pageSize = iObey->iPageSize;
- TInt numPages = iSize/pageSize+1;
- TInt pageInfoSize = numPages*sizeof(SRomPageInfo);
-
- gPageIndexTableSize = pageInfoSize; // For accumulate uncompressed un-paged size added Page Index Table
-
- Print(ELog, "Inserting %d bytes for RomPageInfo at ROM offset 0x%08x\n", pageInfoSize, iHeader->iRomPageIndex);
- memset(aAddr,0,pageInfoSize);
- iOverhead += pageInfoSize;
- aAddr += pageInfoSize;
- }
-
-TInt E32Rom::SetupPages()
- {
- iHeader->iPageableRomStart = 0;
- iHeader->iPageableRomSize = 0;
- iHeader->iDemandPagingConfig = gDemandPagingConfig;
-
- if(!gPagedRom)
- return KErrNone;
-
- // Initialise the Rom Page Info for each page which indicates it is uncompressed...
- TInt pageSize = iObey->iPageSize;
-
- TInt pagedStartOffset = 0x7fffffff;
- TRomBuilderEntry* e = iObey->SetArea().DefaultArea()->iFirstPagedCode;
- if(e)
- {
- // we have paged code...
- pagedStartOffset = e->RomEntry()->iAddressLin-iObey->iRomLinearBase;
- pagedStartOffset = (pagedStartOffset+pageSize-1)&~(pageSize-1); // round up to next page;
- iHeader->iPageableRomStart = pagedStartOffset;
- TInt pageableSize = iSizeUsed-pagedStartOffset;
- if(pageableSize>0)
- iHeader->iPageableRomSize = pageableSize;
- }
-
- return KErrNone;
- }
-
-TInt E32Rom::CompressPages()
- {
-
- if(!gPagedRom || !gEnableCompress)
- return KErrNone;
-
- // Initialise the Rom Page Info for each page which indicates it is uncompressed...
- TInt pageSize = iObey->iPageSize;
- TInt numPages = (iSizeUsed+pageSize-1)/pageSize;
-
- TInt pagedStartOffset = iHeader->iPageableRomStart;
-
- Print(EAlways, "\nCompressing pages...\n");
- TInt inOffset = 0;
- SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex);
- TInt currentIndex = 0;
- while(inOffset < pagedStartOffset)
- {
-
- TUint8 attrib = (TUint8)0;
- SRomPageInfo info = {(TUint32)inOffset,(TUint16)pageSize,(TUint8)SRomPageInfo::EBytePair,(TUint8)attrib};
- info.iDataSize = (TUint16) pageSize;
- *pi++ = info;
- inOffset += pageSize;
- if((currentIndex & 255) == 255)
- Print(EAlways, ".\n");
- currentIndex++;
- }
- CompressPageWorker compressworker(this, pageSize, numPages, currentIndex);
-
- boost::thread_group threads;
- for(int i = 0; i < gThreadNum; i++)
- {
- threads.create_thread(compressworker);
- }
- threads.join_all();
- if(compressworker.m_error < 0)
- return compressworker.m_error;
- for(;currentIndex < numPages - 1; currentIndex++)
- {
- pi++;
- SRomPageInfo* prev = pi - 1;
- TUint8* dest = (TUint8*) iHeader + prev->iDataStart + prev->iDataSize;
- TUint8* src = (TUint8*) iHeader + pi->iDataStart;
- memcpy(dest, src, pi->iDataSize);
- pi->iDataStart = prev->iDataStart + prev->iDataSize;
- }
- TInt relSize = pi->iDataStart + pi->iDataSize;
-
- memset((TUint8*)iHeader + relSize, 0xff, iSizeUsed - relSize);
- TInt compression = (iSizeUsed >= 1000) ? (relSize*10)/(iSizeUsed/1000) : (relSize*10000)/iSizeUsed;
- Print(EAlways, "%d.%02d%%\n", compression/100, compression%100);
- iSizeUsed = relSize;
- return KErrNone;
- }
-
-TInt E32Rom::CompressPage(SRomPageInfo& aPageInfo, TInt aOutOffset, CBytePair * aBPE)
- {
- TUint8* in = (TUint8*)iHeader+aPageInfo.iDataStart;
- TInt inSize = aPageInfo.iDataSize;
- TUint8* out = (TUint8*)iHeader+aOutOffset;
- switch(aPageInfo.iCompressionType)
- {
- case SRomPageInfo::ENoCompression:
- memcpy(out,in,inSize);
- return inSize;
-
- case SRomPageInfo::EBytePair:
- {
- TInt r = BytePairCompress(out, in, inSize, aBPE);
- if(r!=KErrTooBig)
- return r;
- // data can't be compressed...
- aPageInfo.iCompressionType = SRomPageInfo::ENoCompression;
- memcpy(out,in,inSize);
- return inSize;
- }
-
- default:
- Print(EError, "Unsupported page compression type (%d)\n", aPageInfo.iCompressionType);
- return KErrNotSupported;
- }
- }
-
-
-// Avoid "warning" about constant expression
-static void checksize(const char* aTypeName, int aSize, int aCorrectSize)
- {
- if (aSize != aCorrectSize)
- Print(EError, "sizeof(%s) = %d, should be %d\n", aTypeName, aSize, aCorrectSize);
- }
-
-TInt E32Rom::CreateExtension(MRomImage* aKernelRom)
- {
-
- // sanity check
- checksize("TExtensionRomHeader", sizeof(TExtensionRomHeader), 128);
-
- char *addr=(char *)iHeader;
- iExtensionRomHeader=(TExtensionRomHeader*)addr;
- addr += sizeof(TExtensionRomHeader);
- // Aligned
-
- TRomHeader dummy;
- TInt r=LoadContents(addr, &dummy);
- if (r!=KErrNone)
- {
- Print(EError, "LoadContents failed - return code %d\n", r);
- return r;
- }
- iExtensionRomHeader->iRomRootDirectoryList = dummy.iRomRootDirectoryList;
-
- iLoaderHeader->SetUp(iObey);
- FinaliseExtensionHeader(aKernelRom);
- DisplayExtensionHeader();
-
- return KErrNone;
- }
-
-TInt E32Rom::Create()
- {
-
- TVariantList::Setup(iObey);
- char *addr=(char *)iHeader;
- // Aligned
-
- // Put the bootstrap in rom - it contains a hole at offset 0x80 where the
- // TRomHeader information will be placed later
-
- gBootstrapSize = HFile::Read(iObey->iBootFileName, iHeader);
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "bootstrapSize: 0x%08x, (%d)\n", gBootstrapSize, gBootstrapSize);
-
- if (gBootstrapSize==0)
- return Print(EError, "Cannot open the bootstrap file '%s'.\n", iObey->iBootFileName);
- gBootstrapSize=Align(gBootstrapSize);
- addr+=gBootstrapSize;
- iOverhead=gBootstrapSize;
- // Aligned
-
- CreatePageIndex(addr);
-
- TInt r=LoadContents(addr, iHeader);
- if (r!=KErrNone)
- {
- Print(EError, "LoadContents failed - return code %d\n", r);
- return r;
- }
-
- r = SetupPages(); // initialize ROM paging info...
- if(r!=KErrNone)
- {
- Print(EError, "Setup pages information failed - return code %d\n", r);
- return r;
- }
-
- r = CheckUnpagedMemSize(); // check for unpaged memory overflow
- if(r!=KErrNone)
- {
- return r;
- }
-
- r = CompressPages(); // setup ROM paging info...
- if(r!=KErrNone)
- {
- Print(EError, "CompressPages failed - return code %d\n", r);
- return r;
- }
-
- iLoaderHeader->SetUp(iObey);
- ImpTRomHeader* header = (ImpTRomHeader *)iHeader;
- header->SetUp(iObey);
- header->iTotalSvDataSize=iTotalSvDataSize;
- if (iObey->iMemModel==E_MM_Direct)
- {
- header->iUserDataAddress=iObey->iDataRunAddress;
- header->iTotalUserDataSize=iNextDataChunkBase-iObey->iDataRunAddress;
- }
- else
- {
- header->iUserDataAddress=iObey->iDllDataTop;
- header->iTotalUserDataSize=iObey->iDllDataTop-iNextDllDataAddr;
- }
- if (header->iRomSectionHeader)
- FinaliseSectionHeader(); // sorts out the second section checksum
-
- header->CheckSum(iObey->iCheckSum); // finally, sort out the overall checksum
-
- header->Display();
-
- TUint testCheckSum = HMem::CheckSum((TUint *)iHeader, iHeader->iRomSize);
- Print(ELog, "Rom 32bit words sum to %08x\n", testCheckSum);
- if (testCheckSum != iObey->iCheckSum)
- return Print(EError, "Rom checksum is incorrect: %08x should be %08x\n",
- testCheckSum, iObey->iCheckSum);
-
- // 8bit checksum = sum of bytes
- // odd/even checksum = checksum of the odd and even halfwords of the image
-
- Print(ELog, "Rom 8bit checksum %08x\n", HMem::CheckSum8((TUint8 *)iHeader, iHeader->iRomSize));
- Print(ELog, "Rom 8bit odd checksum %08x\n", HMem::CheckSumOdd8((TUint8 *)iHeader, iHeader->iRomSize));
- Print(ELog, "Rom 8bit even checksum %08x\n", HMem::CheckSumEven8((TUint8 *)iHeader, iHeader->iRomSize));
-
- if (iHeader->iPrimaryFile)
- {
- if (iObey->iKernelModel==ESingleKernel)
- {
- Print(ELog,"\nPrimary details (Single Kernel):\n");
- TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader);
- TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader);
- Display(hdr);
- Print(ELog,"\n");
- }
- else if (iObey->iKernelModel==EMultipleKernels)
- {
- Print(ELog,"\nPrimary details (Multiple Kernels):\n");
- TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader);
- TInt n=1;
- FOREVER
- {
- Print(ELog,"\nKernel %d:\n",n);
- TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader);
- Display(hdr);
- Print(ELog,"\n");
- if (!hdr->iNextExtension)
- break;
- r=(TRomEntry*)(hdr->iNextExtension-iObey->iRomLinearBase+(char*)iHeader);
- n++;
- }
- }
- }
-
- return KErrNone;
- }
-
-char *E32Rom::WriteDirectory(char *aAddr, TRomHeader* aHeader)
-//
-// Write the directory structure where appropriate
-//
- {
-
- TLinAddr dirptr=ActualToRomAddress(aAddr);
- if (iObey->iSectionPosition==-1)
- {
- // Just the one rom. Put the directory structure at aAddr
- iDirectorySize=WriteHeadersToRom(aAddr);
- aAddr+=Align(iDirectorySize);
- }
- else
- {
- // Put the directory structure in the second ROM, after the SectionHeader
- // and the second section information for first section files
- TInt size=0;
- TInt i;
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRomBuilderEntry *file=iPeFiles[i];
- if (file->iRomSectionNumber!=0)
- break;
- TInt size1, size2;
- file->SizeInSections(size1,size2);
- size+=size2;
- }
- dirptr=ActualToRomAddress(iSectionPtr)+size;
- iDirectorySize=WriteHeadersToRom(RomToActualAddress(dirptr));
- }
- aHeader->iRomRootDirectoryList=dirptr;
- return aAddr;
- }
-
-void E32Rom::Display(TRomImageHeader *aHdr)
-//
-// Print info on a file
-//
- {
- TRACE(TAREA, Print(ELog, "+Display header %08x\n", aHdr));
- Print(ELog, "Uids: %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum);
- Print(ELog, "Entry point: %08x\n", aHdr->iEntryPoint);
- Print(ELog, "Code start addr: %08x\n", aHdr->iCodeAddress);
- Print(ELog, "Data start addr: %08x\n", aHdr->iDataAddress);
- Print(ELog, "DataBssLinearBase: %08x\n", aHdr->iDataBssLinearBase);
- Print(ELog, "Text size: %08x\n", aHdr->iTextSize);
- Print(ELog, "Code size: %08x\n", aHdr->iCodeSize);
- Print(ELog, "Data size: %08x\n", aHdr->iDataSize);
- Print(ELog, "BssSize: %08x\n", aHdr->iBssSize);
- Print(ELog, "Total data size: %08x\n", aHdr->iTotalDataSize);
- Print(ELog, "Heap min: %08x\n", aHdr->iHeapSizeMin);
- Print(ELog, "Heap max: %08x\n", aHdr->iHeapSizeMax);
- Print(ELog, "Stack size: %08x\n", aHdr->iStackSize);
- Print(ELog, "Dll ref table: %08x\n", aHdr->iDllRefTable);
- Print(ELog, "Export directory: %08x\n", aHdr->iExportDir);
- Print(ELog, "Export dir count: %08x\n", aHdr->iExportDirCount);
- Print(ELog, "Hardware variant: %08x\n", aHdr->iHardwareVariant);
- Print(ELog, "Flags: %08x\n", aHdr->iFlags);
- Print(ELog, "Secure ID: %08x\n", aHdr->iS.iSecureId);
- Print(ELog, "Vendor ID: %08x\n", aHdr->iS.iVendorId);
- Print(ELog, "Capability: %08x %08x\n", aHdr->iS.iCaps[1], aHdr->iS.iCaps[0]);
- Print(ELog, "Tools Version: %d.%02d(%d)\n", aHdr->iToolsVersion.iMajor, aHdr->iToolsVersion.iMinor, aHdr->iToolsVersion.iBuild);
- Print(ELog, "Module Version: %d.%d\n", aHdr->iModuleVersion>>16, aHdr->iModuleVersion&0x0000ffffu);
- Print(ELog, "Exception Descriptor: %08x\n", aHdr->iExceptionDescriptor);
- Print(ELog, "Priority: %d\n", aHdr->iPriority);
- }
-
-void E32Rom::DisplaySizes(TPrintType aWhere)
- {
-
- Print(aWhere, "Summary of file sizes in rom:\n");
- Print(aWhere, "Overhead (bootstrap+gaps+sectioning)\t%d\n", iOverhead);
- Print(aWhere, "Overhead (directory size)\t%d\n", iDirectorySize);
- TRomBuilderEntry *file=iObey->FirstFile();
- while (file)
- {
- file->DisplaySize(aWhere);
- file=iObey->NextFile();
- }
- Print(aWhere, "\nTotal used\t%d\n", iSizeUsed);
- Print(aWhere, "Free\t%d\n", iObey->iRomSize-iSizeUsed);
-
- if (iObey->SetArea().Count() > 1)
- {
- Print(aWhere, "\nArea summary:\n");
- for (NonDefaultAreasIterator it(iObey->SetArea());
- ! it.IsDone();
- it.GoToNext())
- {
- const Area& a = it.Current();
- Print(aWhere, "%s\t used: %d bytes / free: %d bytes\n",
- a.Name(), a.UsedSize(), a.MaxSize()-a.UsedSize());
- }
- }
- }
-
-TInt E32Rom::RequiredSize()
-//
-// Get the (approximate) required size of the Rom
-//
- {
-
- TInt sum=0;
- TRomBuilderEntry *current=iObey->FirstFile();
- while (current)
- {
- if (current->iResource || current->HCRDataFile())
- sum+=Align(HFile::GetLength((TText*)current->iFileName));
- else
- sum+=Align(current->SizeInRom());
- current=iObey->NextFile();
- }
- return sum+iOverhead+Align(iDirectorySize);
- }
-
-TInt E32Rom::TranslateFiles()
-//
-// Load and translate all PE/E32 image files
-//
- {
-
- TInt i=0;
- TInt total_errors = 0;
- TRomBuilderEntry* current = 0;
- EntryQueue imagesQueue;
- for (current = iObey->FirstFile(); current; current = iObey->NextFile() )
- {
- if ((!current->iResource) && (!current->HCRDataFile()))
- {
- iPeFiles[i++]=current;
- imagesQueue.push(current);
- }
- }
- LoadImageWorker loadworker(&imagesQueue, iObey->iMemModel);
- boost::thread_group threads;
- for(int i = 0; i < gThreadNum; i++)
- {
- threads.create_thread(loadworker);
- }
- threads.join_all();
-
- total_errors = loadworker.m_errors;
- if (total_errors)
- return KErrGeneral;
- for (current = iObey->FirstFile(); current; current = iObey->NextFile() )
- {
- if ((!current->iResource) && (!current->HCRDataFile()))
- {
- TInt err = CheckForVersionConflicts(current);
- total_errors += err;
- }
- }
- return total_errors ? KErrGeneral : KErrNone;
- }
-
-const TText FileTypeFile[]= "File ";
-const TText FileTypePrimary[]= "Primary ";
-const TText FileTypeVariant[]= "Variant ";
-const TText FileTypeExtension[]="Extension";
-const TText FileTypeDevice[]= "Device ";
-
-void E32Rom::EnumerateVariants()
- {
- TInt vIndex;
- TInt nFiles=iObey->iNumberOfExtensions+iObey->iNumberOfDevices+3;
- iVariantFileLists=new COrderedFileList*[iObey->iNumberOfVariants];
- for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
- iVariantFileLists[vIndex]=COrderedFileList::New(nFiles);
- for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
- {
- TRomBuilderEntry *variant=iObey->iVariants[vIndex];
- THardwareVariant& v=variant->iHardwareVariant;
- TInt i;
- for (i=0; i<iObey->iNumberOfPrimaries; i++)
- {
- TRomBuilderEntry *primary=iObey->iPrimaries[i];
- if (v<=primary->iHardwareVariant)
- {
- iVariantFileLists[vIndex]->Add(primary);
- break;
- }
- }
- iVariantFileLists[vIndex]->Add(variant);
- for (i=0; i<iObey->iNumberOfExtensions; i++)
- {
- TRomBuilderEntry *ext=iObey->iExtensions[i];
- if (v<=ext->iHardwareVariant)
- {
- iVariantFileLists[vIndex]->Add(ext);
- }
- }
- for (i=0; i<iObey->iNumberOfDevices; i++)
- {
- TRomBuilderEntry *dev=iObey->iDevices[i];
- if (v<=dev->iHardwareVariant)
- {
- iVariantFileLists[vIndex]->Add(dev);
- }
- }
- }
- TUint totalDataBss=0;
- for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
- {
- TRomBuilderEntry *variant=iObey->iVariants[vIndex];
- THardwareVariant& v=variant->iHardwareVariant;
- COrderedFileList& files=*iVariantFileLists[vIndex];
- TInt count=files.Count();
- Print(ELog,"\nVariant %08x, %d Files:\n",v.ReturnVariant(),count);
- TInt i;
- TUint dataOffset=0;
- for (i=0; i<count; i++)
- {
- TRomBuilderEntry *pF=files[i];
- TUint gap=0;
- if (pF->iDataAlignment>0)
- {
- gap=(pF->iDataAlignment-dataOffset)%(pF->iDataAlignment);
- dataOffset+=gap;
- }
- E32ImageHeader *pH=pF->iHdr;
- if (pF->iDataBssOffset!=0xffffffff && pF->iDataBssOffset!=dataOffset)
- Print(EError,"Conflicting DataBss addresses\n");
- pF->iDataBssOffset=dataOffset;
- TInt dataSize=AlignData(pH->iDataSize+pH->iBssSize);
- const TText* pT=FileTypeFile;
- if (pF->Primary())
- pT=FileTypePrimary;
- if (pF->Variant())
- pT=FileTypeVariant;
- if (pF->Extension())
- pT=FileTypeExtension;
- if (pF->Device())
- pT=FileTypeDevice;
- Print(ELog,"%s %12s[%08x] DataSize=%6x DataOffset=%6x",pT,pF->iName,pF->iHardwareVariant.ReturnVariant(),dataSize,dataOffset);
- if (gap)
- Print(ELog, " (gap %x for %x alignment)\n", gap, pF->iDataAlignment);
- Print(ELog, "\n");
- dataOffset+=dataSize;
- }
- if (dataOffset>totalDataBss)
- totalDataBss=dataOffset;
- }
- Print(ELog,"\nTotal SvData size=%6x\n",totalDataBss);
- iTotalSvDataSize=totalDataBss;
- }
-
-TInt E32Rom::LoadDataToRom(TRomBuilderEntry *aFile, TAddressRange& aAddress, CBytePair* aBPE)
-//
-// Load a data file to rom
-//
- {
- const char* tn = "resource";
- if (aFile->iNonXIP)
- tn = (aFile->iCompression) ? "compressed executable" : "uncompressed executable";
- Print(ELog,"Reading %s %s to rom linear address %08x\n", tn, aFile->iFileName, aAddress.iImageAddr);
-
- TUint32 size=HFile::GetLength((TText*)aFile->iFileName);
- if (size==0)
- {
- Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",aFile->iFileName);
- return size;
- }
-
- aFile->iHeaderRange=aAddress;
- char* addr = (char*)aFile->iHeaderRange.iImagePtr;
- const char* src = NULL;
- #ifdef __TOOLS2__
- ostringstream os;
- #else
- ostrstream os;
- #endif
- if (aFile->iNonXIP)
- {
- E32ImageFile f(aBPE);
- TInt r = f.Open(aFile->iFileName);
- // is it really a valid E32ImageFile?
- if (r != KErrNone)
- {
- Print(EWarning, "File '%s' is not a valid executable. Loading file as data.\n", aFile->iFileName);
- aFile->iNonXIP = EFalse;
- }
- else
- {
- TUint compression = f.iHdr->CompressionType();
- if (compression != aFile->iCompression || aFile->iPreferred)
- {
- if (compression == 0)
- Print(ELog, "Compressing file %s\n", aFile->iFileName);
- else if (aFile->iCompression == 0)
- Print(ELog, "Decompressing file %s\n", aFile->iFileName);
- f.iHdr->iCompressionType = aFile->iCompression;
- if (aFile->iPreferred)
- {
- f.iHdr->iModuleVersion &= ~0xffffu;
- f.iHdr->iModuleVersion |= 0x8000u;
- }
- f.UpdateHeaderCrc();
- }
- Print(ELog, "Compression Method:0x%08x/0x%08x \n", f.iHdr->CompressionType(), aFile->iCompression);
- os << f;
- #ifdef __TOOLS2__
- size = (os.str()).length();
- src = (os.str()).c_str();
- #else
- size = os.pcount();
- src = os.str();
- #endif
- }
- }
- if (addr+size>iData+iSize)
- {
- Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName);
- Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize);
- exit(667);
- }
- if (src)
- memcpy(addr, src, size);
- else
- size = HFile::Read((TText*)aFile->iFileName, (TAny *)addr);
- Print(ELog,"Size: %08x\n", size);
-
- aFile->iHeaderRange.iSize=size;
- aAddress.Extend(aFile->iHeaderRange.iSize);
- return size;
- }
-
-
-void E32Rom::CalculateDataAddresses()
-//
-//
-//
- {
-
- TInt i;
- TUint32 maxkern = 0;
- Print(ELog, "\nCalculating kernel limit.\n");
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRomBuilderEntry* e = iPeFiles[i];
- if (e->Primary())
- {
- // this is a kernel
- TUint32 stack = AlignToPage(e->iHdr->iStackSize);
- TUint32 heap = AlignToPage(e->iHdr->iHeapSizeMax);
- if (stack + heap > maxkern)
- maxkern = stack + heap;
- }
- }
- iObey->iKernelLimit = AlignToChunk(maxkern + iTotalSvDataSize) + iObey->iKernDataRunAddress;
- if (iObey->iMemModel==E_MM_Direct)
- iNextDataChunkBase=iObey->iDataRunAddress;
- else
- iNextDataChunkBase = iObey->iKernelLimit;
- Print(ELog, "\nCalculating data addresses.\n");
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRACE(TAREA,Print(ELog,"CalculateDataAddresses %d %s\n",i,iPeFiles[i]->iFileName));
- CalculateDataAddress(iPeFiles[i]);
- }
- TRACE(TIMPORT,Print(ELog,"CalculateDataAddresses complete\n"));
-
- // On moving model, advance kernel limit past fixed process data areas
- if (iObey->iMemModel==E_MM_Moving)
- iObey->iKernelLimit = iNextDataChunkBase;
- }
-
-void E32Rom::CalculateDataAddress(TRomBuilderEntry *aFile)
-//
-// Work out where the .data/.bss will be
-//
- {
- TUint32 dataBssSize=aFile->iRomNode->iRomFile->iTotalDataBss;
- TUint32 dataRunAddr;
- if (aFile->Primary())
- {
- dataRunAddr = iObey->iKernDataRunAddress;
- CPU = aFile->iHdr->CpuIdentifier();
- }
- else
- {
- dataRunAddr = iObey->iDataRunAddress;
- if (iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible && (aFile->iHdr->iFlags & KImageFixedAddressExe)) // propagate 'fixed' from PETRAN
- {
- dataRunAddr=0xffffffff;
- }
- }
- if (aFile->iOverrideFlags&KOverrideAddress)
- {
- if ((iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible) || aFile->iRelocationAddress!=0xffffffff)
- dataRunAddr=aFile->iRelocationAddress;
- if (aFile->Extension() || aFile->Variant() || aFile->Device())
- Print(EError, "reloc not permitted with extension/variant/device\n");
- }
- if (!aFile->IsDll() && !aFile->Primary() && (dataRunAddr==0xffffffff || iObey->iMemModel==E_MM_Direct))
- {
- dataRunAddr=iNextDataChunkBase;
- TInt stackreserve=iObey->iDefaultStackReserve;
- if (aFile->iOverrideFlags & KOverrideStackReserve)
- stackreserve=aFile->iStackReserve;
- TInt datsize=AlignToChunk(dataBssSize+stackreserve);
- // Move target data address to next free chunk
- iNextDataChunkBase+=datsize;
- }
- if (aFile->Extension() || aFile->Device() || aFile->Variant())
- {
- dataRunAddr=iObey->iKernDataRunAddress+aFile->iDataBssOffset;
- }
- else if (aFile->IsDll() && dataBssSize!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe<0)
- {
- iNextDllDataAddr = AllocVirtual(iNextDllDataAddr,dataBssSize);
- dataRunAddr=iNextDllDataAddr;
- }
- if (iObey->iMemModel==E_MM_Moving && dataRunAddr==iObey->iDataRunAddress && aFile->Secondary())
- {
- Print(EWarning,"Secondary not fixed\n");
- }
-
- TRACE(TAREA, Print(ELog, "Data run address %08x\n", dataRunAddr));
- aFile->iDataBssLinearBase=dataRunAddr;
- }
-
-void E32Rom::LoadFileToRom(TRomBuilderEntry *aFile)
-//
-// Load an E32Image/PE file to rom
-//
- {
-
- char* addr = (char*)aFile->iHeaderRange.iImagePtr;
- TRACE(TAREA, Print(ELog,"+LoadFileToRom addr %08x %08x %08x\n", addr,
- aFile->iHeaderRange.iImageAddr, aFile->iHeaderRange.iRunAddr));
-
- if (addr+aFile->SizeInRom()>iData+iSize) // check this
- {
- Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName);
- Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize);
- exit(666);
- }
-
- // check file will not overflow into next ROM
- if (aFile->Primary())
- {
- if (!iPrevPrimaryAddress)
- iHeader->iPrimaryFile=ActualToRomAddress(aFile->RomEntry());
- else if (iObey->iKernelModel==EMultipleKernels)
- {
- ((TRomImageHeader*)iPrevPrimaryAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry());
- }
- iPrevPrimaryAddress=addr;
- TRACE(TAREA, Print(ELog, "iHeader->iPrimaryFile = %08x\n", iHeader->iPrimaryFile));
- }
-
- // Place the file in rom
- if (aFile->Variant())
- {
- if (iPrevVariantAddress)
- ((TRomImageHeader*)iPrevVariantAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry());
- else
- iHeader->iVariantFile=ActualToRomAddress(aFile->RomEntry());
- iPrevVariantAddress=addr;
- }
- if (aFile->IsDll() && aFile->iRomNode->iRomFile->iTotalDataBss!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe>=0)
- {
- TRomFile* f=aFile->iRomNode->iRomFile->iPDeps[0]; // attach process
- aFile->iDataBssLinearBase = f->DataBssLinearBase() + aFile->iRomNode->iRomFile->iDataBssOffsetInExe;
- }
-
- aFile->LoadToRom();
- }
-
-char *E32Rom::LayoutRom(char *romaddr)
-//
-// Layout the files from the obey file starting at romaddr in the image
-// dealing correctly with areas
-// Also deals with two section ROMs
-//
- {
-
- TAddressRange main;
- TAddressRange* mainptr=&main;
- SetImageAddr(main, romaddr);
-
- TAddressRange second;
- TAddressRange* secondptr=0;
- if (iObey->iSectionStart != 0)
- {
- SetImageAddr(second,iSectionPtr);
- secondptr = &second;
- }
-
- TInt fileCount=0;
-
- //
- // Process files in non default areas
- //
-
- CBytePair bpe(gFastCompress);
- for (NonDefaultAreasIterator areaIt(iObey->SetArea());
- ! areaIt.IsDone();
- areaIt.GoToNext())
- {
- Area& currentArea = areaIt.Current();
- currentArea.SetSrcBaseAddr(mainptr->iImageAddr);
-
- mainptr->iRunAddr = currentArea.DestBaseAddr();
-
- for (FilesInAreaIterator fileIt(currentArea);
- ! fileIt.IsDone();
- fileIt.GoToNext())
- {
- TRomBuilderEntry* currentFile = fileIt.Current();
-
- LayoutFile(currentFile, *mainptr, secondptr, &bpe);
-
- TUint overflow;
- if (! currentArea.ExtendSrcLimitAddr(mainptr->iImageAddr, overflow))
- {
- Print(EError, "Can't fit '%s' in area '%s'\n", currentFile->iFileName, currentArea.Name());
- Print(EError, "Area overflowed by 0x%x bytes.\n", overflow);
- exit(666);
- }
-
- ++fileCount;
- assert(iObey->iSectionPosition == -1 || fileCount < iObey->iSectionPosition);
- }
-
- TInt offset=(char*)mainptr->iImagePtr-romaddr;
- mainptr->Extend(Align(offset)-offset);
- } // for every non default area
-
-
- //
- // Process files in default area
- //
-
- mainptr->iRunAddr = mainptr->iImageAddr;
-
- for (FilesInAreaIterator fileIt(*(iObey->SetArea().DefaultArea()));
- ! fileIt.IsDone();
- fileIt.GoToNext())
- {
- if (fileCount==iObey->iSectionPosition)
- {
- // skip rest of first section and pick up after the
- // information already accumulated in the second section
- NextRom(mainptr, secondptr);
- mainptr = secondptr;
- secondptr = 0;
- }
-
- LayoutFile(fileIt.Current(), *mainptr, secondptr, &bpe);
-
- ++fileCount;
- }
-
- // align to likely position of next file
- TInt offset=(char*)mainptr->iImagePtr-romaddr;
- offset = Align(offset)-offset;
- mainptr->Extend(offset);
- iOverhead +=offset;
-
- return (char*)mainptr->iImagePtr;
- }
-
-void E32Rom::LayoutFile(TRomBuilderEntry* current, TAddressRange& aMain, TAddressRange* aSecond, CBytePair * aBPE)
-//
-// Work out where to place a file in ROM and set up the
-// appropriate TAddressRange information
-//
- {
- TInt alignment = iObey->iRomAlign;
- if (current->iAlignment > alignment)
- alignment = current->iAlignment;
-
- if (alignment)
- {
- // Align this file on a boundary
- TUint32 romaddr=aMain.iRunAddr;
- TInt i=romaddr & (alignment-1);
- TInt gap=0;
- if (i!=0)
- gap=alignment-i;
- if (current->iAlignment)
- Print(ELog, "\nAlign to %08x. Skipped %d bytes\n", romaddr+gap, gap);
- aMain.Extend(gap);
- iOverhead += gap;
- }
-
- if (current->iCodeAlignment != 0)
- {
- TUint32 runaddr=aMain.iRunAddr + sizeof(TRomImageHeader);
- TInt i=runaddr & (current->iCodeAlignment-1);
- TInt gap=0;
- if (i!=0)
- gap=current->iCodeAlignment-i;
- Print(ELog, "\nCode Align to %08x. Skipped %d bytes\n", runaddr+gap, gap);
- aMain.Extend(gap);
- iOverhead += gap;
- }
-
- Print(ELog,"\n********************************************************************\n");
-
- if (current->iPatched)
- Print(ELog, "[Patched file]\n");
-
- if (current->iResource)
- {
- TInt size=LoadDataToRom(current, aMain, aBPE);
- if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
- return; // first section has overflowed
- current->FixupRomEntries(size);
- return;
- }
- if(current->HCRDataFile()){
- TInt size=LoadDataToRom(current, aMain, aBPE);
- if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
- return; // first section has overflowed
- current->FixupRomEntries(size);
- iHeader->iHcrFileAddress = current->iHeaderRange.iImageAddr ;
- TRACE(TAREA, Print(ELog, "iHeader->iHcrFileAddress = %08x\n", iHeader->iHcrFileAddress));
- return ;
- }
- Print(ELog,"Processing file %s\n",current->iFileName);
-
- if (current->Primary())
- {
- Print(ELog, "[Primary]\n");
- }
-
- if (current->Secondary())
- {
- iHeader->iSecondaryFile=ActualToRomAddress(current->RomEntry());
- Print(ELog, "[Secondary]\n");
- }
-
- // Section 1 things
- //
- // TRomImageHeader, text, export directory, data
-
- aMain.Append(current->iHeaderRange);
- aMain.Append(current->iCodeSection);
- aMain.Append(current->iDataSection);
-
- // section 2 things
- //
- // dll ref table
-
- if (aSecond != 0)
- {
- // two section ROM - split image between both sections
- aSecond->Append(current->iExportDirSection);
- aSecond->Append(current->iDllRefTableRange);
- }
- else
- {
- // default placement in first section
- aMain.Append(current->iExportDirSection);
- aMain.Append(current->iDllRefTableRange);
- }
-
- TInt section1size = aMain.iRunAddr-current->iCodeSection.iRunAddr;
-
- if (aMain.iRunAddr == aMain.iImageAddr)
- {
- Print(ELog, "Load Address: %08x\n", current->iHeaderRange.iImageAddr);
- }
- else
- {
- Print(ELog, "Rom Address: %08x\n", current->iHeaderRange.iImageAddr);
- Print(ELog, "Area Address: %08x\n", current->iHeaderRange.iRunAddr);
- }
- Print(ELog, "Size: %08x\n", section1size);
-
- if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
- return; // first section has overflowed
-
- LoadFileToRom(current);
- Display(current->iRomImageHeader);
- Print(ELog, "Dll ref table size: %08x\n", current->iDllRefTableRange.iSize);
- Print(ELog, "Compression: %08x\n", current->iCompression);
- Print(ELog, "\n");
-
- current->FixupRomEntries(section1size);
- }
-
-static int CompareAddresses(const void * arg1, const void * arg2)
- {
- return (* (TUint32 *)arg1) < (* (TUint32 *)arg2) ? -1: 1;
- }
-
-char *E32Rom::ReserveRomExceptionSearchTable(char *anAddr, TRomExceptionSearchTable*& exceptionSearchTable)
- {
- TRomExceptionSearchTable *pT = (TRomExceptionSearchTable *)anAddr;
- exceptionSearchTable = pT;
- if (iExtensionRomHeader)
- {
- iExtensionRomHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr);
- }
- else
- {
- iHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr);
- }
- TLinAddr * addr = &pT->iEntries[0];
- int numEntries = 0;
- int errors = 0;
- // Count number of entries needed
- for (int i = 0; i < iObey->iNumberOfPeFiles; i++)
- {
- TUint32 xd = iPeFiles[i]->iHdr->iExceptionDescriptor;
- if ((xd & 1) && (xd != 0xffffffffu))
- {
- numEntries++;
- }
- else if (!iPeFiles[i]->iHdr->iExceptionDescriptor)
- {
-#ifdef __REJECT_NON_EXCEPTION_AWARE_BINARIES__
- Print(EError, "Executable not exception aware: %s\n", iPeFiles[i]->iName);
- errors++;
-#else
- Print(ELog, "Executable not exception aware: %s\n", iPeFiles[i]->iName);
-#endif
- }
- }
- if (errors > 0) exit(666);
- // NB we add one to numEntries to allow space for a fencepost value (see below for more)
- int spaceNeeded = sizeof(pT->iNumEntries) + sizeof(pT->iEntries[0])*(numEntries+1);
- int delta = (int)(addr+spaceNeeded) - (int)(iData+iSize);
- // Check we've got enough room
- if (delta > 0)
- {
- Print(EError, "Can't fit Rom Exception Search Table in Rom.\n");
- Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", delta);
- exit(666);
- }
- pT->iNumEntries = numEntries;
- return anAddr+spaceNeeded;
- }
-
-void E32Rom::ConstructRomExceptionSearchTable(TRomExceptionSearchTable* exceptionSearchTable)
- {
- TRomExceptionSearchTable *pT = exceptionSearchTable;
- TLinAddr * addr = &pT->iEntries[0];
- // Initialize the table
- int numEntries = pT->iNumEntries;
- TLinAddr fencepost = 0xffffffff;
- if (numEntries)
- {
- TLinAddr fp = 0;
- for (int j = 0; j < iObey->iNumberOfPeFiles; j++)
- {
- TUint32 xd = iPeFiles[j]->iHdr->iExceptionDescriptor;
- if ((xd & 1) && (xd != 0xffffffff))
- {
- // mask out bottom bit set by ELFTRAN.
- xd &= ~1;
- *addr++ = iPeFiles[j]->iHdr->iCodeBase;
- TLinAddr aEDAddr = iPeFiles[j]->iHdr->iCodeBase + xd;
- // Keep track of greatest code limit so we can use it as the fencepost value
- TExceptionDescriptor * aEDp = (TExceptionDescriptor *)RomToActualAddress(aEDAddr);
- TLinAddr codeLimit = aEDp->iROSegmentLimit;
- if (codeLimit>fp) fp=codeLimit;
- }
- }
- if (fp) fencepost=fp;
- // now check they're in order (they should be).
- int inOrder = 1;
- for (int k=numEntries-1;inOrder && k; k--)
- {
- inOrder = pT->iEntries[k]>pT->iEntries[k-1]?1:0;
- }
-
- if (!inOrder)
- {
- Print(ELog, "Sorting Rom Exception Table.\n");
- qsort(&pT->iEntries[0],numEntries,sizeof(pT->iEntries[0]), CompareAddresses);
- }
- }
- /*
- Add the fencepost value at the end of the table. This is used to optimize the comparison
- function passed to bsearch when retrieving values from the search table. It also allows a certain
- amount of error checking on lookup keys.
- */
- *addr++ = fencepost;
- }
-
-void TRomBuilderEntry::SizeInSections(TInt& aSize1, TInt& aSize2)
-//
-// Exact size of the upper & lower section information
-// lower = text + data
-// upper = export directory + dllref table
-//
- {
- aSize1 = iHeaderRange.iSize;
- aSize1 += iCodeSection.iSize; // text (including rdata)
- aSize1 += iDataSection.iSize; // static data
-
- aSize2 = iExportDirSection.iSize; // export directory
- aSize2 += iDllRefTableRange.iSize; // DLL ref table
- }
-
-
-void E32Rom::NextRom(TAddressRange* aFirst, TAddressRange* aSecond)
-//
-// Move on to the next Rom bank, taking the IATs with us
-//
- {
-
- Print(ELog,"\n####################################################################\n");
- TInt gap=iObey->iSectionStart-aFirst->iImageAddr;
- if (gap<0)
- {
- Print(EError, "First section overflowed by %08x bytes\n", -gap);
- exit(669);
- }
- iOverhead+=gap+sizeof(TRomSectionHeader);
- Print(ELog, "[Next rom section]\n");
- Print(ELog, "Skipping %08x bytes\n", gap);
- Print(ELog, "LinAddr: %08x\n", iObey->iSectionStart);
- Print(ELog, "First section tables: %08x\n", iObey->iSectionStart+sizeof(TRomSectionHeader));
- TInt size=aSecond->iImageAddr-iObey->iSectionStart;
- Print(ELog, "Tables size: %08x\n", size-sizeof(TRomSectionHeader));
- Print(ELog, "Rom Directory %08x\n", iHeader->iRomRootDirectoryList);
- Print(ELog, "Rom Directory size %08x\n", iDirectorySize);
-
- if (aSecond->iImageAddr != iHeader->iRomRootDirectoryList)
- {
- Print(EError, "Second section has overwritten the Rom directory\n");
- exit(669);
- }
- aSecond->Extend(iDirectorySize);
-
- Print(ELog, "\n");
- }
-
-TInt E32Rom::ResolveDllRefTables()
-//
-//
-//
- {
-
- Print(ELog, "\nResolving Dll reference tables.\n");
- TInt i;
- TInt err = KErrNone;
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables %d\n",i));
- TInt r=iPeFiles[i]->ResolveDllRefTable(*this);
- if (r!=KErrNone)
- err=r;
- }
- TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables complete\n"));
- return err;
- }
-
-
-TInt E32Rom::BuildDependenceGraph()
- {
- Print(ELog, "\nBuilding dependence graph.\n");
- TInt i;
- TInt err = KErrNone;
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRACE(TIMPORT,Print(ELog,"BuildDep %d\n",i));
- TRomBuilderEntry* e=iPeFiles[i];
- TInt r=e->BuildDependenceGraph(*this);
- if (r!=KErrNone)
- err=r;
- if (!e->IsDll())
- {
- if (e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0)
- e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataPresent); // EXE with static data
- }
- else if ((e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0) && !e->Variant() && !e->Extension())
- {
- // requires normal case DLL data initialisation
- e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataInit|KRomImageFlagDataPresent);
- }
- }
- TRACE(TIMPORT,Print(ELog,"BuildDep complete\n"));
-
- if(!gPagedRom)
- return err;
-
- Print(ELog,"\n");
-
- return err;
- }
-
-#define MARK_BEEN_HERE 1
-#define MARK_KEEP 2
-#define MARK_EXE 4
-#define MARK_CHECKED 8
-void E32Rom::UnmarkGraph(TInt aMark)
- {
- TRomNode* x = 0;
- for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable)
- x->iRomFile->iMark &= ~aMark;
- }
-
-void E32Rom::FindMarked(TInt aMarkMask, TInt aMark, TRomFile**& aList)
- {
- UnmarkGraph(MARK_CHECKED);
- TRomNode* x = 0;
- aMarkMask |= MARK_CHECKED;
- aMark &= ~MARK_CHECKED;
- for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable)
- {
- TRomFile* e = x->iRomFile;
- if ((e->iMark&aMarkMask)==aMark)
- {
- *aList++=e;
- e->iMark |= MARK_CHECKED;
- }
- }
- }
-
-TInt TRomFile::MarkDeps()
- {
- TInt n=0;
- TInt i;
- for (i=0; i<iNumDeps; ++i)
- {
- TRomFile* e=iDeps[i];
- if (!(e->iMark & MARK_BEEN_HERE))
- {
- e->iMark|=MARK_BEEN_HERE;
- ++n;
- n+=e->MarkDeps();
- TUint32 flg = RomImageFlags();
- TUint32 eflg = e->RomImageFlags();
- if (eflg & KRomImageFlagDataPresent)
- iRbEntry->iRomImageFlags |= KRomImageFlagDataPresent;
- TBool e_is_dll = eflg & KImageDll;
- if ((flg & KImageDll) && e_is_dll && (eflg & KRomImageFlagDataInit))
- iRbEntry->iRomImageFlags |= KRomImageFlagDataInit;
- if (!e_is_dll)
- e->iMark|=MARK_EXE;
- if (eflg&KRomImageFlagData)
- e->iMark|=MARK_KEEP;
- }
- }
- return n;
- }
-
-TInt TRomFile::FindRouteTo(TRomFile* aDest, TRomFile** aStack, TInt aIndex)
- {
- TInt i;
- for (i=0; i<iNumDeps; ++i)
- {
- TRomFile* e=iDeps[i];
- if (e == aDest)
- return aIndex;
- if (!(e->iMark & MARK_BEEN_HERE))
- {
- e->iMark|=MARK_BEEN_HERE;
- aStack[aIndex] = e;
- TInt r = e->FindRouteTo(aDest, aStack, aIndex+1);
- if (r >= 0)
- return r;
- }
- }
- return KErrNotFound;
- }
-
-void E32Rom::ListRouteTo(TRomFile* aStart, TRomFile* aDest, TInt aNDeps)
- {
- TRomNode* rootdir = iObey->iRootDirectory;
- TRomFile** stack = new TRomFile*[aNDeps];
- UnmarkGraph();
- TInt depth = aStart->FindRouteTo(aDest, stack, 0);
- assert(depth >= 0);
- Print(EAlways, "\t--->%s\n", (const char*)TModuleName(*aDest, rootdir));
- while(--depth >= 0)
- Print(EAlways, "\tvia %s\n", (const char*)TModuleName(*stack[depth], rootdir));
- delete[] stack;
- }
-
-TInt E32Rom::ProcessDependencies()
- {
- TInt i;
- TInt errors = 0;
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRomBuilderEntry* e=iPeFiles[i];
- TRomNode* rn = e->iRomNode;
- TRomFile* rf = rn->iRomFile;
- UnmarkGraph();
- TInt n=rf->MarkDeps();
- rf->iNumPDeps=n;
- if (n)
- {
- rf->iPDeps=new TRomFile* [n];
- if (!rf->iPDeps)
- return KErrNoMemory;
- TRomFile** l=rf->iPDeps;
- FindMarked(MARK_EXE, MARK_EXE, l);
- TInt nx=l-rf->iPDeps;
- if (!e->IsDll() && (nx>1 || nx==1 && l[-1]!=rf))
- {
- Print(EError,"EXE %s links to the following other EXEs:\n", e->iFileName);
- TInt j;
- for (j=0; j<nx; ++j)
- {
- if (rf->iPDeps[j] != rf)
- ListRouteTo(rf, rf->iPDeps[j], n);
- }
- ++errors;
- continue;
- }
- else if (nx>1)
- {
- Print(EError,"DLL %s links to more than one EXE:\n",e->iFileName);
- TInt j;
- for (j=0; j<nx; ++j)
- ListRouteTo(rf, rf->iPDeps[j], n);
- ++errors;
- continue;
- }
- if (nx)
- e->iRomImageFlags|=KRomImageFlagExeInTree;
- FindMarked(MARK_KEEP|MARK_EXE, MARK_KEEP, l);
- rf->iNumPDeps=l-rf->iPDeps;
- if (rf->iNumPDeps)
- {
- e->iDllRefTableRange.iSize=(rf->iNumPDeps-1)*sizeof(TRomImageHeader*)+sizeof(TDllRefTable);
- if (e->IsDll() && rf->iTotalDataBss)
- {
- TRomFile* f=rf->iPDeps[0]; // first dependency, EXE if there is one
- TUint fflg = f->RomImageFlags();
- TBool f_is_dll = fflg & KImageDll;
- if (!f_is_dll)
- {
- // DLL with data/bss depends on EXE
- if ((fflg & KRomImageFlagFixedAddressExe) || iObey->iMemModel==E_MM_Direct)
- {
- // assign the DLL data address in the EXE bss section
- rf->iDataBssOffsetInExe=f->iTotalDataBss;
- f->iTotalDataBss+=rf->iTotalDataBss;
- }
- }
- else if (iObey->iMemModel==E_MM_Direct)
- {
- Print(EError, "DLL with data/bss must have attach process specified\n");
- return KErrGeneral;
- }
- }
- }
- else
- {
- delete[] rf->iPDeps;
- rf->iPDeps=NULL;
- }
- }
- if (!rf->iNumPDeps)
- e->iDllRefTableRange.iSize=0;
- }
- if (iObey->iMemModel == E_MM_Moving)
- {
- // On moving model only, we must verify that no fixed process links to a
- // DLL with data/bss which is attached to a fixed process.
- // On multiple model there is no restriction.
- // On direct model all DLLs with data/bss must specify an attach process
- // and the error will show up as one EXE depending on another.
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRomBuilderEntry* e=iPeFiles[i];
- TRomNode* rn = e->iRomNode;
- TRomFile* rf = rn->iRomFile;
- TUint rif = rf->RomImageFlags();
- if (e->IsDll() || e->Primary() || !(rif & KRomImageFlagFixedAddressExe))
- continue; // only need to check fixed address user mode EXEs
- TInt n = rf->iNumPDeps;
- TInt j;
- for (j=0; j<n; ++j)
- {
- TRomFile* f = rf->iPDeps[j];
- TUint fflg = f->RomImageFlags();
- if ((fflg & KImageDll) && (f->iDataBssOffsetInExe < 0))
- {
- // fixed user EXE links to DLL with data/bss and no attach process
- Print(EError,"Fixed EXE %s links to DLL with data/bss and no attach process:\n", e->iFileName);
- ListRouteTo(rf, rf->iPDeps[j], n);
- ++errors;
- }
- }
- }
- }
- if (errors)
- return KErrGeneral;
-
- STRACE(TIMPORT,
- {
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TRomBuilderEntry* e=iPeFiles[i];
- TRomNode* rn = e->iRomNode;
- TRomFile* rf = rn->iRomFile;
- Print(ELog,"File %s: PN=%d\n",e->iFileName,rf->iNumPDeps);
- TInt j;
- for (j=0; j<rf->iNumPDeps; ++j)
- {
- TRomFile* f=rf->iPDeps[j];
- Print(ELog,"\t%s\n", (const char*)TModuleName(*f, iObey->iRootDirectory));
- }
- }
- })
- return KErrNone;
- }
-
-void E32Rom::SetSmpFlags()
- {
- if (gLogLevel & LOG_LEVEL_SMP_INFO)
- {
- Print(ELog,"\nComputing SMP properties. The following components are SMP-unsafe:\n");
- }
-
- bool is_all_safe = 1;
-
- for (int i = 0; i < iObey->iNumberOfPeFiles; i++)
- {
- TRomBuilderEntry* e = iPeFiles[i];
-
- if ( e->iRomNode->iRomFile->ComputeSmpSafe(e) )
- {
- e->iRomImageFlags |= KRomImageSMPSafe;
- }
- else
- {
- is_all_safe = 0;
- e->iRomImageFlags &= ~KRomImageSMPSafe;
- }
- }
-
- if ( (gLogLevel & LOG_LEVEL_SMP_INFO) && is_all_safe)
- {
- Print(ELog,"There are no unsafe components.");
- }
- }
-
-TInt E32Rom::ResolveImports()
-//
-// Fix the import address table for each of the files in rom
-//
- {
-
- Print(ELog, "Resolving Imports.\n");
- TInt i;
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- TInt r=iPeFiles[i]->FixupImports(*this);
- if (r!=KErrNone)
- return r;
- }
- return KErrNone;
- }
-
-char *E32Rom::RomToActualAddress(TUint aPtr)
- {
- return (char *)(aPtr-iObey->iRomLinearBase+(TUint)iHeader);
- }
-
-TUint E32Rom::ActualToRomAddress(TAny *aPtr)
- {
- return ((TUint)aPtr)-(TUint32)iHeader+iObey->iRomLinearBase;
- }
-
-void E32Rom::SetImageAddr(TAddressRange& aRange, TAny* aPtr, TUint32 aRunOffset)
- {
- aRange.iImagePtr=aPtr;
- aRange.iImageAddr=ActualToRomAddress(aPtr);
- aRange.iRunAddr=aRange.iImageAddr+aRunOffset;
- }
-
-void E32Rom::SetImageAddr(TAddressRange& aRange, TUint aAddr, TUint32 aRunOffset)
- {
- aRange.iImagePtr=RomToActualAddress(aAddr);
- aRange.iImageAddr=aAddr;
- aRange.iRunAddr=aAddr+aRunOffset;
- }
-
-TRomNode* E32Rom::FindImageFileByName(const TDllFindInfo& aInfo, TBool aPrintDiag, TBool& aFallBack)
-//
-// return the file with the name aName
-//
- {
- return iObey->iRootDirectory->FindImageFileByName(aInfo, aPrintDiag, aFallBack);
- }
-
-TInt E32Rom::CheckForVersionConflicts(const TRomBuilderEntry* a)
- {
- return iObey->iRootDirectory->CheckForVersionConflicts(a);
- }
-
-TRomNode* E32Rom::CopyDirectory(TRomNode*& aLastExecutable)
- {
- return iObey->iRootDirectory->CopyDirectory(aLastExecutable, 0);
- }
-
-TInt E32Rom::CollapseImportThunks()
-//
-// Collapse 3-word import thunks into a single branch
-//
- {
-
- Print(ELog, "\nCollapsing Import Thunks.\n");
- TInt i;
- for (i=0; i<iObey->iNumberOfPeFiles; i++)
- {
- if (iPeFiles[i]->iHdr->iImportOffset)
- {
- TInt r=CollapseImportThunks(iPeFiles[i]);
- if (r!=KErrNone)
- return r;
- }
- }
- return KErrNone;
- }
-
-TInt E32Rom::WriteImages(TInt aHeaderType)
- {
- if (aHeaderType < 0)
- aHeaderType = 1;
- ofstream romFile((const char *)iObey->iRomFileName,ios::binary);
- if (!romFile)
- return Print(EError,"Cannot open ROM file %s for output\n",iObey->iRomFileName);
- Write(romFile, aHeaderType);
- romFile.close();
-
- // Write out the odd/even 16-bits of the images
-
- char sname[256];
- if (iObey->iRomOddFileName)
- {
- strcpy(sname, (const char*)iObey->iRomOddFileName);
- if (strcmp(sname, "*")==0)
- {
- // use romname with ".odd" appended.
- sprintf(sname,"%s.odd",(const char *)iObey->iRomFileName);
- }
- ofstream oFile(sname,ios::binary);
- if (!oFile)
- return Print(EError,"Cannot open file %s for output\n",sname);
- Print(EAlways, "Writing odd half words to file %s\n",sname);
- WriteOdd(oFile);
- oFile.close();
- }
- if (iObey->iRomEvenFileName)
- {
- strcpy(sname, (const char*)iObey->iRomEvenFileName);
- if (strcmp(sname, "*")==0)
- {
- // use romname with ".even" appended.
- sprintf(sname,"%s.even",(const char *)iObey->iRomFileName);
- }
- ofstream oFile(sname,ios::binary);
- if (!oFile)
- return Print(EError,"Cannot open file %s for output\n",sname);
- Print(EAlways, "Writing even half words to file %s\n",sname);
- WriteEven(oFile);
- oFile.close();
- }
-
- // Write out the ROM in the SREC or S19 format
-
- if (iObey->iSRecordFileName)
- {
- strcpy(sname, (const char*)iObey->iSRecordFileName);
- if (strcmp(sname, "*")==0)
- {
- // use romname with ".srec" appended.
- sprintf(sname,"%s.srec",(const char *)iObey->iRomFileName);
- }
- ofstream sFile(sname,ios::binary);
- if (!romFile)
- return Print(EError,"Cannot open file %s for output\n",sname);
- Print(EAlways, "Writing S record format to file %s\n",sname);
- WriteSRecord(sFile);
- sFile.close();
- }
- return KErrNone;
- }
-
-void E32Rom::WriteOdd(ofstream &os)
- {
- char *ptr=(char *)iHeader+2;
- TInt i;
- for (i=2; i<iObey->iRomSize; i+=4, ptr+=4)
- os.write(ptr, 2);
- }
-
-void E32Rom::WriteEven(ofstream &os)
- {
- char *ptr=(char *)iHeader;
- TInt i;
- for (i=0; i<iObey->iRomSize; i+=4, ptr+=4)
- os.write(ptr, 2);
- }
-
-void E32Rom::SetCompressionInfo(TUint aCompressionType, TUint aCompressedSize, TUint aUncompressedSize)
- {
-
- if (iExtensionRomHeader)
- {
- iExtensionRomHeader->iCompressionType=aCompressionType;
- iExtensionRomHeader->iCompressedSize=aCompressedSize;
- iExtensionRomHeader->iUncompressedSize=aUncompressedSize;
- }
- else
- {
- iHeader->iCompressionType=aCompressionType;
- iHeader->iCompressedSize=aCompressedSize;
- iHeader->iUncompressedSize=aUncompressedSize;
- }
- }
-
-void E32Rom::Write(ofstream &os, TInt aHeaderType)
-//
-// Output a rom image
-//
- {
-
- const char *compressed=gEnableCompress ? " compressed" : " uncompressed";
-
- switch (aHeaderType)
- {
- case 0:
- Print(EAlways, "\nWriting%s Rom image without",compressed);
- break;
- case 1:
- default:
- Print(EAlways, "\nWriting%sRom image with repro",compressed);
- os.write(iData, sizeof(TRomLoaderHeader));
- break;
- case 2:
- Print(EAlways, "\nWriting%s Rom image with PE-COFF",compressed);
- {
- unsigned char coffhead[0x58] = {0}; // zero all the elements
-
- // fill in the constant bits
- // this is supposed to be simple, remember
- coffhead[1] = 0x0a;
- coffhead[2] = 0x01;
- coffhead[0x10] = 0x1c;
- coffhead[0x12] = 0x0f;
- coffhead[0x13] = 0xa1;
- coffhead[0x14] = 0x0b;
- coffhead[0x15] = 0x01;
- coffhead[0x26] = 0x40;
- coffhead[0x2a] = 0x40;
- coffhead[0x30] = 0x2e;
- coffhead[0x31] = 0x74;
- coffhead[0x32] = 0x65;
- coffhead[0x33] = 0x78;
- coffhead[0x34] = 0x74;
- coffhead[0x3a] = 0x40;
- coffhead[0x3e] = 0x40;
- coffhead[0x44] = 0x58;
- coffhead[0x54] = 0x20;
-
- // now fill in the text segment size
- *(TUint32 *) (&coffhead[0x18]) = ALIGN4K(iSizeUsed);
- *(TUint32 *) (&coffhead[0x40]) = ALIGN4K(iSizeUsed);
-
- os.write(reinterpret_cast<char *>(coffhead), sizeof(coffhead));
- }
- break;
- }
- Print(EAlways, " header to file %s\n", iObey->iRomFileName);
-
- iHeader->iUnpagedCompressedSize = 0;
- iHeader->iUnpagedUncompressedSize = iHeader->iPageableRomStart;
- iHeader->iCompressedUnpagedStart = gBootstrapSize + gPageIndexTableSize; // AttilaV calculate uncompressed un-paged size
-
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- {
- Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize);
- Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize);
-
- Print(ELog, "iExtensionRomHeader :%d\n", iExtensionRomHeader);
- Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));
- Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ));
- Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
-
- Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart );
- Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize );
- Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex );
-
- Print(ELog, "iSizeUsed :0x%08x (%d)\n", iSizeUsed, iSizeUsed );
- Print(ELog, "Linear base address :0x%08x\n",iHeader->iRomBase);
- Print(ELog, "Size: 0x%08x\n",iHeader->iRomSize);
- }
-
- if ( gPagedRom && gCompressUnpaged)
- {
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "Write out compressed un-paged and paged sections\n\n");
- ImpTRomHeader* header = (ImpTRomHeader *)iHeader;
-
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- {
- Print(ELog, "Header:\n");
- header->Display();
- }
-
- streampos headerpos=os.tellp();
-
- // Write out uncompressed un-paged part (bootstrap + Page Index Table)
- os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart);
-
- // write out the compressed unpaged part
- int srcsize=iHeader->iPageableRomStart - iHeader->iCompressedUnpagedStart;
-
- int rawimagelen=DeflateCompressCheck(((char *)iHeader)+iHeader->iCompressedUnpagedStart,srcsize,os);
- iHeader->iUnpagedCompressedSize = rawimagelen;
- iHeader->iUnpagedUncompressedSize = srcsize ;
-
- // align to 4kbyte boundary if neccessary
- TUint32 distanceFrom4kBoundary = ((~(iHeader->iCompressedUnpagedStart + rawimagelen /*+ sizeof(TRomLoaderHeader)*/ )) & 0xfff) + 1;
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "distanceFrom4kBoundary :0x%08x (%d)\n", distanceFrom4kBoundary, distanceFrom4kBoundary);
- char filer[0x1000];
- memset( filer, 0, 0x1000);
- os.write((char *)filer, distanceFrom4kBoundary);
-
-
- // write out the paged part
- os.write((char *)iHeader + iHeader->iPageableRomStart, ALIGN4K(iSizeUsed - iHeader->iPageableRomStart));
-
- // update size and compression information of paged-part
- SetCompressionInfo(KUidCompressionDeflate, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize));
-
- // Calculate starting index of the Pageable Rom Start
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- {
- Print(ELog, "iPageableRomStart : %d (0x%08x)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart);
- Print(ELog, "iCompressedUnpagedStart : %d (0x%08x)\n", iHeader->iCompressedUnpagedStart, iHeader->iCompressedUnpagedStart);
- Print(ELog, "rawimagelen : %d (0x%08x)\n", rawimagelen, rawimagelen);
- }
-
- TInt displacement = iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary;
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "new iPageableRomStart : %d (0x%08x)\n", (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary), (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary));
- displacement = iHeader->iPageableRomStart-displacement;
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "displacement : %d (0x%08x)\n", displacement, displacement);
-
- SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex);
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "First Pageable page info[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize);
-
- TInt startPageableIndex = (iHeader->iPageableRomStart) / (iObey->iPageSize);
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- {
- Print(ELog, "iObey->iPageSize : %d (0x%08x)\n", iObey->iPageSize, iObey->iPageSize);
- Print(ELog, "startPageableIndex : %d (0x%08x)\n", startPageableIndex, startPageableIndex);
- }
- pi += startPageableIndex;
-
-
- while ( 0 != pi->iDataStart)
- {
- 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);
-
- pi->iDataStart -= displacement;
-
- 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);
-
- ++pi;
- }
-
-
-
- // Rewrite the header with updated info
- #ifdef __TOOLS2__
- os.seekp(headerpos);
- #else
- os.seekp(headerpos,ios::beg);
- #endif
-
- // Rewrite uncompressed un-paged part (bootstrap + Page Index Table)
- os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart);
-
-
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- {
- Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize, iHeader->iUnpagedCompressedSize);
- Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize, iHeader->iUnpagedUncompressedSize);
-
- Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));
- Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ));
- Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
-
- Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart );
- Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize );
- Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex );
- Print(ELog, "\t\tinfo(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi->iDataStart, pi->iDataSize, pi->iDataSize);
-
- Print(ELog, "Linear base address: %08x\n",iHeader->iRomBase);
- Print(ELog, "Size: %08x\n",iHeader->iRomSize);
- }
-
- return;
- }
-
- if (!gEnableCompress || gPagedRom || !gCompressUnpaged)
- {
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "Writeout uncompressed un-paged and paged sections2\n");
- SetCompressionInfo(KFormatNotCompressed, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize));
- iHeader->iUnpagedCompressedSize = ALIGN4K(iSizeUsed);
- iHeader->iUnpagedUncompressedSize = ALIGN4K(iUncompressedSize);
-
- os.write((char *)iHeader, ALIGN4K(iSizeUsed));
-
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- {
- Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize);
- Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize);
-
- Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));
- Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ));
- Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
-
- Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart );
- Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize );
- Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex );
- }
-
- return;
- }
-
- // compressed image without paging section
- streampos headerpos=os.tellp();
- int headersize=iExtensionRomHeader ? sizeof(TExtensionRomHeader) : sizeof(TRomHeader);
-
- os.write(reinterpret_cast<char*>(iHeader), headersize); // write a dummy header
- // compress the rest of the image
- int srcsize=iSizeUsed - headersize;
- int rawimagelen=DeflateCompressCheck(((char *)iHeader)+headersize,srcsize,os);
- // write the compression info into the header
- SetCompressionInfo(KUidCompressionDeflate, rawimagelen, iUncompressedSize); // doesn't need to be 4K aligned
- iHeader->iCompressedUnpagedStart = headersize;
- iHeader->iUnpagedCompressedSize = rawimagelen;
- iHeader->iUnpagedUncompressedSize = srcsize;
-
- #ifdef __TOOLS2__
- os.seekp(headerpos);
- #else
- os.seekp(headerpos,ios::beg);
- #endif
- os.write(reinterpret_cast<char*>(iHeader), headersize); // write header again with (compressed) size info
-
- if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
- Print(ELog, "\tiSizeUsed:%d, iUncompressedSize:%d, headersize:%d, srcsize:%d, rawimagelen:%d \n",iSizeUsed, iUncompressedSize, headersize, srcsize, rawimagelen);
- }
-
-TInt E32Rom::Compare(char *anImage, TInt aHeaderType)
- {
- if (aHeaderType < 0)
- aHeaderType = 1;
- ifstream file(anImage, ios::binary);
- if (!file)
- return Print(EError, "Cannot open Rom image '%s' for verification\n", anImage);
- Print(ELog, "\nVerifying ROM against image in %s\n", anImage);
- switch (aHeaderType)
- {
- case 0:
- break;
- case 1:
- default:
- Print(ELog, "Skipping repro header\n");
- file.seekg(sizeof(TRomLoaderHeader));
- break;
- case 2:
- Print(ELog, "Skipping coff header\n");
- file.seekg(0x58);
- break;
- }
- TInt length=ALIGN4K(iSizeUsed);
- if (iObey->iSectionStart != 0)
- {
- length = iObey->iSectionStart-iObey->iRomLinearBase;
- Print(ELog, "Verifying first section (%08x bytes)... ", length);
- }
-
- TRomHeader compareHeader;
- file.read((char *)&compareHeader, sizeof(TRomHeader));
- // Arrange different settings for TRomHeader and
- // TRomSectionHeader in the obey file
- // For now just copy across the things that'll change
- compareHeader.iVersion=iHeader->iVersion;
- compareHeader.iTime=iHeader->iTime;
- compareHeader.iTimeHi=(TUint32)(iHeader->iTime >> 32);
- compareHeader.iCheckSum=iHeader->iCheckSum;
- compareHeader.iLanguage=iHeader->iLanguage;
-
- if (memcmp(&compareHeader, iHeader, sizeof(TRomHeader))!=0)
- return Print(EError, "Verify failed.\nRom headers are different\n");
-
- // Now compare the rest of the image (or first section)
-
- TUint *ptr=(TUint *)(iHeader+1);
- TInt i;
- for (i=sizeof(TRomHeader); i<length; i+=4)
- {
- TUint a;
- file.read((char *)&a, sizeof(TUint));
- if (file.eof())
- return Print(EError, "Verify failed.\nDifferent Rom sizes\n");
- if (a!=*ptr)
- return Print(EError, "Verify failed.\nContents differ at Rom address %08x\n", i+iObey->iRomLinearBase);
- ptr++;
- }
- file.close();
- Print(EAlways, "Verify OK\n");
- return KErrNone;
- }
-
-
-char* E32Rom::AllocateRelocationTable(char* aAddr, TReloc*& aRelocTable)
- {
- if(iObey->SetArea().Count() > 1)
- {
- aRelocTable = reinterpret_cast<TReloc*>(aAddr);
-
- // Allocate one entry per non default area + 1 sentinel
- // (Count() returns number of non default areas + 1 (the
- // default area))
- TInt size = iObey->SetArea().Count() * sizeof(TReloc);
- aAddr += Align(size);
- }
- else
- {
- aRelocTable = 0;
- }
-
- return aAddr;
- }
-
-
-void E32Rom::FillInRelocationTable(TReloc* aRelocTable)
- {
- TReloc* p = aRelocTable;
- TInt wastedBytes = 0;
-
- for (NonDefaultAreasIterator areaIt(iObey->SetArea());
- ! areaIt.IsDone();
- areaIt.GoToNext())
- {
- Area& currentArea = areaIt.Current();
-
- if (currentArea.UsedSize() > 0)
- {
- p->iLength = currentArea.UsedSize();
- p->iSrc = currentArea.SrcBaseAddr();
- p->iDest = currentArea.DestBaseAddr();
- ++p;
- }
- else
- {
- wastedBytes += sizeof(TReloc);
- }
- }
-
- if (aRelocTable != 0)
- {
- // Last entry acts as a sentinel
- memset(p, 0, sizeof(*p));
- }
-
- if (wastedBytes > 0)
- {
- Print(EWarning, "Some areas are declared but not used\n");
- Print(EWarning, "%d bytes wasted in relocation table\n", wastedBytes);
- }
- }
-
-
-/**
- Link together the kernel extensions.
-
- Must be called only after space has been allocated in the ROM image
- for the kernel extension.
- */
-
-void E32Rom::LinkKernelExtensions(TRomBuilderEntry* aExtArray[], TInt aExtCount)
- {
- /**
- * The kernel extensions should never be linked together as part of extension ROMs.
- */
- if (!iExtensionRomHeader)
- {
- TLinAddr* pLastNextExtAddr = &(iHeader->iExtensionFile);
-
- for (TInt i=0; i<aExtCount; ++i)
- {
- TRomBuilderEntry* curExt = aExtArray[i];
- *pLastNextExtAddr = ActualToRomAddress(curExt->RomEntry());
- pLastNextExtAddr = &(curExt->iRomImageHeader->iNextExtension);
- }
-
- *pLastNextExtAddr = 0;
- }
- }
-
-void E32Rom::ProcessDllData()
- {
- DllDataEntry *entry = iObey->GetFirstDllDataEntry();
- TRomBuilderEntry *romEntry;
- TLinAddr* aExportTbl;
- void *aLocation;
- TUint aDataAddr;
- while(entry){
- // A Dll data may be patched either via the ordinal number (as in ABIv2), or via
- // the address of the data field (as in ABIv1).
- romEntry = entry->iRomNode->iRomFile->iRbEntry;
- if((TInt)entry->iOrdinal != -1) {
-
- // const data symbol may belong in the Code section. Get the address of the data field via the
- // export table. If the address lies within the Code or data section limits,
- // get the corresponding location and update it.While considering the Data section limits don't
- // include the Bss section, as it doesn't exist as yet in the image.
- if(entry->iOrdinal < 1 || entry->iOrdinal > (TUint32)romEntry->iOrigHdr->iExportDirCount)
- {
- Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", entry->iOrdinal, romEntry->iName);
- entry = entry->NextDllDataEntry();
- continue;
- }
- aExportTbl = (TLinAddr*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iExportDirOffset);
- aDataAddr = (TInt32)(aExportTbl[entry->iOrdinal - 1] + entry->iOffset);
-
- if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) &&
- (aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \
- romEntry->iOrigHdr->iCodeSize)) )
- {
- char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset);
- aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase));
- memcpy(aLocation, &(entry->iNewValue), entry->iSize);
- }
- else if( (aDataAddr >= romEntry->iOrigHdr->iDataBase) &&
- (aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \
- romEntry->iOrigHdr->iDataSize )) )
- {
- char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset);
- aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase));
- memcpy(aLocation, &(entry->iNewValue), entry->iSize);
- }
- else
- {
- 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);
- }
-
- }
- else if((TInt)entry->iDataAddress != -1) {
- // const data symbol may belong in the Code section. If the address lies within the Code
- // or data section limits, get the corresponding location and update it.While considering
- // the Data section limits don't include the Bss section, as it doesn't exist as yet in the image.
- aDataAddr = (TUint)(entry->iDataAddress + entry->iOffset);
- if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) &&
- (aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \
- romEntry->iOrigHdr->iCodeSize )) )
- {
- char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset);
- aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase));
- memcpy(aLocation, &(entry->iNewValue), entry->iSize);
- }
- else if( (aDataAddr >= romEntry->iOrigHdr->iDataBase) &&
- (aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \
- romEntry->iOrigHdr->iDataSize )) )
- {
- char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset);
- aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase));
- memcpy(aLocation, &(entry->iNewValue), entry->iSize);
- }
- else
- {
- 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);
- }
- }
- else {
- }
- entry = entry->NextDllDataEntry();
- }
- }
-
-TInt E32Rom::CheckUnpagedMemSize()
- {
-
- if (H.iVerbose && gPagedRom)
- {
- Print(EDiagnostic, "iMaxUnpagedMemSize 0x%08x (%d)\n", iObey->iMaxUnpagedMemSize, iObey->iMaxUnpagedMemSize);
- }
-
- // Only check if the iMaxUnpagedMemSize is set
- if (iObey->iMaxUnpagedMemSize <= 0) return KErrNone;
-
- // Only for paged rom
- if (!gPagedRom)
- {
- Print(EWarning, "The unpaged size overflow check is skipped.\n");
- return KErrNone;
- }
-
- if (iHeader->iPageableRomStart > 0)
- {
- if (iHeader->iPageableRomStart > iObey->iMaxUnpagedMemSize)
- {
- Print(EError, "Unpaged memory size overflow: require 0x%08x (%d) bytes while the maximum size is 0x%08x (%d) bytes\n",
- iHeader->iPageableRomStart,
- iHeader->iPageableRomStart,
- iObey->iMaxUnpagedMemSize,
- iObey->iMaxUnpagedMemSize);
-
- return KErrNoMemory;
- }
- }
- else
- {
- Print(EWarning, "The size of unpaged memory is not available. The unpaged memory overflow checking is skipped.\n");
- }
-
- return KErrNone;
- }
-
-TRomNode* E32Rom::RootDirectory()
-{
- return iObey->iRootDirectory;
-}
-
-TText* E32Rom::RomFileName()
-{
- return iObey->iRomFileName;
-}
-
-TUint32 E32Rom::RomBase()
-{
- return iHeader->iRomBase;
-}
-
-TUint32 E32Rom::RomSize()
-{
- return iHeader->iRomSize;
-}
-
-TVersion E32Rom::Version()
-{
- return iHeader->iVersion;
-}
-
-TInt64 E32Rom::Time()
-{
- return iHeader->iTime;
-}
-
-TUint32 E32Rom::CheckSum()
-{
- return iHeader->iCheckSum;
-}
-
-TUint32 E32Rom::DataRunAddress()
-{
- return iObey->iDataRunAddress;
-}
-
-TUint32 E32Rom::RomAlign()
-{
- return iObey->iRomAlign;
-}
+/*
+* Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <e32uid.h>
+#include "h_utl.h"
+#include <string.h>
+#include <stdlib.h>
+#include <iomanip>
+
+#include "r_global.h"
+#include "r_obey.h"
+#include "r_rom.h"
+#include "r_dir.h"
+#include "patchdataprocessor.h"
+#include "memmap.h"
+#include "byte_pair.h"
+#include "symbolgenerator.h"
+
+const TInt KSpareExports=16;
+extern TInt gThreadNum;
+extern string gDepInfoFile;
+extern TBool gGenDepGraph;
+
+TUint32 DeflateCompressCheck(char *bytes,TInt size,ostream &os);
+void DeflateCompress(char *bytes,TInt size,ostream &os);
+void InflateUnCompress(unsigned char* source, int sourcesize,unsigned char* dest, int destsize);
+
+EntryQueue* LoadImageWorker::m_queue = NULL;
+TInt LoadImageWorker::m_errors = 0;
+TMemModel LoadImageWorker::m_memmodel;
+boost::mutex LoadImageWorker::m_mutex;
+LoadImageWorker::LoadImageWorker(EntryQueue* aQueue, TMemModel aMemModel)
+ {
+ m_queue = aQueue;
+ m_memmodel = aMemModel;
+ }
+void LoadImageWorker::operator()()
+ {
+ while(1)
+ {
+ m_mutex.lock();
+ if(m_queue->size() > 0)
+ {
+ TRomBuilderEntry * current = m_queue->front();
+ m_queue->pop();
+ m_mutex.unlock();
+ TInt err = current->OpenImageFile();
+ m_mutex.lock();
+ err = current->GetImageFileInfo(err);
+ m_mutex.unlock();
+ if(err)
+ {
+ m_mutex.lock();
+ ++m_errors;
+ m_mutex.unlock();
+ continue;
+ }
+ if(current->iOverrideFlags&KOverrideAddress || current->iHdr->iFlags & KImageFixedAddressExe)
+ {
+ if(m_memmodel != E_MM_Multiple && m_memmodel != E_MM_Flexible && !current->IsDll())
+ current->iRomImageFlags |=KRomImageFlagFixedAddressExe;
+ }
+ if(gPagedRom)
+ {
+ if(current->iHdr->iFlags&KImageCodePaged)
+ {
+ current->iRomImageFlags&=~KRomImageFlagCodeUnpaged;
+ current->iRomImageFlags|=KRomImageFlagCodePaged;
+ }
+ if(current->iHdr->iFlags&KImageCodeUnpaged)
+ {
+ current->iRomImageFlags|=KRomImageFlagCodeUnpaged;
+ current->iRomImageFlags&=~KRomImageFlagCodePaged;
+ }
+ }
+ if(current->iHdr->iFlags&KImageDataPaged)
+ {
+ current->iRomImageFlags&=~KRomImageFlagDataUnpaged;
+ current->iRomImageFlags|=KRomImageFlagDataPaged;
+ }
+ if(current->iHdr->iFlags&KImageDataUnpaged)
+ {
+ current->iRomImageFlags|=KRomImageFlagDataUnpaged;
+ current->iRomImageFlags&=~KRomImageFlagDataPaged;
+ }
+ if(current->iHdr->iFlags&KImageDebuggable)
+ {
+ current->iRomImageFlags|=KRomImageDebuggable;
+ }
+ else
+ {
+ current->iRomImageFlags&=~KRomImageDebuggable;
+ }
+ }
+ else
+ {
+ m_mutex.unlock();
+ break;
+ }
+ }
+ }
+E32Rom* CompressPageWorker::m_rom = NULL;
+TInt CompressPageWorker::m_nextpage = 0;
+TInt CompressPageWorker::m_totalpages = 0;
+TInt CompressPageWorker::m_pagesize = 0;
+boost::mutex CompressPageWorker::m_mutex;
+TInt CompressPageWorker::m_error = 0;
+CompressPageWorker::CompressPageWorker(E32Rom* aRom, TInt aPageSize, TInt aTotalPages, TInt aNextPage)
+ {
+ m_rom = aRom;
+ m_pagesize = aPageSize;
+ m_totalpages = aTotalPages;
+ m_nextpage = aNextPage;
+ }
+void CompressPageWorker::operator()()
+ {
+ SRomPageInfo* pPageBase = (SRomPageInfo*)((TInt)m_rom->iHeader + m_rom->iHeader->iRomPageIndex);
+ CBytePair bpe;
+ while(1)
+ {
+ m_mutex.lock();
+ TInt currentPageIndex = m_nextpage++;
+ m_mutex.unlock();
+ if(currentPageIndex < m_totalpages)
+ {
+ TInt inOffset = m_pagesize * currentPageIndex;
+ TUint8 attrib = (TUint8)SRomPageInfo::EPageable;
+ SRomPageInfo info ={ (TUint32)inOffset, (TUint16)m_pagesize, (TUint8)SRomPageInfo::EBytePair, attrib };
+ TUint8* in = (TUint8*) m_rom->iHeader + inOffset;
+ TUint8* out = in;
+ TInt outSize = BytePairCompress(out, in, m_pagesize, &bpe);
+ if(outSize == KErrTooBig)
+ {
+ info.iCompressionType = SRomPageInfo::ENoCompression;
+ memcpy(out, in, m_pagesize);
+ outSize = m_pagesize;
+ }
+ if(outSize < 0 )
+ {
+ m_mutex.lock();
+ m_error = outSize;
+ m_mutex.unlock();
+ break;
+ }
+ info.iDataSize = (TUint16) outSize;
+ *(pPageBase + currentPageIndex) = info;
+ if((currentPageIndex & 255) == 255)
+ {
+ m_mutex.lock();
+ Print(EAlways, ".\n");
+ m_mutex.unlock();
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+////////////////////////////////////////////////////////////////////////
+
+TAddressRange::TAddressRange()
+ : iImagePtr(0), iImageAddr(0), iRunAddr(0), iSize(0)
+ {
+ }
+
+void TAddressRange::Append(TAddressRange& aRange)
+ {
+ if(aRange.iSize)
+ {
+ aRange.iImagePtr = iImagePtr;
+ aRange.iImageAddr = iImageAddr;
+ aRange.iRunAddr = iRunAddr;
+ Extend(aRange.iSize);
+ }
+ }
+
+void TAddressRange::Move(TInt aOffset)
+ {
+ iImagePtr = static_cast<char*>(iImagePtr) + aOffset;
+ iImageAddr += aOffset;
+ iRunAddr += aOffset;
+ }
+
+void TAddressRange::Extend(TInt aOffset)
+ {
+ Move(aOffset);
+ iSize += aOffset;
+ }
+
+////////////////////////////////////////////////////////////////////////
+
+inline TUint32 AlignData(TUint32 anAddr)
+ {
+ return ((anAddr+0x0f)&~0x0f);
+ }
+
+TUint32 E32Rom::AlignToPage(TUint32 anAddr)
+ {
+ TUint a=(TUint)iObey->iPageSize-1;
+ return ((anAddr+a)&~a);
+ }
+
+/*
+Allocate virtual memory for static data in rom.
+@param aAddr Base address of last allocated memory.
+@param aSize Size of memory to allocate.
+@return Address allocated. This is below aAddr.
+*/
+TUint32 E32Rom::AllocVirtual(TUint32 aAddr,TUint aSize)
+ {
+ TInt align = iObey->iVirtualAllocSize;
+ if(align<0)
+ {
+ align = -align; // get correct sign
+ // -ve align means also align to next power-of-two >= aSize...
+ while(aSize>(TUint)align)
+ align <<=1;
+ }
+
+ TUint mask = (TUint)align-1;
+ aSize = (aSize+mask)&~mask; // round up
+ aAddr &= ~mask; // round down
+ return aAddr-aSize;
+ }
+
+TUint32 E32Rom::AlignToChunk(TUint32 anAddr)
+ {
+ TUint a=(TUint)iObey->iChunkSize-1;
+ return ((anAddr+a)&~a);
+ }
+
+COrderedFileList::COrderedFileList(TInt aMaxFiles)
+ : iCount(0), iMaxFiles(aMaxFiles), iOrderedFiles(NULL)
+ {}
+
+COrderedFileList::~COrderedFileList()
+ {
+ iCount=0;
+ if(iOrderedFiles)
+ delete[] iOrderedFiles;
+ }
+
+COrderedFileList* COrderedFileList::New(TInt aMaxFiles)
+ {
+ COrderedFileList *pL=new COrderedFileList(aMaxFiles);
+ pL->iOrderedFiles=new TRomBuilderEntry*[aMaxFiles];
+ return pL;
+ }
+
+void COrderedFileList::Add(TRomBuilderEntry* anEntry)
+ {
+ // note: this routine assumes that the set of kernel-mode files
+ // (primary/extension/device) required by a given variant is linearly ordered by <=
+ // e.g. can't have three variants {A,B,V1} {A,B,C,V2} {A,C,V3} because B and C
+ // are unordered with respect to <=, since neither of
+ // {n | Vn requires B} and {n | Vn requires C} is a subset of the other.
+ // In a case like this, ROMBUILD may fail to resolve the addresses of some global data
+ THardwareVariant& v=anEntry->iHardwareVariant;
+ TInt i=0;
+ while(i<iCount && v<=iOrderedFiles[i]->iHardwareVariant) i++;
+ TInt j=iCount;
+ while(j>i)
+ {
+ iOrderedFiles[j]=iOrderedFiles[j-1];
+ j--;
+ }
+ iOrderedFiles[i]=anEntry;
+ iCount++;
+ }
+
+void GetFileNameAndUid(char *aDllName, TUid &aDllUid, char *aExportName)
+ {
+ strcpy(aDllName, aExportName);
+ aDllUid=KNullUid;
+ TInt start;
+ for (start=0; start<(TInt)strlen(aExportName) && aExportName[start]!='['; start++)
+ ;
+ if (start==(TInt)strlen(aExportName))
+ start=KErrNotFound;
+ TInt end=strlen(aExportName)-1;
+ while (end>=0)
+ {
+ if (aExportName[end]==']')
+ break;
+ --end;
+ }
+ if (end<0)
+ end=KErrNotFound;
+
+ if ((start!=KErrNotFound) && (end!=KErrNotFound) && (end>start))
+ {
+ // Importing from DLL with Uid
+ char uidStr[0x100];
+ strcpy(uidStr, "0x");
+ strncat(uidStr, aExportName+start+1, end-start-1);
+
+
+ if (IsValidNumber(uidStr)){
+ TUint32 u = 0;
+ Val(u,uidStr);
+ aDllUid=TUid::Uid(u);
+ char *dot=aExportName+strlen(aExportName)-1;
+ while (dot>=aExportName)
+ {
+ if (*dot=='.')
+ break;
+ dot--;
+ }
+ if (dot<aExportName) // no dot
+ aDllName[start]=0;
+ else
+ {
+ aDllName[start]=0;
+ strcat(aDllName, dot);
+ }
+ }
+ }
+ }
+
+E32Rom::E32Rom(CObeyFile *aObey) {
+
+ iSize=sizeof(TRomLoaderHeader)+aObey->iRomSize;
+ iObey=aObey;
+ iPeFiles=NULL;
+ iSymGen = NULL ;
+ if(gLowMem)
+ {
+ iImageMap = new Memmap();
+
+ if(iImageMap == NULL)
+ {
+ iSize = 0;
+ Print(EError, "Out of memory.\n");
+ }
+ else
+ {
+ iImageMap->SetMaxMapSize(iSize);
+ if(iImageMap->CreateMemoryMap(0, 0xff) == EFalse)
+ {
+ iSize = 0;
+ Print(EError, "Failed to create image map object");
+
+ iImageMap->CloseMemoryMap(ETrue);
+ delete iImageMap;
+ iImageMap = NULL;
+ }
+ else
+ {
+ iData = iImageMap->GetMemoryMapPointer();
+ }
+ }
+ }
+ else
+ {
+ iData=new char [iSize];
+ if (iData==NULL)
+ {
+ iSize=0;
+ Print(EError, "Out of memory.\n");
+ }
+ HMem::Set(iData, 0xff, iSize);
+ }
+ iHeader=(TRomHeader *)(iData+sizeof(TRomLoaderHeader));
+ iExtensionRomHeader=NULL;
+ iLoaderHeader=(TRomLoaderHeader *)iData;
+ iSectionPtr=(char *)iHeader+aObey->iSectionStart-aObey->iRomLinearBase+sizeof(TRomSectionHeader);
+ TheRomHeader=(ImpTRomHeader *)iHeader;
+ TheRomMem=(TUint32)iHeader;
+ iNextDataChunkBase=aObey->iKernDataRunAddress;
+ iTotalSvDataSize=0;
+ iNextDllDataAddr=aObey->iDllDataTop;
+ iPrevPrimaryAddress=NULL;
+ iPrevVariantAddress=NULL;
+ iVariantFileLists=NULL;
+ iImportsFixedUp=0;
+ iBranchesFixedUp=0;
+ iVtableEntriesFixedUp=0;
+ iOverhead=0;
+ }
+
+E32Rom::~E32Rom() {
+ if(iSymGen){
+ delete iSymGen;
+ iSymGen = NULL ;
+ }
+ if(gLowMem)
+ {
+ iImageMap->CloseMemoryMap(ETrue);
+ delete iImageMap;
+ }
+ else
+ delete iData;
+ delete [] iPeFiles;
+ if (iVariantFileLists)
+ {
+ TInt i;
+ for (i=0; i<iObey->iNumberOfVariants; i++)
+ delete iVariantFileLists[i];
+ delete [] iVariantFileLists;
+ }
+ }
+
+TInt E32Rom::Align(TInt aVal)
+//
+// Align to romalign
+//
+ {
+
+ return ((aVal+iObey->iRomAlign-1)/iObey->iRomAlign)*iObey->iRomAlign;
+ }
+
+TInt E32Rom::LoadContents(char*& anAddr, TRomHeader* aHeader)
+ {
+ // Load all the PE/E32Image files
+ TInt nfiles=iObey->iNumberOfPeFiles;
+ iPeFiles=new TRomBuilderEntry* [nfiles];
+ if (!iPeFiles)
+ return Print(EError, "Out of memory.\n");
+
+ TInt r=TranslateFiles();
+ if (r!=KErrNone)
+ return r;
+
+ ProcessDllData();
+
+ EnumerateVariants();
+
+ r=BuildDependenceGraph();
+ if (r!=KErrNone)
+ return r;
+
+ // Update the ROM image headers with SMP information.
+ SetSmpFlags();
+
+ r=ProcessDependencies();
+ if (r!=KErrNone)
+ return r;
+
+ char* addr = anAddr;
+ TRomExceptionSearchTable* exceptionSearchTable = 0;
+
+ if(gPagedRom)
+ {
+ gDepInfoFile = iObey->iRomFileName;
+ iObey->SetArea().DefaultArea()->SortFilesForPagedRom();
+ // exception search table needs to go at start of ROM to make it not demand paged...
+ addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable);
+ }
+ else if(gGenDepGraph)
+ {
+ Print(EWarning, "Not dependence information in an unpaged ROM.");
+ }
+
+ addr=WriteDirectory(addr, aHeader);
+ // Aligned
+
+ TRACE(TSCRATCH,Print(EAlways,"Directory written\n"));
+
+ // Stick all the files in ROM
+
+ TReloc* relocationTable;
+ addr = AllocateRelocationTable(addr, relocationTable);
+ aHeader->iRelocInfo = relocationTable ? ActualToRomAddress(relocationTable) : 0;
+ // Aligned
+
+ TRACE(TSCRATCH,Print(EAlways,"Done AllocateRelocationTable\n"));
+
+ CalculateDataAddresses();
+ addr = LayoutRom(addr);
+
+ TRACE(TSCRATCH,Print(EAlways,"Done LayoutRom\n"));
+
+ FillInRelocationTable(relocationTable);
+
+ TRACE(TSCRATCH,Print(EAlways,"Done FillInRelocationTable\n"));
+
+ if(!exceptionSearchTable)
+ addr = ReserveRomExceptionSearchTable(addr,exceptionSearchTable);
+ ConstructRomExceptionSearchTable(exceptionSearchTable);
+
+ TRACE(TSCRATCH,Print(EAlways,"Done ConstructRomExceptionSearchTable\n"));
+
+ LinkKernelExtensions(iObey->iExtensions, iObey->iNumberOfExtensions);
+
+ TRACE(TSCRATCH,Print(EAlways,"Done LinkKernelExtensions\n"));
+
+ r=ResolveDllRefTables();
+ if (r!=KErrNone)
+ return r;
+ r=ResolveImports();
+ if (r!=KErrNone)
+ return r;
+ if (iObey->iCollapseMode>ECollapseNone)
+ {
+ r=CollapseImportThunks();
+ if (r!=KErrNone)
+ return r;
+ if (iObey->iCollapseMode>ECollapseImportThunksOnly)
+ {
+ r=CollapseBranches();
+ if (r!=KErrNone)
+ return r;
+ }
+ Print(ELog,"%d imports, %d branches, %d vtable entries fixed up\n",
+ iImportsFixedUp,iBranchesFixedUp,iVtableEntriesFixedUp);
+ }
+
+ iSizeUsed=(TInt)addr-(TInt)iHeader;
+ Print(ELog, "\n%08x of %08x bytes used.\n", iSizeUsed, iSize-sizeof(TRomLoaderHeader));
+
+ // round the rom size in the header to a multiple of 1 Megabyte
+ TInt rounded = ((iSizeUsed+0xfffff)&0xfff00000);
+ if (rounded < iObey->iRomSize)
+ iObey->iRomSize = rounded;
+ iUncompressedSize = iSizeUsed;
+
+ anAddr = addr;
+
+ return KErrNone;
+ }
+
+
+void E32Rom::CreatePageIndex(char*& aAddr)
+ {
+ iHeader->iRomPageIndex = 0;
+ if(gPagedRom==0 || gEnableCompress==0)
+ return;
+
+ // Insert space for Rom Page Info table...
+ iHeader->iRomPageIndex = (TInt)aAddr-(TInt)iHeader;
+ TInt pageSize = iObey->iPageSize;
+ TInt numPages = iSize/pageSize+1;
+ TInt pageInfoSize = numPages*sizeof(SRomPageInfo);
+
+ gPageIndexTableSize = pageInfoSize; // For accumulate uncompressed un-paged size added Page Index Table
+
+ Print(ELog, "Inserting %d bytes for RomPageInfo at ROM offset 0x%08x\n", pageInfoSize, iHeader->iRomPageIndex);
+ memset(aAddr,0,pageInfoSize);
+ iOverhead += pageInfoSize;
+ aAddr += pageInfoSize;
+ }
+
+TInt E32Rom::SetupPages()
+ {
+ iHeader->iPageableRomStart = 0;
+ iHeader->iPageableRomSize = 0;
+ iHeader->iDemandPagingConfig = gDemandPagingConfig;
+
+ if(!gPagedRom)
+ return KErrNone;
+
+ // Initialise the Rom Page Info for each page which indicates it is uncompressed...
+ TInt pageSize = iObey->iPageSize;
+
+ TInt pagedStartOffset = 0x7fffffff;
+ TRomBuilderEntry* e = iObey->SetArea().DefaultArea()->iFirstPagedCode;
+ if(e)
+ {
+ // we have paged code...
+ pagedStartOffset = e->RomEntry()->iAddressLin-iObey->iRomLinearBase;
+ pagedStartOffset = (pagedStartOffset+pageSize-1)&~(pageSize-1); // round up to next page;
+ iHeader->iPageableRomStart = pagedStartOffset;
+ TInt pageableSize = iSizeUsed-pagedStartOffset;
+ if(pageableSize>0)
+ iHeader->iPageableRomSize = pageableSize;
+ }
+
+ return KErrNone;
+ }
+
+TInt E32Rom::CompressPages()
+ {
+
+ if(!gPagedRom || !gEnableCompress)
+ return KErrNone;
+
+ // Initialise the Rom Page Info for each page which indicates it is uncompressed...
+ TInt pageSize = iObey->iPageSize;
+ TInt numPages = (iSizeUsed+pageSize-1)/pageSize;
+
+ TInt pagedStartOffset = iHeader->iPageableRomStart;
+
+ Print(EAlways, "\nCompressing pages...\n");
+ TInt inOffset = 0;
+ SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex);
+ TInt currentIndex = 0;
+ while(inOffset < pagedStartOffset)
+ {
+
+ TUint8 attrib = (TUint8)0;
+ SRomPageInfo info = {(TUint32)inOffset,(TUint16)pageSize,(TUint8)SRomPageInfo::EBytePair,(TUint8)attrib};
+ info.iDataSize = (TUint16) pageSize;
+ *pi++ = info;
+ inOffset += pageSize;
+ if((currentIndex & 255) == 255)
+ Print(EAlways, ".\n");
+ currentIndex++;
+ }
+ CompressPageWorker compressworker(this, pageSize, numPages, currentIndex);
+
+ boost::thread_group threads;
+ for(int i = 0; i < gThreadNum; i++)
+ {
+ threads.create_thread(compressworker);
+ }
+ threads.join_all();
+ if(compressworker.m_error < 0)
+ return compressworker.m_error;
+ for(;currentIndex < numPages - 1; currentIndex++)
+ {
+ pi++;
+ SRomPageInfo* prev = pi - 1;
+ TUint8* dest = (TUint8*) iHeader + prev->iDataStart + prev->iDataSize;
+ TUint8* src = (TUint8*) iHeader + pi->iDataStart;
+ memcpy(dest, src, pi->iDataSize);
+ pi->iDataStart = prev->iDataStart + prev->iDataSize;
+ }
+ TInt relSize = pi->iDataStart + pi->iDataSize;
+
+ memset((TUint8*)iHeader + relSize, 0xff, iSizeUsed - relSize);
+ TInt compression = (iSizeUsed >= 1000) ? (relSize*10)/(iSizeUsed/1000) : (relSize*10000)/iSizeUsed;
+ Print(EAlways, "%d.%02d%%\n", compression/100, compression%100);
+ iSizeUsed = relSize;
+ return KErrNone;
+ }
+
+TInt E32Rom::CompressPage(SRomPageInfo& aPageInfo, TInt aOutOffset, CBytePair * aBPE)
+ {
+ TUint8* in = (TUint8*)iHeader+aPageInfo.iDataStart;
+ TInt inSize = aPageInfo.iDataSize;
+ TUint8* out = (TUint8*)iHeader+aOutOffset;
+ switch(aPageInfo.iCompressionType)
+ {
+ case SRomPageInfo::ENoCompression:
+ memcpy(out,in,inSize);
+ return inSize;
+
+ case SRomPageInfo::EBytePair:
+ {
+ TInt r = BytePairCompress(out, in, inSize, aBPE);
+ if(r!=KErrTooBig)
+ return r;
+ // data can't be compressed...
+ aPageInfo.iCompressionType = SRomPageInfo::ENoCompression;
+ memcpy(out,in,inSize);
+ return inSize;
+ }
+
+ default:
+ Print(EError, "Unsupported page compression type (%d)\n", aPageInfo.iCompressionType);
+ return KErrNotSupported;
+ }
+ }
+
+
+// Avoid "warning" about constant expression
+static void checksize(const char* aTypeName, int aSize, int aCorrectSize)
+ {
+ if (aSize != aCorrectSize)
+ Print(EError, "sizeof(%s) = %d, should be %d\n", aTypeName, aSize, aCorrectSize);
+ }
+
+TInt E32Rom::CreateExtension(MRomImage* aKernelRom)
+ {
+
+ // sanity check
+ checksize("TExtensionRomHeader", sizeof(TExtensionRomHeader), 128);
+
+ char *addr=(char *)iHeader;
+ iExtensionRomHeader=(TExtensionRomHeader*)addr;
+ addr += sizeof(TExtensionRomHeader);
+ // Aligned
+
+ TRomHeader dummy;
+ TInt r=LoadContents(addr, &dummy);
+ if (r!=KErrNone)
+ {
+ Print(EError, "LoadContents failed - return code %d\n", r);
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return r;
+ }
+ iExtensionRomHeader->iRomRootDirectoryList = dummy.iRomRootDirectoryList;
+
+ iLoaderHeader->SetUp(iObey);
+ FinaliseExtensionHeader(aKernelRom);
+ DisplayExtensionHeader();
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return KErrNone;
+ }
+
+TInt E32Rom::Create()
+ {
+
+ TVariantList::Setup(iObey);
+ char *addr=(char *)iHeader;
+ // Aligned
+
+ // Put the bootstrap in rom - it contains a hole at offset 0x80 where the
+ // TRomHeader information will be placed later
+
+ gBootstrapSize = HFile::Read(iObey->iBootFileName, iHeader);
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "bootstrapSize: 0x%08x, (%d)\n", gBootstrapSize, gBootstrapSize);
+
+ if (gBootstrapSize==0)
+ return Print(EError, "Cannot open the bootstrap file '%s'.\n", iObey->iBootFileName);
+ gBootstrapSize=Align(gBootstrapSize);
+ addr+=gBootstrapSize;
+ iOverhead=gBootstrapSize;
+ // Aligned
+
+ CreatePageIndex(addr);
+
+ TInt r=LoadContents(addr, iHeader);
+ if (r!=KErrNone)
+ {
+ Print(EError, "LoadContents failed - return code %d\n", r);
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return r;
+ }
+
+ r = SetupPages(); // initialize ROM paging info...
+ if(r!=KErrNone)
+ {
+ Print(EError, "Setup pages information failed - return code %d\n", r);
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return r;
+ }
+
+ r = CheckUnpagedMemSize(); // check for unpaged memory overflow
+ if(r!=KErrNone)
+ {
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return r;
+ }
+
+ r = CompressPages(); // setup ROM paging info...
+ if(r!=KErrNone)
+ {
+ Print(EError, "CompressPages failed - return code %d\n", r);
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return r;
+ }
+
+ iLoaderHeader->SetUp(iObey);
+ ImpTRomHeader* header = (ImpTRomHeader *)iHeader;
+ header->SetUp(iObey);
+ header->iTotalSvDataSize=iTotalSvDataSize;
+ if (iObey->iMemModel==E_MM_Direct)
+ {
+ header->iUserDataAddress=iObey->iDataRunAddress;
+ header->iTotalUserDataSize=iNextDataChunkBase-iObey->iDataRunAddress;
+ }
+ else
+ {
+ header->iUserDataAddress=iObey->iDllDataTop;
+ header->iTotalUserDataSize=iObey->iDllDataTop-iNextDllDataAddr;
+ }
+ if (header->iRomSectionHeader)
+ FinaliseSectionHeader(); // sorts out the second section checksum
+
+ header->CheckSum(iObey->iCheckSum); // finally, sort out the overall checksum
+
+ header->Display();
+
+ TUint testCheckSum = HMem::CheckSum((TUint *)iHeader, iHeader->iRomSize);
+ Print(ELog, "Rom 32bit words sum to %08x\n", testCheckSum);
+ if (testCheckSum != iObey->iCheckSum){
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return Print(EError, "Rom checksum is incorrect: %08x should be %08x\n",
+ testCheckSum, iObey->iCheckSum);
+ }
+
+ // 8bit checksum = sum of bytes
+ // odd/even checksum = checksum of the odd and even halfwords of the image
+
+ Print(ELog, "Rom 8bit checksum %08x\n", HMem::CheckSum8((TUint8 *)iHeader, iHeader->iRomSize));
+ Print(ELog, "Rom 8bit odd checksum %08x\n", HMem::CheckSumOdd8((TUint8 *)iHeader, iHeader->iRomSize));
+ Print(ELog, "Rom 8bit even checksum %08x\n", HMem::CheckSumEven8((TUint8 *)iHeader, iHeader->iRomSize));
+
+ if (iHeader->iPrimaryFile)
+ {
+ if (iObey->iKernelModel==ESingleKernel)
+ {
+ Print(ELog,"\nPrimary details (Single Kernel):\n");
+ TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader);
+ TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader);
+ Display(hdr);
+ Print(ELog,"\n");
+ }
+ else if (iObey->iKernelModel==EMultipleKernels)
+ {
+ Print(ELog,"\nPrimary details (Multiple Kernels):\n");
+ TRomEntry *r = (TRomEntry *)(iHeader->iPrimaryFile-iObey->iRomLinearBase+(char *)iHeader);
+ TInt n=1;
+ FOREVER
+ {
+ Print(ELog,"\nKernel %d:\n",n);
+ TRomImageHeader *hdr = (TRomImageHeader *)(r->iAddressLin-iObey->iRomLinearBase+(char *)iHeader);
+ Display(hdr);
+ Print(ELog,"\n");
+ if (!hdr->iNextExtension)
+ break;
+ r=(TRomEntry*)(hdr->iNextExtension-iObey->iRomLinearBase+(char*)iHeader);
+ n++;
+ }
+ }
+ }
+ if(iSymGen)
+ iSymGen->WaitThreads();
+ return KErrNone;
+ }
+
+char *E32Rom::WriteDirectory(char *aAddr, TRomHeader* aHeader)
+//
+// Write the directory structure where appropriate
+//
+ {
+
+ TLinAddr dirptr=ActualToRomAddress(aAddr);
+ if (iObey->iSectionPosition==-1)
+ {
+ // Just the one rom. Put the directory structure at aAddr
+ iDirectorySize=WriteHeadersToRom(aAddr);
+ aAddr+=Align(iDirectorySize);
+ }
+ else
+ {
+ // Put the directory structure in the second ROM, after the SectionHeader
+ // and the second section information for first section files
+ TInt size=0;
+ TInt i;
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRomBuilderEntry *file=iPeFiles[i];
+ if (file->iRomSectionNumber!=0)
+ break;
+ TInt size1, size2;
+ file->SizeInSections(size1,size2);
+ size+=size2;
+ }
+ dirptr=ActualToRomAddress(iSectionPtr)+size;
+ iDirectorySize=WriteHeadersToRom(RomToActualAddress(dirptr));
+ }
+ aHeader->iRomRootDirectoryList=dirptr;
+ return aAddr;
+ }
+
+void E32Rom::Display(TRomImageHeader *aHdr)
+//
+// Print info on a file
+//
+ {
+ TRACE(TAREA, Print(ELog, "+Display header %08x\n", aHdr));
+ Print(ELog, "Uids: %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum);
+ Print(ELog, "Entry point: %08x\n", aHdr->iEntryPoint);
+ Print(ELog, "Code start addr: %08x\n", aHdr->iCodeAddress);
+ Print(ELog, "Data start addr: %08x\n", aHdr->iDataAddress);
+ Print(ELog, "DataBssLinearBase: %08x\n", aHdr->iDataBssLinearBase);
+ Print(ELog, "Text size: %08x\n", aHdr->iTextSize);
+ Print(ELog, "Code size: %08x\n", aHdr->iCodeSize);
+ Print(ELog, "Data size: %08x\n", aHdr->iDataSize);
+ Print(ELog, "BssSize: %08x\n", aHdr->iBssSize);
+ Print(ELog, "Total data size: %08x\n", aHdr->iTotalDataSize);
+ Print(ELog, "Heap min: %08x\n", aHdr->iHeapSizeMin);
+ Print(ELog, "Heap max: %08x\n", aHdr->iHeapSizeMax);
+ Print(ELog, "Stack size: %08x\n", aHdr->iStackSize);
+ Print(ELog, "Dll ref table: %08x\n", aHdr->iDllRefTable);
+ Print(ELog, "Export directory: %08x\n", aHdr->iExportDir);
+ Print(ELog, "Export dir count: %08x\n", aHdr->iExportDirCount);
+ Print(ELog, "Hardware variant: %08x\n", aHdr->iHardwareVariant);
+ Print(ELog, "Flags: %08x\n", aHdr->iFlags);
+ Print(ELog, "Secure ID: %08x\n", aHdr->iS.iSecureId);
+ Print(ELog, "Vendor ID: %08x\n", aHdr->iS.iVendorId);
+ Print(ELog, "Capability: %08x %08x\n", aHdr->iS.iCaps[1], aHdr->iS.iCaps[0]);
+ Print(ELog, "Tools Version: %d.%02d(%d)\n", aHdr->iToolsVersion.iMajor, aHdr->iToolsVersion.iMinor, aHdr->iToolsVersion.iBuild);
+ Print(ELog, "Module Version: %d.%d\n", aHdr->iModuleVersion>>16, aHdr->iModuleVersion&0x0000ffffu);
+ Print(ELog, "Exception Descriptor: %08x\n", aHdr->iExceptionDescriptor);
+ Print(ELog, "Priority: %d\n", aHdr->iPriority);
+ }
+
+void E32Rom::DisplaySizes(TPrintType aWhere)
+ {
+
+ Print(aWhere, "Summary of file sizes in rom:\n");
+ Print(aWhere, "Overhead (bootstrap+gaps+sectioning)\t%d\n", iOverhead);
+ Print(aWhere, "Overhead (directory size)\t%d\n", iDirectorySize);
+ TRomBuilderEntry *file=iObey->FirstFile();
+ while (file)
+ {
+ file->DisplaySize(aWhere);
+ file=iObey->NextFile();
+ }
+ Print(aWhere, "\nTotal used\t%d\n", iSizeUsed);
+ Print(aWhere, "Free\t%d\n", iObey->iRomSize-iSizeUsed);
+
+ if (iObey->SetArea().Count() > 1)
+ {
+ Print(aWhere, "\nArea summary:\n");
+ for (NonDefaultAreasIterator it(iObey->SetArea());
+ ! it.IsDone();
+ it.GoToNext())
+ {
+ const Area& a = it.Current();
+ Print(aWhere, "%s\t used: %d bytes / free: %d bytes\n",
+ a.Name(), a.UsedSize(), a.MaxSize()-a.UsedSize());
+ }
+ }
+ }
+
+TInt E32Rom::RequiredSize()
+//
+// Get the (approximate) required size of the Rom
+//
+ {
+
+ TInt sum=0;
+ TRomBuilderEntry *current=iObey->FirstFile();
+ while (current)
+ {
+ if (current->iResource || current->HCRDataFile())
+ sum+=Align(HFile::GetLength(current->iFileName));
+ else
+ sum+=Align(current->SizeInRom());
+ current=iObey->NextFile();
+ }
+ return sum+iOverhead+Align(iDirectorySize);
+ }
+
+TInt E32Rom::TranslateFiles()
+//
+// Load and translate all PE/E32 image files
+//
+ {
+
+ TInt i=0;
+ TInt total_errors = 0;
+ TRomBuilderEntry* current = 0;
+ EntryQueue imagesQueue;
+ for (current = iObey->FirstFile(); current; current = iObey->NextFile() )
+ {
+ if ((!current->iResource) && (!current->HCRDataFile()))
+ {
+ iPeFiles[i++]=current;
+ imagesQueue.push(current);
+ }
+ }
+ LoadImageWorker loadworker(&imagesQueue, iObey->iMemModel);
+ boost::thread_group threads;
+ for(int i = 0; i < gThreadNum; i++)
+ {
+ threads.create_thread(loadworker);
+ }
+ threads.join_all();
+
+ total_errors = loadworker.m_errors;
+ if (total_errors)
+ return KErrGeneral;
+ for (current = iObey->FirstFile(); current; current = iObey->NextFile() )
+ {
+ if ((!current->iResource) && (!current->HCRDataFile()))
+ {
+ TInt err = CheckForVersionConflicts(current);
+ total_errors += err;
+ }
+ }
+ return total_errors ? KErrGeneral : KErrNone;
+ }
+
+const char FileTypeFile[]= "File ";
+const char FileTypePrimary[]= "Primary ";
+const char FileTypeVariant[]= "Variant ";
+const char FileTypeExtension[]="Extension";
+const char FileTypeDevice[]= "Device ";
+
+void E32Rom::EnumerateVariants()
+ {
+ TInt vIndex;
+ TInt nFiles=iObey->iNumberOfExtensions+iObey->iNumberOfDevices+3;
+ iVariantFileLists=new COrderedFileList*[iObey->iNumberOfVariants];
+ for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
+ iVariantFileLists[vIndex]=COrderedFileList::New(nFiles);
+ for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
+ {
+ TRomBuilderEntry *variant=iObey->iVariants[vIndex];
+ THardwareVariant& v=variant->iHardwareVariant;
+ TInt i;
+ for (i=0; i<iObey->iNumberOfPrimaries; i++)
+ {
+ TRomBuilderEntry *primary=iObey->iPrimaries[i];
+ if (v<=primary->iHardwareVariant)
+ {
+ iVariantFileLists[vIndex]->Add(primary);
+ break;
+ }
+ }
+ iVariantFileLists[vIndex]->Add(variant);
+ for (i=0; i<iObey->iNumberOfExtensions; i++)
+ {
+ TRomBuilderEntry *ext=iObey->iExtensions[i];
+ if (v<=ext->iHardwareVariant)
+ {
+ iVariantFileLists[vIndex]->Add(ext);
+ }
+ }
+ for (i=0; i<iObey->iNumberOfDevices; i++)
+ {
+ TRomBuilderEntry *dev=iObey->iDevices[i];
+ if (v<=dev->iHardwareVariant)
+ {
+ iVariantFileLists[vIndex]->Add(dev);
+ }
+ }
+ }
+ TUint totalDataBss=0;
+ for (vIndex=0; vIndex<iObey->iNumberOfVariants; vIndex++)
+ {
+ TRomBuilderEntry *variant=iObey->iVariants[vIndex];
+ THardwareVariant& v=variant->iHardwareVariant;
+ COrderedFileList& files=*iVariantFileLists[vIndex];
+ TInt count=files.Count();
+ Print(ELog,"\nVariant %08x, %d Files:\n",v.ReturnVariant(),count);
+ TInt i;
+ TUint dataOffset=0;
+ for (i=0; i<count; i++)
+ {
+ TRomBuilderEntry *pF=files[i];
+ TUint gap=0;
+ if (pF->iDataAlignment>0)
+ {
+ gap=(pF->iDataAlignment-dataOffset)%(pF->iDataAlignment);
+ dataOffset+=gap;
+ }
+ E32ImageHeader *pH=pF->iHdr;
+ if (pF->iDataBssOffset!=0xffffffff && pF->iDataBssOffset!=dataOffset)
+ Print(EError,"Conflicting DataBss addresses\n");
+ pF->iDataBssOffset=dataOffset;
+ TInt dataSize=AlignData(pH->iDataSize+pH->iBssSize);
+ const char* pT=FileTypeFile;
+ if (pF->Primary())
+ pT=FileTypePrimary;
+ if (pF->Variant())
+ pT=FileTypeVariant;
+ if (pF->Extension())
+ pT=FileTypeExtension;
+ if (pF->Device())
+ pT=FileTypeDevice;
+ Print(ELog,"%s %12s[%08x] DataSize=%6x DataOffset=%6x",pT,pF->iName,pF->iHardwareVariant.ReturnVariant(),dataSize,dataOffset);
+ if (gap)
+ Print(ELog, " (gap %x for %x alignment)\n", gap, pF->iDataAlignment);
+ Print(ELog, "\n");
+ dataOffset+=dataSize;
+ }
+ if (dataOffset>totalDataBss)
+ totalDataBss=dataOffset;
+ }
+ Print(ELog,"\nTotal SvData size=%6x\n",totalDataBss);
+ iTotalSvDataSize=totalDataBss;
+ }
+
+TInt E32Rom::LoadDataToRom(TRomBuilderEntry *aFile, TAddressRange& aAddress, CBytePair* aBPE)
+//
+// Load a data file to rom
+//
+ {
+ const char* tn = "resource";
+ if (aFile->iNonXIP)
+ tn = (aFile->iCompression) ? "compressed executable" : "uncompressed executable";
+ Print(ELog,"Reading %s %s to rom linear address %08x\n", tn, aFile->iFileName, aAddress.iImageAddr);
+
+ TUint32 size=HFile::GetLength(aFile->iFileName);
+ if (size==0)
+ {
+ Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",aFile->iFileName);
+ return size;
+ }
+
+ aFile->iHeaderRange=aAddress;
+ char* addr = (char*)aFile->iHeaderRange.iImagePtr;
+ const char* src = NULL;
+ ostringstream os;
+ if (aFile->iNonXIP)
+ {
+ E32ImageFile f(aBPE);
+ TInt r = f.Open(aFile->iFileName);
+ // is it really a valid E32ImageFile?
+ if (r != KErrNone)
+ {
+ Print(EWarning, "File '%s' is not a valid executable. Loading file as data.\n", aFile->iFileName);
+ aFile->iNonXIP = EFalse;
+ }
+ else
+ {
+ TUint compression = f.iHdr->CompressionType();
+ if (compression != aFile->iCompression || aFile->iPreferred)
+ {
+ if (compression == 0)
+ Print(ELog, "Compressing file %s\n", aFile->iFileName);
+ else if (aFile->iCompression == 0)
+ Print(ELog, "Decompressing file %s\n", aFile->iFileName);
+ f.iHdr->iCompressionType = aFile->iCompression;
+ if (aFile->iPreferred)
+ {
+ f.iHdr->iModuleVersion &= ~0xffffu;
+ f.iHdr->iModuleVersion |= 0x8000u;
+ }
+ f.UpdateHeaderCrc();
+ }
+ Print(ELog, "Compression Method:0x%08x/0x%08x \n", f.iHdr->CompressionType(), aFile->iCompression);
+ os << f;
+ size = (os.str()).length();
+ src = (os.str()).c_str();
+ }
+ }
+ if (addr+size>iData+iSize)
+ {
+ Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName);
+ Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize);
+ exit(667);
+ }
+ if (src)
+ memcpy(addr, src, size);
+ else
+ size = HFile::Read(aFile->iFileName, (TAny *)addr);
+ Print(ELog,"Size: %08x\n", size);
+
+ aFile->iHeaderRange.iSize=size;
+ aAddress.Extend(aFile->iHeaderRange.iSize);
+ return size;
+ }
+
+
+void E32Rom::CalculateDataAddresses()
+//
+//
+//
+ {
+
+ TInt i;
+ TUint32 maxkern = 0;
+ Print(ELog, "\nCalculating kernel limit.\n");
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRomBuilderEntry* e = iPeFiles[i];
+ if (e->Primary())
+ {
+ // this is a kernel
+ TUint32 stack = AlignToPage(e->iHdr->iStackSize);
+ TUint32 heap = AlignToPage(e->iHdr->iHeapSizeMax);
+ if (stack + heap > maxkern)
+ maxkern = stack + heap;
+ }
+ }
+ iObey->iKernelLimit = AlignToChunk(maxkern + iTotalSvDataSize) + iObey->iKernDataRunAddress;
+ if (iObey->iMemModel==E_MM_Direct)
+ iNextDataChunkBase=iObey->iDataRunAddress;
+ else
+ iNextDataChunkBase = iObey->iKernelLimit;
+ Print(ELog, "\nCalculating data addresses.\n");
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRACE(TAREA,Print(ELog,"CalculateDataAddresses %d %s\n",i,iPeFiles[i]->iFileName));
+ CalculateDataAddress(iPeFiles[i]);
+ }
+ TRACE(TIMPORT,Print(ELog,"CalculateDataAddresses complete\n"));
+
+ // On moving model, advance kernel limit past fixed process data areas
+ if (iObey->iMemModel==E_MM_Moving)
+ iObey->iKernelLimit = iNextDataChunkBase;
+ }
+
+void E32Rom::CalculateDataAddress(TRomBuilderEntry *aFile)
+//
+// Work out where the .data/.bss will be
+//
+ {
+ TUint32 dataBssSize=aFile->iRomNode->iRomFile->iTotalDataBss;
+ TUint32 dataRunAddr;
+ if (aFile->Primary())
+ {
+ dataRunAddr = iObey->iKernDataRunAddress;
+ CPU = aFile->iHdr->CpuIdentifier();
+ }
+ else
+ {
+ dataRunAddr = iObey->iDataRunAddress;
+ if (iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible && (aFile->iHdr->iFlags & KImageFixedAddressExe)) // propagate 'fixed' from PETRAN
+ {
+ dataRunAddr=0xffffffff;
+ }
+ }
+ if (aFile->iOverrideFlags&KOverrideAddress)
+ {
+ if ((iObey->iMemModel!=E_MM_Multiple && iObey->iMemModel!=E_MM_Flexible) || aFile->iRelocationAddress!=0xffffffff)
+ dataRunAddr=aFile->iRelocationAddress;
+ if (aFile->Extension() || aFile->Variant() || aFile->Device())
+ Print(EError, "reloc not permitted with extension/variant/device\n");
+ }
+ if (!aFile->IsDll() && !aFile->Primary() && (dataRunAddr==0xffffffff || iObey->iMemModel==E_MM_Direct))
+ {
+ dataRunAddr=iNextDataChunkBase;
+ TInt stackreserve=iObey->iDefaultStackReserve;
+ if (aFile->iOverrideFlags & KOverrideStackReserve)
+ stackreserve=aFile->iStackReserve;
+ TInt datsize=AlignToChunk(dataBssSize+stackreserve);
+ // Move target data address to next free chunk
+ iNextDataChunkBase+=datsize;
+ }
+ if (aFile->Extension() || aFile->Device() || aFile->Variant())
+ {
+ dataRunAddr=iObey->iKernDataRunAddress+aFile->iDataBssOffset;
+ }
+ else if (aFile->IsDll() && dataBssSize!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe<0)
+ {
+ iNextDllDataAddr = AllocVirtual(iNextDllDataAddr,dataBssSize);
+ dataRunAddr=iNextDllDataAddr;
+ }
+ if (iObey->iMemModel==E_MM_Moving && dataRunAddr==iObey->iDataRunAddress && aFile->Secondary())
+ {
+ Print(EWarning,"Secondary not fixed\n");
+ }
+
+ TRACE(TAREA, Print(ELog, "Data run address %08x\n", dataRunAddr));
+ aFile->iDataBssLinearBase=dataRunAddr;
+ }
+
+void E32Rom::LoadFileToRom(TRomBuilderEntry *aFile)
+//
+// Load an E32Image/PE file to rom
+//
+ {
+
+ char* addr = (char*)aFile->iHeaderRange.iImagePtr;
+ TRACE(TAREA, Print(ELog,"+LoadFileToRom addr %08x %08x %08x\n", addr,
+ aFile->iHeaderRange.iImageAddr, aFile->iHeaderRange.iRunAddr));
+
+ if (addr+aFile->SizeInRom()>iData+iSize) // check this
+ {
+ Print(EError, "Can't fit '%s' in Rom.\n", aFile->iFileName);
+ Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", RequiredSize()-iObey->iRomSize);
+ exit(666);
+ }
+
+ // check file will not overflow into next ROM
+ if (aFile->Primary())
+ {
+ if (!iPrevPrimaryAddress)
+ iHeader->iPrimaryFile=ActualToRomAddress(aFile->RomEntry());
+ else if (iObey->iKernelModel==EMultipleKernels)
+ {
+ ((TRomImageHeader*)iPrevPrimaryAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry());
+ }
+ iPrevPrimaryAddress=addr;
+ TRACE(TAREA, Print(ELog, "iHeader->iPrimaryFile = %08x\n", iHeader->iPrimaryFile));
+ }
+
+ // Place the file in rom
+ if (aFile->Variant())
+ {
+ if (iPrevVariantAddress)
+ ((TRomImageHeader*)iPrevVariantAddress)->iNextExtension=ActualToRomAddress(aFile->RomEntry());
+ else
+ iHeader->iVariantFile=ActualToRomAddress(aFile->RomEntry());
+ iPrevVariantAddress=addr;
+ }
+ if (aFile->IsDll() && aFile->iRomNode->iRomFile->iTotalDataBss!=0 && aFile->iRomNode->iRomFile->iDataBssOffsetInExe>=0)
+ {
+ TRomFile* f=aFile->iRomNode->iRomFile->iPDeps[0]; // attach process
+ aFile->iDataBssLinearBase = f->DataBssLinearBase() + aFile->iRomNode->iRomFile->iDataBssOffsetInExe;
+ }
+
+ aFile->LoadToRom();
+ }
+
+char *E32Rom::LayoutRom(char *romaddr)
+//
+// Layout the files from the obey file starting at romaddr in the image
+// dealing correctly with areas
+// Also deals with two section ROMs
+//
+ {
+
+ TAddressRange main;
+ TAddressRange* mainptr=&main;
+ SetImageAddr(main, romaddr);
+
+ TAddressRange second;
+ TAddressRange* secondptr=0;
+ if (iObey->iSectionStart != 0)
+ {
+ SetImageAddr(second,iSectionPtr);
+ secondptr = &second;
+ }
+
+ TInt fileCount=0;
+ if(gGenSymbols && !iSymGen) {
+ string filename(iObey->GetFileName());
+ filename.erase(filename.length() - 3,3);
+ filename.append("symbol");
+ iSymGen = new SymbolGenerator(filename.c_str(),gThreadNum - 1);
+ }
+
+ //
+ // Process files in non default areas
+ //
+
+ CBytePair bpe;
+ for (NonDefaultAreasIterator areaIt(iObey->SetArea());
+ ! areaIt.IsDone();
+ areaIt.GoToNext())
+ {
+ Area& currentArea = areaIt.Current();
+ currentArea.SetSrcBaseAddr(mainptr->iImageAddr);
+
+ mainptr->iRunAddr = currentArea.DestBaseAddr();
+
+ for (FilesInAreaIterator fileIt(currentArea);
+ ! fileIt.IsDone();
+ fileIt.GoToNext())
+ {
+ TRomBuilderEntry* currentFile = fileIt.Current();
+
+ LayoutFile(currentFile, *mainptr, secondptr, &bpe);
+
+ TUint overflow;
+ if (! currentArea.ExtendSrcLimitAddr(mainptr->iImageAddr, overflow))
+ {
+ Print(EError, "Can't fit '%s' in area '%s'\n", currentFile->iFileName, currentArea.Name());
+ Print(EError, "Area overflowed by 0x%x bytes.\n", overflow);
+ exit(666);
+ }
+
+ ++fileCount;
+ assert(iObey->iSectionPosition == -1 || fileCount < iObey->iSectionPosition);
+ }
+
+ TInt offset=(char*)mainptr->iImagePtr-romaddr;
+ mainptr->Extend(Align(offset)-offset);
+ } // for every non default area
+
+
+ //
+ // Process files in default area
+ //
+
+ mainptr->iRunAddr = mainptr->iImageAddr;
+
+ for (FilesInAreaIterator fileIt(*(iObey->SetArea().DefaultArea()));
+ ! fileIt.IsDone();
+ fileIt.GoToNext())
+ {
+ if (fileCount==iObey->iSectionPosition)
+ {
+ // skip rest of first section and pick up after the
+ // information already accumulated in the second section
+ NextRom(mainptr, secondptr);
+ mainptr = secondptr;
+ secondptr = 0;
+ }
+
+ LayoutFile(fileIt.Current(), *mainptr, secondptr, &bpe);
+
+ ++fileCount;
+ }
+
+ // align to likely position of next file
+ TInt offset=(char*)mainptr->iImagePtr-romaddr;
+ offset = Align(offset)-offset;
+ mainptr->Extend(offset);
+ iOverhead +=offset;
+ if(iSymGen){
+ SymGenContext context ;
+ memset(&context,0,sizeof(SymGenContext));
+ iSymGen->AddEntry(context);
+ }
+ return (char*)mainptr->iImagePtr;
+ }
+
+void E32Rom::LayoutFile(TRomBuilderEntry* current, TAddressRange& aMain, TAddressRange* aSecond, CBytePair * aBPE)
+//
+// Work out where to place a file in ROM and set up the
+// appropriate TAddressRange information
+//
+ {
+ TInt alignment = iObey->iRomAlign;
+ if (current->iAlignment > alignment)
+ alignment = current->iAlignment;
+
+ if (alignment)
+ {
+ // Align this file on a boundary
+ TUint32 romaddr=aMain.iRunAddr;
+ TInt i=romaddr & (alignment-1);
+ TInt gap=0;
+ if (i!=0)
+ gap=alignment-i;
+ if (current->iAlignment)
+ Print(ELog, "\nAlign to %08x. Skipped %d bytes\n", romaddr+gap, gap);
+ aMain.Extend(gap);
+ iOverhead += gap;
+ }
+
+ if (current->iCodeAlignment != 0)
+ {
+ TUint32 runaddr=aMain.iRunAddr + sizeof(TRomImageHeader);
+ TInt i=runaddr & (current->iCodeAlignment-1);
+ TInt gap=0;
+ if (i!=0)
+ gap=current->iCodeAlignment-i;
+ Print(ELog, "\nCode Align to %08x. Skipped %d bytes\n", runaddr+gap, gap);
+ aMain.Extend(gap);
+ iOverhead += gap;
+ }
+
+ Print(ELog,"\n********************************************************************\n");
+
+ if (current->iPatched)
+ Print(ELog, "[Patched file]\n");
+ TLinAddr savedAddr = aMain.iImageAddr;
+ if (current->iResource)
+ {
+ TInt size=LoadDataToRom(current, aMain, aBPE);
+ if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
+ return; // first section has overflowed
+ current->FixupRomEntries(size);
+ if(iSymGen) {
+ SymGenContext context ;
+ memset(&context,0,sizeof(SymGenContext));
+ context.iFileName = current->iFileName ;
+ context.iDataAddress = savedAddr ;
+ iSymGen->AddEntry(context);
+ }
+ return;
+ }
+ if(current->HCRDataFile()){
+ TInt size=LoadDataToRom(current, aMain, aBPE);
+ if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
+ return; // first section has overflowed
+ current->FixupRomEntries(size);
+ iHeader->iHcrFileAddress = current->iHeaderRange.iImageAddr ;
+ TRACE(TAREA, Print(ELog, "iHeader->iHcrFileAddress = %08x\n", iHeader->iHcrFileAddress));
+ if(iSymGen) {
+ SymGenContext context ;
+ memset(&context,0,sizeof(SymGenContext));
+ context.iFileName = current->iFileName ;
+ context.iDataAddress = savedAddr ;
+ iSymGen->AddEntry(context);
+ }
+ return ;
+ }
+ Print(ELog,"Processing file %s\n",current->iFileName);
+
+ if (current->Primary())
+ {
+ Print(ELog, "[Primary]\n");
+ }
+
+ if (current->Secondary())
+ {
+ iHeader->iSecondaryFile=ActualToRomAddress(current->RomEntry());
+ Print(ELog, "[Secondary]\n");
+ }
+
+ // Section 1 things
+ //
+ // TRomImageHeader, text, export directory, data
+
+ aMain.Append(current->iHeaderRange);
+ aMain.Append(current->iCodeSection);
+ aMain.Append(current->iDataSection);
+
+ // section 2 things
+ //
+ // dll ref table
+
+ if (aSecond != 0)
+ {
+ // two section ROM - split image between both sections
+ aSecond->Append(current->iExportDirSection);
+ aSecond->Append(current->iDllRefTableRange);
+ }
+ else
+ {
+ // default placement in first section
+ aMain.Append(current->iExportDirSection);
+ aMain.Append(current->iDllRefTableRange);
+ }
+
+ TInt section1size = aMain.iRunAddr-current->iCodeSection.iRunAddr;
+
+ if (aMain.iRunAddr == aMain.iImageAddr)
+ {
+ Print(ELog, "Load Address: %08x\n", current->iHeaderRange.iImageAddr);
+ }
+ else
+ {
+ Print(ELog, "Rom Address: %08x\n", current->iHeaderRange.iImageAddr);
+ Print(ELog, "Area Address: %08x\n", current->iHeaderRange.iRunAddr);
+ }
+ Print(ELog, "Size: %08x\n", section1size);
+
+ if (aSecond != 0 && aMain.iImageAddr > iObey->iSectionStart)
+ return; // first section has overflowed
+
+ LoadFileToRom(current);
+ TRomImageHeader *header = current->iRomImageHeader;
+ if(iSymGen){
+ SymGenContext context ;
+ context.iFileName = current->iFileName ;
+ context.iTotalSize = section1size;
+ context.iCodeAddress = header->iCodeAddress;
+ context.iDataAddress = header->iDataAddress;
+ context.iDataBssLinearBase = header->iDataBssLinearBase;
+ context.iTextSize = header->iTextSize;
+ context.iDataSize = header->iDataSize;
+ context.iBssSize = header->iBssSize;
+ context.iTotalDataSize = header->iTotalDataSize;
+ context.iExecutable = ETrue ;
+ iSymGen->AddEntry(context);
+ }
+ Display(header);
+ Print(ELog, "Dll ref table size: %08x\n", current->iDllRefTableRange.iSize);
+ Print(ELog, "Compression: %08x\n", current->iCompression);
+ Print(ELog, "\n");
+
+ current->FixupRomEntries(section1size);
+ }
+
+static int CompareAddresses(const void * arg1, const void * arg2)
+ {
+ return (* (TUint32 *)arg1) < (* (TUint32 *)arg2) ? -1: 1;
+ }
+
+char *E32Rom::ReserveRomExceptionSearchTable(char *anAddr, TRomExceptionSearchTable*& exceptionSearchTable)
+ {
+ TRomExceptionSearchTable *pT = (TRomExceptionSearchTable *)anAddr;
+ exceptionSearchTable = pT;
+ if (iExtensionRomHeader)
+ {
+ iExtensionRomHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr);
+ }
+ else
+ {
+ iHeader->iRomExceptionSearchTable = ActualToRomAddress(anAddr);
+ }
+ TLinAddr * addr = &pT->iEntries[0];
+ int numEntries = 0;
+ int errors = 0;
+ // Count number of entries needed
+ for (int i = 0; i < iObey->iNumberOfPeFiles; i++)
+ {
+ TUint32 xd = iPeFiles[i]->iHdr->iExceptionDescriptor;
+ if ((xd & 1) && (xd != 0xffffffffu))
+ {
+ numEntries++;
+ }
+ else if (!iPeFiles[i]->iHdr->iExceptionDescriptor)
+ {
+#ifdef __REJECT_NON_EXCEPTION_AWARE_BINARIES__
+ Print(EError, "Executable not exception aware: %s\n", iPeFiles[i]->iName);
+ errors++;
+#else
+ Print(ELog, "Executable not exception aware: %s\n", iPeFiles[i]->iName);
+#endif
+ }
+ }
+ if (errors > 0) exit(666);
+ // NB we add one to numEntries to allow space for a fencepost value (see below for more)
+ int spaceNeeded = sizeof(pT->iNumEntries) + sizeof(pT->iEntries[0])*(numEntries+1);
+ int delta = (int)(addr+spaceNeeded) - (int)(iData+iSize);
+ // Check we've got enough room
+ if (delta > 0)
+ {
+ Print(EError, "Can't fit Rom Exception Search Table in Rom.\n");
+ Print(EError, "Rom overflowed by approximately 0x%x bytes.\n", delta);
+ exit(666);
+ }
+ pT->iNumEntries = numEntries;
+ return anAddr+spaceNeeded;
+ }
+
+void E32Rom::ConstructRomExceptionSearchTable(TRomExceptionSearchTable* exceptionSearchTable)
+ {
+ TRomExceptionSearchTable *pT = exceptionSearchTable;
+ TLinAddr * addr = &pT->iEntries[0];
+ // Initialize the table
+ int numEntries = pT->iNumEntries;
+ TLinAddr fencepost = 0xffffffff;
+ if (numEntries)
+ {
+ TLinAddr fp = 0;
+ for (int j = 0; j < iObey->iNumberOfPeFiles; j++)
+ {
+ TUint32 xd = iPeFiles[j]->iHdr->iExceptionDescriptor;
+ if ((xd & 1) && (xd != 0xffffffff))
+ {
+ // mask out bottom bit set by ELFTRAN.
+ xd &= ~1;
+ *addr++ = iPeFiles[j]->iHdr->iCodeBase;
+ TLinAddr aEDAddr = iPeFiles[j]->iHdr->iCodeBase + xd;
+ // Keep track of greatest code limit so we can use it as the fencepost value
+ TExceptionDescriptor * aEDp = (TExceptionDescriptor *)RomToActualAddress(aEDAddr);
+ TLinAddr codeLimit = aEDp->iROSegmentLimit;
+ if (codeLimit>fp) fp=codeLimit;
+ }
+ }
+ if (fp) fencepost=fp;
+ // now check they're in order (they should be).
+ int inOrder = 1;
+ for (int k=numEntries-1;inOrder && k; k--)
+ {
+ inOrder = pT->iEntries[k]>pT->iEntries[k-1]?1:0;
+ }
+
+ if (!inOrder)
+ {
+ Print(ELog, "Sorting Rom Exception Table.\n");
+ qsort(&pT->iEntries[0],numEntries,sizeof(pT->iEntries[0]), CompareAddresses);
+ }
+ }
+ /*
+ Add the fencepost value at the end of the table. This is used to optimize the comparison
+ function passed to bsearch when retrieving values from the search table. It also allows a certain
+ amount of error checking on lookup keys.
+ */
+ *addr++ = fencepost;
+ }
+
+void TRomBuilderEntry::SizeInSections(TInt& aSize1, TInt& aSize2)
+//
+// Exact size of the upper & lower section information
+// lower = text + data
+// upper = export directory + dllref table
+//
+ {
+ aSize1 = iHeaderRange.iSize;
+ aSize1 += iCodeSection.iSize; // text (including rdata)
+ aSize1 += iDataSection.iSize; // static data
+
+ aSize2 = iExportDirSection.iSize; // export directory
+ aSize2 += iDllRefTableRange.iSize; // DLL ref table
+ }
+
+
+void E32Rom::NextRom(TAddressRange* aFirst, TAddressRange* aSecond)
+//
+// Move on to the next Rom bank, taking the IATs with us
+//
+ {
+
+ Print(ELog,"\n####################################################################\n");
+ TInt gap=iObey->iSectionStart-aFirst->iImageAddr;
+ if (gap<0)
+ {
+ Print(EError, "First section overflowed by %08x bytes\n", -gap);
+ exit(669);
+ }
+ iOverhead+=gap+sizeof(TRomSectionHeader);
+ Print(ELog, "[Next rom section]\n");
+ Print(ELog, "Skipping %08x bytes\n", gap);
+ Print(ELog, "LinAddr: %08x\n", iObey->iSectionStart);
+ Print(ELog, "First section tables: %08x\n", iObey->iSectionStart+sizeof(TRomSectionHeader));
+ TInt size=aSecond->iImageAddr-iObey->iSectionStart;
+ Print(ELog, "Tables size: %08x\n", size-sizeof(TRomSectionHeader));
+ Print(ELog, "Rom Directory %08x\n", iHeader->iRomRootDirectoryList);
+ Print(ELog, "Rom Directory size %08x\n", iDirectorySize);
+
+ if (aSecond->iImageAddr != iHeader->iRomRootDirectoryList)
+ {
+ Print(EError, "Second section has overwritten the Rom directory\n");
+ exit(669);
+ }
+ aSecond->Extend(iDirectorySize);
+
+ Print(ELog, "\n");
+ }
+
+TInt E32Rom::ResolveDllRefTables()
+//
+//
+//
+ {
+
+ Print(ELog, "\nResolving Dll reference tables.\n");
+ TInt i;
+ TInt err = KErrNone;
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables %d\n",i));
+ TInt r=iPeFiles[i]->ResolveDllRefTable(*this);
+ if (r!=KErrNone)
+ err=r;
+ }
+ TRACE(TIMPORT,Print(ELog,"ResolveDllRefTables complete\n"));
+ return err;
+ }
+
+
+TInt E32Rom::BuildDependenceGraph()
+ {
+ Print(ELog, "\nBuilding dependence graph.\n");
+ TInt i;
+ TInt err = KErrNone;
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRACE(TIMPORT,Print(ELog,"BuildDep %d\n",i));
+ TRomBuilderEntry* e=iPeFiles[i];
+ TInt r=e->BuildDependenceGraph(*this);
+ if (r!=KErrNone)
+ err=r;
+ if (!e->IsDll())
+ {
+ if (e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0)
+ e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataPresent); // EXE with static data
+ }
+ else if ((e->iHdr->iDataSize!=0 || e->iHdr->iBssSize!=0) && !e->Variant() && !e->Extension())
+ {
+ // requires normal case DLL data initialisation
+ e->iRomImageFlags|=(KRomImageFlagData|KRomImageFlagDataInit|KRomImageFlagDataPresent);
+ }
+ }
+ TRACE(TIMPORT,Print(ELog,"BuildDep complete\n"));
+
+ if(!gPagedRom)
+ return err;
+
+ Print(ELog,"\n");
+
+ return err;
+ }
+
+#define MARK_BEEN_HERE 1
+#define MARK_KEEP 2
+#define MARK_EXE 4
+#define MARK_CHECKED 8
+void E32Rom::UnmarkGraph(TInt aMark)
+ {
+ TRomNode* x = 0;
+ for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable)
+ x->iRomFile->iMark &= ~aMark;
+ }
+
+void E32Rom::FindMarked(TInt aMarkMask, TInt aMark, TRomFile**& aList)
+ {
+ UnmarkGraph(MARK_CHECKED);
+ TRomNode* x = 0;
+ aMarkMask |= MARK_CHECKED;
+ aMark &= ~MARK_CHECKED;
+ for (x=iObey->iRootDirectory->iNextExecutable; x; x=x->iNextExecutable)
+ {
+ TRomFile* e = x->iRomFile;
+ if ((e->iMark&aMarkMask)==aMark)
+ {
+ *aList++=e;
+ e->iMark |= MARK_CHECKED;
+ }
+ }
+ }
+
+TInt TRomFile::MarkDeps()
+ {
+ TInt n=0;
+ TInt i;
+ for (i=0; i<iNumDeps; ++i)
+ {
+ TRomFile* e=iDeps[i];
+ if (!(e->iMark & MARK_BEEN_HERE))
+ {
+ e->iMark|=MARK_BEEN_HERE;
+ ++n;
+ n+=e->MarkDeps();
+ TUint32 flg = RomImageFlags();
+ TUint32 eflg = e->RomImageFlags();
+ if (eflg & KRomImageFlagDataPresent)
+ iRbEntry->iRomImageFlags |= KRomImageFlagDataPresent;
+ TBool e_is_dll = eflg & KImageDll;
+ if ((flg & KImageDll) && e_is_dll && (eflg & KRomImageFlagDataInit))
+ iRbEntry->iRomImageFlags |= KRomImageFlagDataInit;
+ if (!e_is_dll)
+ e->iMark|=MARK_EXE;
+ if (eflg&KRomImageFlagData)
+ e->iMark|=MARK_KEEP;
+ }
+ }
+ return n;
+ }
+
+TInt TRomFile::FindRouteTo(TRomFile* aDest, TRomFile** aStack, TInt aIndex)
+ {
+ TInt i;
+ for (i=0; i<iNumDeps; ++i)
+ {
+ TRomFile* e=iDeps[i];
+ if (e == aDest)
+ return aIndex;
+ if (!(e->iMark & MARK_BEEN_HERE))
+ {
+ e->iMark|=MARK_BEEN_HERE;
+ aStack[aIndex] = e;
+ TInt r = e->FindRouteTo(aDest, aStack, aIndex+1);
+ if (r >= 0)
+ return r;
+ }
+ }
+ return KErrNotFound;
+ }
+
+void E32Rom::ListRouteTo(TRomFile* aStart, TRomFile* aDest, TInt aNDeps)
+ {
+ TRomNode* rootdir = iObey->iRootDirectory;
+ TRomFile** stack = new TRomFile*[aNDeps];
+ UnmarkGraph();
+ TInt depth = aStart->FindRouteTo(aDest, stack, 0);
+ assert(depth >= 0);
+ Print(EAlways, "\t--->%s\n", (const char*)TModuleName(*aDest, rootdir));
+ while(--depth >= 0)
+ Print(EAlways, "\tvia %s\n", (const char*)TModuleName(*stack[depth], rootdir));
+ delete[] stack;
+ }
+
+TInt E32Rom::ProcessDependencies()
+ {
+ TInt i;
+ TInt errors = 0;
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRomBuilderEntry* e=iPeFiles[i];
+ TRomNode* rn = e->iRomNode;
+ TRomFile* rf = rn->iRomFile;
+ UnmarkGraph();
+ TInt n=rf->MarkDeps();
+ rf->iNumPDeps=n;
+ if (n)
+ {
+ rf->iPDeps=new TRomFile* [n];
+ if (!rf->iPDeps)
+ return KErrNoMemory;
+ TRomFile** l=rf->iPDeps;
+ FindMarked(MARK_EXE, MARK_EXE, l);
+ TInt nx=l-rf->iPDeps;
+ if (!e->IsDll() && (nx>1 || nx==1 && l[-1]!=rf))
+ {
+ Print(EError,"EXE %s links to the following other EXEs:\n", e->iFileName);
+ TInt j;
+ for (j=0; j<nx; ++j)
+ {
+ if (rf->iPDeps[j] != rf)
+ ListRouteTo(rf, rf->iPDeps[j], n);
+ }
+ ++errors;
+ continue;
+ }
+ else if (nx>1)
+ {
+ Print(EError,"DLL %s links to more than one EXE:\n",e->iFileName);
+ TInt j;
+ for (j=0; j<nx; ++j)
+ ListRouteTo(rf, rf->iPDeps[j], n);
+ ++errors;
+ continue;
+ }
+ if (nx)
+ e->iRomImageFlags|=KRomImageFlagExeInTree;
+ FindMarked(MARK_KEEP|MARK_EXE, MARK_KEEP, l);
+ rf->iNumPDeps=l-rf->iPDeps;
+ if (rf->iNumPDeps)
+ {
+ e->iDllRefTableRange.iSize=(rf->iNumPDeps-1)*sizeof(TRomImageHeader*)+sizeof(TDllRefTable);
+ if (e->IsDll() && rf->iTotalDataBss)
+ {
+ TRomFile* f=rf->iPDeps[0]; // first dependency, EXE if there is one
+ TUint fflg = f->RomImageFlags();
+ TBool f_is_dll = fflg & KImageDll;
+ if (!f_is_dll)
+ {
+ // DLL with data/bss depends on EXE
+ if ((fflg & KRomImageFlagFixedAddressExe) || iObey->iMemModel==E_MM_Direct)
+ {
+ // assign the DLL data address in the EXE bss section
+ rf->iDataBssOffsetInExe=f->iTotalDataBss;
+ f->iTotalDataBss+=rf->iTotalDataBss;
+ }
+ }
+ else if (iObey->iMemModel==E_MM_Direct)
+ {
+ Print(EError, "DLL with data/bss must have attach process specified\n");
+ return KErrGeneral;
+ }
+ }
+ }
+ else
+ {
+ delete[] rf->iPDeps;
+ rf->iPDeps=NULL;
+ }
+ }
+ if (!rf->iNumPDeps)
+ e->iDllRefTableRange.iSize=0;
+ }
+ if (iObey->iMemModel == E_MM_Moving)
+ {
+ // On moving model only, we must verify that no fixed process links to a
+ // DLL with data/bss which is attached to a fixed process.
+ // On multiple model there is no restriction.
+ // On direct model all DLLs with data/bss must specify an attach process
+ // and the error will show up as one EXE depending on another.
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRomBuilderEntry* e=iPeFiles[i];
+ TRomNode* rn = e->iRomNode;
+ TRomFile* rf = rn->iRomFile;
+ TUint rif = rf->RomImageFlags();
+ if (e->IsDll() || e->Primary() || !(rif & KRomImageFlagFixedAddressExe))
+ continue; // only need to check fixed address user mode EXEs
+ TInt n = rf->iNumPDeps;
+ TInt j;
+ for (j=0; j<n; ++j)
+ {
+ TRomFile* f = rf->iPDeps[j];
+ TUint fflg = f->RomImageFlags();
+ if ((fflg & KImageDll) && (f->iDataBssOffsetInExe < 0))
+ {
+ // fixed user EXE links to DLL with data/bss and no attach process
+ Print(EError,"Fixed EXE %s links to DLL with data/bss and no attach process:\n", e->iFileName);
+ ListRouteTo(rf, rf->iPDeps[j], n);
+ ++errors;
+ }
+ }
+ }
+ }
+ if (errors)
+ return KErrGeneral;
+
+ STRACE(TIMPORT,
+ {
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TRomBuilderEntry* e=iPeFiles[i];
+ TRomNode* rn = e->iRomNode;
+ TRomFile* rf = rn->iRomFile;
+ Print(ELog,"File %s: PN=%d\n",e->iFileName,rf->iNumPDeps);
+ TInt j;
+ for (j=0; j<rf->iNumPDeps; ++j)
+ {
+ TRomFile* f=rf->iPDeps[j];
+ Print(ELog,"\t%s\n", (const char*)TModuleName(*f, iObey->iRootDirectory));
+ }
+ }
+ })
+ return KErrNone;
+ }
+
+void E32Rom::SetSmpFlags()
+ {
+ if (gLogLevel & LOG_LEVEL_SMP_INFO)
+ {
+ Print(ELog,"\nComputing SMP properties. The following components are SMP-unsafe:\n");
+ }
+
+ bool is_all_safe = 1;
+
+ for (int i = 0; i < iObey->iNumberOfPeFiles; i++)
+ {
+ TRomBuilderEntry* e = iPeFiles[i];
+
+ if ( e->iRomNode->iRomFile->ComputeSmpSafe(e) )
+ {
+ e->iRomImageFlags |= KRomImageSMPSafe;
+ }
+ else
+ {
+ is_all_safe = 0;
+ e->iRomImageFlags &= ~KRomImageSMPSafe;
+ }
+ }
+
+ if ( (gLogLevel & LOG_LEVEL_SMP_INFO) && is_all_safe)
+ {
+ Print(ELog,"There are no unsafe components.");
+ }
+ }
+
+TInt E32Rom::ResolveImports()
+//
+// Fix the import address table for each of the files in rom
+//
+ {
+
+ Print(ELog, "Resolving Imports.\n");
+ TInt i;
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ TInt r=iPeFiles[i]->FixupImports(*this);
+ if (r!=KErrNone)
+ return r;
+ }
+ return KErrNone;
+ }
+
+char *E32Rom::RomToActualAddress(TUint aPtr)
+ {
+ return (char *)(aPtr-iObey->iRomLinearBase+(TUint)iHeader);
+ }
+
+TUint E32Rom::ActualToRomAddress(TAny *aPtr)
+ {
+ return ((TUint)aPtr)-(TUint32)iHeader+iObey->iRomLinearBase;
+ }
+
+void E32Rom::SetImageAddr(TAddressRange& aRange, TAny* aPtr, TUint32 aRunOffset)
+ {
+ aRange.iImagePtr=aPtr;
+ aRange.iImageAddr=ActualToRomAddress(aPtr);
+ aRange.iRunAddr=aRange.iImageAddr+aRunOffset;
+ }
+
+void E32Rom::SetImageAddr(TAddressRange& aRange, TUint aAddr, TUint32 aRunOffset)
+ {
+ aRange.iImagePtr=RomToActualAddress(aAddr);
+ aRange.iImageAddr=aAddr;
+ aRange.iRunAddr=aAddr+aRunOffset;
+ }
+
+TRomNode* E32Rom::FindImageFileByName(const TDllFindInfo& aInfo, TBool aPrintDiag, TBool& aFallBack)
+//
+// return the file with the name aName
+//
+ {
+ return iObey->iRootDirectory->FindImageFileByName(aInfo, aPrintDiag, aFallBack);
+ }
+
+TInt E32Rom::CheckForVersionConflicts(const TRomBuilderEntry* a)
+ {
+ return iObey->iRootDirectory->CheckForVersionConflicts(a);
+ }
+
+TRomNode* E32Rom::CopyDirectory(TRomNode*& aLastExecutable)
+ {
+ return iObey->iRootDirectory->CopyDirectory(aLastExecutable, 0);
+ }
+
+TInt E32Rom::CollapseImportThunks()
+//
+// Collapse 3-word import thunks into a single branch
+//
+ {
+
+ Print(ELog, "\nCollapsing Import Thunks.\n");
+ TInt i;
+ for (i=0; i<iObey->iNumberOfPeFiles; i++)
+ {
+ if (iPeFiles[i]->iHdr->iImportOffset)
+ {
+ TInt r=CollapseImportThunks(iPeFiles[i]);
+ if (r!=KErrNone)
+ return r;
+ }
+ }
+ return KErrNone;
+ }
+
+TInt E32Rom::WriteImages(TInt aHeaderType)
+ {
+ if (aHeaderType < 0)
+ aHeaderType = 1;
+ ofstream romFile((const char *)iObey->iRomFileName,ios_base::binary);
+ if (!romFile)
+ return Print(EError,"Cannot open ROM file %s for output\n",iObey->iRomFileName);
+ Write(romFile, aHeaderType);
+ romFile.close();
+
+ // Write out the odd/even 16-bits of the images
+
+ char sname[256];
+ if (iObey->iRomOddFileName)
+ {
+ strcpy(sname, (const char*)iObey->iRomOddFileName);
+ if (strcmp(sname, "*")==0)
+ {
+ // use romname with ".odd" appended.
+ sprintf(sname,"%s.odd",(const char *)iObey->iRomFileName);
+ }
+ ofstream oFile(sname,ios_base::binary);
+ if (!oFile)
+ return Print(EError,"Cannot open file %s for output\n",sname);
+ Print(EAlways, "Writing odd half words to file %s\n",sname);
+ WriteOdd(oFile);
+ oFile.close();
+ }
+ if (iObey->iRomEvenFileName)
+ {
+ strcpy(sname, (const char*)iObey->iRomEvenFileName);
+ if (strcmp(sname, "*")==0)
+ {
+ // use romname with ".even" appended.
+ sprintf(sname,"%s.even",(const char *)iObey->iRomFileName);
+ }
+ ofstream oFile(sname,ios_base::binary);
+ if (!oFile)
+ return Print(EError,"Cannot open file %s for output\n",sname);
+ Print(EAlways, "Writing even half words to file %s\n",sname);
+ WriteEven(oFile);
+ oFile.close();
+ }
+
+ // Write out the ROM in the SREC or S19 format
+
+ if (iObey->iSRecordFileName)
+ {
+ strcpy(sname, (const char*)iObey->iSRecordFileName);
+ if (strcmp(sname, "*")==0)
+ {
+ // use romname with ".srec" appended.
+ sprintf(sname,"%s.srec",(const char *)iObey->iRomFileName);
+ }
+ ofstream sFile(sname,ios_base::binary);
+ if (!romFile)
+ return Print(EError,"Cannot open file %s for output\n",sname);
+ Print(EAlways, "Writing S record format to file %s\n",sname);
+ WriteSRecord(sFile);
+ sFile.close();
+ }
+ return KErrNone;
+ }
+
+void E32Rom::WriteOdd(ofstream &os)
+ {
+ char *ptr=(char *)iHeader+2;
+ TInt i;
+ for (i=2; i<iObey->iRomSize; i+=4, ptr+=4)
+ os.write(ptr, 2);
+ }
+
+void E32Rom::WriteEven(ofstream &os)
+ {
+ char *ptr=(char *)iHeader;
+ TInt i;
+ for (i=0; i<iObey->iRomSize; i+=4, ptr+=4)
+ os.write(ptr, 2);
+ }
+
+void E32Rom::SetCompressionInfo(TUint aCompressionType, TUint aCompressedSize, TUint aUncompressedSize)
+ {
+
+ if (iExtensionRomHeader)
+ {
+ iExtensionRomHeader->iCompressionType=aCompressionType;
+ iExtensionRomHeader->iCompressedSize=aCompressedSize;
+ iExtensionRomHeader->iUncompressedSize=aUncompressedSize;
+ }
+ else
+ {
+ iHeader->iCompressionType=aCompressionType;
+ iHeader->iCompressedSize=aCompressedSize;
+ iHeader->iUncompressedSize=aUncompressedSize;
+ }
+ }
+
+void E32Rom::Write(ofstream &os, TInt aHeaderType)
+//
+// Output a rom image
+//
+ {
+
+ const char *compressed=gEnableCompress ? " compressed" : " uncompressed";
+
+ switch (aHeaderType)
+ {
+ case 0:
+ Print(EAlways, "\nWriting%s Rom image without",compressed);
+ break;
+ case 1:
+ default:
+ Print(EAlways, "\nWriting%sRom image with repro",compressed);
+ os.write(iData, sizeof(TRomLoaderHeader));
+ break;
+ case 2:
+ Print(EAlways, "\nWriting%s Rom image with PE-COFF",compressed);
+ {
+ unsigned char coffhead[0x58] = {0}; // zero all the elements
+
+ // fill in the constant bits
+ // this is supposed to be simple, remember
+ coffhead[1] = 0x0a;
+ coffhead[2] = 0x01;
+ coffhead[0x10] = 0x1c;
+ coffhead[0x12] = 0x0f;
+ coffhead[0x13] = 0xa1;
+ coffhead[0x14] = 0x0b;
+ coffhead[0x15] = 0x01;
+ coffhead[0x26] = 0x40;
+ coffhead[0x2a] = 0x40;
+ coffhead[0x30] = 0x2e;
+ coffhead[0x31] = 0x74;
+ coffhead[0x32] = 0x65;
+ coffhead[0x33] = 0x78;
+ coffhead[0x34] = 0x74;
+ coffhead[0x3a] = 0x40;
+ coffhead[0x3e] = 0x40;
+ coffhead[0x44] = 0x58;
+ coffhead[0x54] = 0x20;
+
+ // now fill in the text segment size
+ *(TUint32 *) (&coffhead[0x18]) = ALIGN4K(iSizeUsed);
+ *(TUint32 *) (&coffhead[0x40]) = ALIGN4K(iSizeUsed);
+
+ os.write(reinterpret_cast<char *>(coffhead), sizeof(coffhead));
+ }
+ break;
+ }
+ Print(EAlways, " header to file %s\n", iObey->iRomFileName);
+
+ iHeader->iUnpagedCompressedSize = 0;
+ iHeader->iUnpagedUncompressedSize = iHeader->iPageableRomStart;
+ iHeader->iCompressedUnpagedStart = gBootstrapSize + gPageIndexTableSize; // AttilaV calculate uncompressed un-paged size
+
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ {
+ Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize);
+ Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize);
+
+ Print(ELog, "iExtensionRomHeader :%d\n", iExtensionRomHeader);
+ Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));
+ Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ));
+ Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
+
+ Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart );
+ Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize );
+ Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex );
+
+ Print(ELog, "iSizeUsed :0x%08x (%d)\n", iSizeUsed, iSizeUsed );
+ Print(ELog, "Linear base address :0x%08x\n",iHeader->iRomBase);
+ Print(ELog, "Size: 0x%08x\n",iHeader->iRomSize);
+ }
+
+ if ( gPagedRom && gCompressUnpaged)
+ {
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "Write out compressed un-paged and paged sections\n\n");
+ ImpTRomHeader* header = (ImpTRomHeader *)iHeader;
+
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ {
+ Print(ELog, "Header:\n");
+ header->Display();
+ }
+
+ streampos headerpos=os.tellp();
+
+ // Write out uncompressed un-paged part (bootstrap + Page Index Table)
+ os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart);
+
+ // write out the compressed unpaged part
+ int srcsize=iHeader->iPageableRomStart - iHeader->iCompressedUnpagedStart;
+
+ int rawimagelen=DeflateCompressCheck(((char *)iHeader)+iHeader->iCompressedUnpagedStart,srcsize,os);
+ iHeader->iUnpagedCompressedSize = rawimagelen;
+ iHeader->iUnpagedUncompressedSize = srcsize ;
+
+ // align to 4kbyte boundary if neccessary
+ TUint32 distanceFrom4kBoundary = ((~(iHeader->iCompressedUnpagedStart + rawimagelen /*+ sizeof(TRomLoaderHeader)*/ )) & 0xfff) + 1;
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "distanceFrom4kBoundary :0x%08x (%d)\n", distanceFrom4kBoundary, distanceFrom4kBoundary);
+ char filer[0x1000];
+ memset( filer, 0, 0x1000);
+ os.write((char *)filer, distanceFrom4kBoundary);
+
+
+ // write out the paged part
+ os.write((char *)iHeader + iHeader->iPageableRomStart, ALIGN4K(iSizeUsed - iHeader->iPageableRomStart));
+
+ // update size and compression information of paged-part
+ SetCompressionInfo(KUidCompressionDeflate, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize));
+
+ // Calculate starting index of the Pageable Rom Start
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ {
+ Print(ELog, "iPageableRomStart : %d (0x%08x)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart);
+ Print(ELog, "iCompressedUnpagedStart : %d (0x%08x)\n", iHeader->iCompressedUnpagedStart, iHeader->iCompressedUnpagedStart);
+ Print(ELog, "rawimagelen : %d (0x%08x)\n", rawimagelen, rawimagelen);
+ }
+
+ TInt displacement = iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary;
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "new iPageableRomStart : %d (0x%08x)\n", (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary), (iHeader->iCompressedUnpagedStart + rawimagelen + distanceFrom4kBoundary));
+ displacement = iHeader->iPageableRomStart-displacement;
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "displacement : %d (0x%08x)\n", displacement, displacement);
+
+ SRomPageInfo* pi = (SRomPageInfo*)((TInt)iHeader+iHeader->iRomPageIndex);
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "First Pageable page info[0x%08x]:(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi, pi->iDataStart, pi->iDataSize, pi->iDataSize);
+
+ TInt startPageableIndex = (iHeader->iPageableRomStart) / (iObey->iPageSize);
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ {
+ Print(ELog, "iObey->iPageSize : %d (0x%08x)\n", iObey->iPageSize, iObey->iPageSize);
+ Print(ELog, "startPageableIndex : %d (0x%08x)\n", startPageableIndex, startPageableIndex);
+ }
+ pi += startPageableIndex;
+
+
+ while ( 0 != pi->iDataStart)
+ {
+ 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);
+
+ pi->iDataStart -= displacement;
+
+ 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);
+
+ ++pi;
+ }
+
+
+
+ // Rewrite the header with updated info
+ #ifdef __TOOLS2__
+ os.seekp(headerpos);
+ #else
+ os.seekp(headerpos,ios_base::beg);
+ #endif
+
+ // Rewrite uncompressed un-paged part (bootstrap + Page Index Table)
+ os.write((char *)(iHeader), iHeader->iCompressedUnpagedStart);
+
+
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ {
+ Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize, iHeader->iUnpagedCompressedSize);
+ Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize, iHeader->iUnpagedUncompressedSize);
+
+ Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));
+ Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ));
+ Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
+
+ Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart );
+ Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize );
+ Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex );
+ Print(ELog, "\t\tinfo(iDataStart:0x%08x, iDataSize:0x%08x (%d))\n\n", pi->iDataStart, pi->iDataSize, pi->iDataSize);
+
+ Print(ELog, "Linear base address: %08x\n",iHeader->iRomBase);
+ Print(ELog, "Size: %08x\n",iHeader->iRomSize);
+ }
+
+ return;
+ }
+
+ if (!gEnableCompress || gPagedRom || !gCompressUnpaged)
+ {
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "Writeout uncompressed un-paged and paged sections2\n");
+ SetCompressionInfo(KFormatNotCompressed, ALIGN4K(iSizeUsed), ALIGN4K(iUncompressedSize));
+ iHeader->iUnpagedCompressedSize = ALIGN4K(iSizeUsed);
+ iHeader->iUnpagedUncompressedSize = ALIGN4K(iUncompressedSize);
+
+ os.write((char *)iHeader, ALIGN4K(iSizeUsed));
+
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ {
+ Print(ELog, "iUnpagedCompressedSize :0x%08x (%d)\n", iHeader->iUnpagedCompressedSize);
+ Print(ELog, "iUnpagedUncompressedSize:0x%08x (%d)\n\n", iHeader->iUnpagedUncompressedSize);
+
+ Print(ELog, "iCompressionType :0x%08x\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressionType : iHeader->iCompressionType ));
+ Print(ELog, "iCompressedSize :0x%08x (%d)\n", (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iCompressedSize : iHeader->iCompressedSize ));
+ Print(ELog, "iUncompressedSize :0x%08x (%d)\n\n", (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ), (iExtensionRomHeader ? iExtensionRomHeader->iUncompressedSize: iHeader->iUncompressedSize ));
+
+ Print(ELog, "iPageableRomStart :0x%08x (%d)\n", iHeader->iPageableRomStart, iHeader->iPageableRomStart );
+ Print(ELog, "iPageableRomSize :0x%08x (%d)\n", iHeader->iPageableRomSize, iHeader->iPageableRomSize );
+ Print(ELog, "iRomPageIndex :0x%08x (%d)\n", iHeader->iRomPageIndex, iHeader->iRomPageIndex );
+ }
+
+ return;
+ }
+
+ // compressed image without paging section
+ streampos headerpos=os.tellp();
+ int headersize=iExtensionRomHeader ? sizeof(TExtensionRomHeader) : sizeof(TRomHeader);
+
+ os.write(reinterpret_cast<char*>(iHeader), headersize); // write a dummy header
+ // compress the rest of the image
+ int srcsize=iSizeUsed - headersize;
+ int rawimagelen=DeflateCompressCheck(((char *)iHeader)+headersize,srcsize,os);
+ // write the compression info into the header
+ SetCompressionInfo(KUidCompressionDeflate, rawimagelen, iUncompressedSize); // doesn't need to be 4K aligned
+ iHeader->iCompressedUnpagedStart = headersize;
+ iHeader->iUnpagedCompressedSize = rawimagelen;
+ iHeader->iUnpagedUncompressedSize = srcsize;
+
+ #ifdef __TOOLS2__
+ os.seekp(headerpos);
+ #else
+ os.seekp(headerpos,ios_base::beg);
+ #endif
+ os.write(reinterpret_cast<char*>(iHeader), headersize); // write header again with (compressed) size info
+
+ if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+ Print(ELog, "\tiSizeUsed:%d, iUncompressedSize:%d, headersize:%d, srcsize:%d, rawimagelen:%d \n",iSizeUsed, iUncompressedSize, headersize, srcsize, rawimagelen);
+ }
+
+TInt E32Rom::Compare(const char *aImage, TInt aHeaderType)
+ {
+ if (aHeaderType < 0)
+ aHeaderType = 1;
+ ifstream file(aImage, ios_base::binary);
+ if (!file)
+ return Print(EError, "Cannot open Rom image '%s' for verification\n", aImage);
+ Print(ELog, "\nVerifying ROM against image in %s\n", aImage);
+ switch (aHeaderType)
+ {
+ case 0:
+ break;
+ case 1:
+ default:
+ Print(ELog, "Skipping repro header\n");
+ file.seekg(sizeof(TRomLoaderHeader));
+ break;
+ case 2:
+ Print(ELog, "Skipping coff header\n");
+ file.seekg(0x58);
+ break;
+ }
+ TInt length=ALIGN4K(iSizeUsed);
+ if (iObey->iSectionStart != 0)
+ {
+ length = iObey->iSectionStart-iObey->iRomLinearBase;
+ Print(ELog, "Verifying first section (%08x bytes)... ", length);
+ }
+
+ TRomHeader compareHeader;
+ file.read((char *)&compareHeader, sizeof(TRomHeader));
+ // Arrange different settings for TRomHeader and
+ // TRomSectionHeader in the obey file
+ // For now just copy across the things that'll change
+ compareHeader.iVersion=iHeader->iVersion;
+ compareHeader.iTime=iHeader->iTime;
+ compareHeader.iTimeHi=(TUint32)(iHeader->iTime >> 32);
+ compareHeader.iCheckSum=iHeader->iCheckSum;
+ compareHeader.iLanguage=iHeader->iLanguage;
+
+ if (memcmp(&compareHeader, iHeader, sizeof(TRomHeader))!=0)
+ return Print(EError, "Verify failed.\nRom headers are different\n");
+
+ // Now compare the rest of the image (or first section)
+
+ TUint *ptr=(TUint *)(iHeader+1);
+ TInt i;
+ for (i=sizeof(TRomHeader); i<length; i+=4)
+ {
+ TUint a;
+ file.read((char *)&a, sizeof(TUint));
+ if (file.eof())
+ return Print(EError, "Verify failed.\nDifferent Rom sizes\n");
+ if (a!=*ptr)
+ return Print(EError, "Verify failed.\nContents differ at Rom address %08x\n", i+iObey->iRomLinearBase);
+ ptr++;
+ }
+ file.close();
+ Print(EAlways, "Verify OK\n");
+ return KErrNone;
+ }
+
+
+char* E32Rom::AllocateRelocationTable(char* aAddr, TReloc*& aRelocTable)
+ {
+ if(iObey->SetArea().Count() > 1)
+ {
+ aRelocTable = reinterpret_cast<TReloc*>(aAddr);
+
+ // Allocate one entry per non default area + 1 sentinel
+ // (Count() returns number of non default areas + 1 (the
+ // default area))
+ TInt size = iObey->SetArea().Count() * sizeof(TReloc);
+ aAddr += Align(size);
+ }
+ else
+ {
+ aRelocTable = 0;
+ }
+
+ return aAddr;
+ }
+
+
+void E32Rom::FillInRelocationTable(TReloc* aRelocTable)
+ {
+ TReloc* p = aRelocTable;
+ TInt wastedBytes = 0;
+
+ for (NonDefaultAreasIterator areaIt(iObey->SetArea());
+ ! areaIt.IsDone();
+ areaIt.GoToNext())
+ {
+ Area& currentArea = areaIt.Current();
+
+ if (currentArea.UsedSize() > 0)
+ {
+ p->iLength = currentArea.UsedSize();
+ p->iSrc = currentArea.SrcBaseAddr();
+ p->iDest = currentArea.DestBaseAddr();
+ ++p;
+ }
+ else
+ {
+ wastedBytes += sizeof(TReloc);
+ }
+ }
+
+ if (aRelocTable != 0)
+ {
+ // Last entry acts as a sentinel
+ memset(p, 0, sizeof(*p));
+ }
+
+ if (wastedBytes > 0)
+ {
+ Print(EWarning, "Some areas are declared but not used\n");
+ Print(EWarning, "%d bytes wasted in relocation table\n", wastedBytes);
+ }
+ }
+
+
+/**
+ Link together the kernel extensions.
+
+ Must be called only after space has been allocated in the ROM image
+ for the kernel extension.
+ */
+
+void E32Rom::LinkKernelExtensions(TRomBuilderEntry* aExtArray[], TInt aExtCount)
+ {
+ /**
+ * The kernel extensions should never be linked together as part of extension ROMs.
+ */
+ if (!iExtensionRomHeader)
+ {
+ TLinAddr* pLastNextExtAddr = &(iHeader->iExtensionFile);
+
+ for (TInt i=0; i<aExtCount; ++i)
+ {
+ TRomBuilderEntry* curExt = aExtArray[i];
+ *pLastNextExtAddr = ActualToRomAddress(curExt->RomEntry());
+ pLastNextExtAddr = &(curExt->iRomImageHeader->iNextExtension);
+ }
+
+ *pLastNextExtAddr = 0;
+ }
+ }
+
+void E32Rom::ProcessDllData()
+ {
+ DllDataEntry *entry = iObey->GetFirstDllDataEntry();
+ TRomBuilderEntry *romEntry;
+ TLinAddr* aExportTbl;
+ void *aLocation;
+ TUint aDataAddr;
+ while(entry){
+ // A Dll data may be patched either via the ordinal number (as in ABIv2), or via
+ // the address of the data field (as in ABIv1).
+ romEntry = entry->iRomNode->iRomFile->iRbEntry;
+ if((TInt)entry->iOrdinal != -1) {
+
+ // const data symbol may belong in the Code section. Get the address of the data field via the
+ // export table. If the address lies within the Code or data section limits,
+ // get the corresponding location and update it.While considering the Data section limits don't
+ // include the Bss section, as it doesn't exist as yet in the image.
+ if(entry->iOrdinal < 1 || entry->iOrdinal > (TUint32)romEntry->iOrigHdr->iExportDirCount)
+ {
+ Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", entry->iOrdinal, romEntry->iName);
+ entry = entry->NextDllDataEntry();
+ continue;
+ }
+ aExportTbl = (TLinAddr*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iExportDirOffset);
+ aDataAddr = (TInt32)(aExportTbl[entry->iOrdinal - 1] + entry->iOffset);
+
+ if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) &&
+ (aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \
+ romEntry->iOrigHdr->iCodeSize)) )
+ {
+ char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset);
+ aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase));
+ memcpy(aLocation, &(entry->iNewValue), entry->iSize);
+ }
+ else if( (aDataAddr >= romEntry->iOrigHdr->iDataBase) &&
+ (aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \
+ romEntry->iOrigHdr->iDataSize )) )
+ {
+ char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset);
+ aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase));
+ memcpy(aLocation, &(entry->iNewValue), entry->iSize);
+ }
+ else
+ {
+ 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);
+ }
+
+ }
+ else if((TInt)entry->iDataAddress != -1) {
+ // const data symbol may belong in the Code section. If the address lies within the Code
+ // or data section limits, get the corresponding location and update it.While considering
+ // the Data section limits don't include the Bss section, as it doesn't exist as yet in the image.
+ aDataAddr = (TUint)(entry->iDataAddress + entry->iOffset);
+ if( (aDataAddr >= romEntry->iOrigHdr->iCodeBase) &&
+ (aDataAddr <= (TUint)(romEntry->iOrigHdr->iCodeBase + \
+ romEntry->iOrigHdr->iCodeSize )) )
+ {
+ char *aCodeSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iCodeOffset);
+ aLocation = (void*)(aCodeSeg + (aDataAddr - romEntry->iOrigHdr->iCodeBase));
+ memcpy(aLocation, &(entry->iNewValue), entry->iSize);
+ }
+ else if( (aDataAddr >= romEntry->iOrigHdr->iDataBase) &&
+ (aDataAddr <= (TUint)(romEntry->iOrigHdr->iDataBase + \
+ romEntry->iOrigHdr->iDataSize )) )
+ {
+ char *aDataSeg = (char*)((char*)romEntry->iOrigHdr + romEntry->iOrigHdr->iDataOffset);
+ aLocation = (void*)(aDataSeg + (aDataAddr - romEntry->iOrigHdr->iDataBase));
+ memcpy(aLocation, &(entry->iNewValue), entry->iSize);
+ }
+ else
+ {
+ 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);
+ }
+ }
+ else {
+ }
+ entry = entry->NextDllDataEntry();
+ }
+ }
+
+TInt E32Rom::CheckUnpagedMemSize()
+ {
+
+ if (H.iVerbose && gPagedRom)
+ {
+ Print(EDiagnostic, "iMaxUnpagedMemSize 0x%08x (%d)\n", iObey->iMaxUnpagedMemSize, iObey->iMaxUnpagedMemSize);
+ }
+
+ // Only check if the iMaxUnpagedMemSize is set
+ if (iObey->iMaxUnpagedMemSize <= 0) return KErrNone;
+
+ // Only for paged rom
+ if (!gPagedRom)
+ {
+ Print(EWarning, "The unpaged size overflow check is skipped.\n");
+ return KErrNone;
+ }
+
+ if (iHeader->iPageableRomStart > 0)
+ {
+ if (iHeader->iPageableRomStart > iObey->iMaxUnpagedMemSize)
+ {
+ Print(EError, "Unpaged memory size overflow: require 0x%08x (%d) bytes while the maximum size is 0x%08x (%d) bytes\n",
+ iHeader->iPageableRomStart,
+ iHeader->iPageableRomStart,
+ iObey->iMaxUnpagedMemSize,
+ iObey->iMaxUnpagedMemSize);
+
+ return KErrNoMemory;
+ }
+ }
+ else
+ {
+ Print(EWarning, "The size of unpaged memory is not available. The unpaged memory overflow checking is skipped.\n");
+ }
+
+ return KErrNone;
+}
+TRomNode* E32Rom::RootDirectory() const {
+ return iObey->iRootDirectory;
+}
+const char* E32Rom::RomFileName() const {
+ return iObey->iRomFileName;
+}
+TUint32 E32Rom::RomBase() const {
+ return iHeader->iRomBase;
+}
+TUint32 E32Rom::RomSize() const {
+ return iHeader->iRomSize;
+}
+TVersion E32Rom::Version() const {
+ return iHeader->iVersion;
+}
+TInt64 E32Rom::Time() const {
+ return iHeader->iTime;
+}
+TUint32 E32Rom::CheckSum() const {
+ return iHeader->iCheckSum;
+}
+TUint32 E32Rom::DataRunAddress() const {
+ return iObey->iDataRunAddress;
+}
+TUint32 E32Rom::RomAlign() const {
+ return iObey->iRomAlign;
+}