--- a/imgtools/romtools/rofsbuild/r_rofs.cpp Wed Jun 16 16:51:40 2010 +0300
+++ b/imgtools/romtools/rofsbuild/r_rofs.cpp Wed Jun 23 16:56:47 2010 +0800
@@ -1,617 +1,587 @@
-/*
-* 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 <f32file.h>
-#include "h_utl.h"
-#include <string.h>
-#include <stdlib.h>
-#include "r_obey.h"
-#include "r_rofs.h"
-#include "r_coreimage.h"
-#include "memmap.h"
-extern TInt gLogLevel;
-extern TBool gLowMem;
-extern TBool gFastCompress;
-extern TInt gThreadNum;
-////////////////////////////////////////////////////////////////////////
-
-
-
-inline TUint32 AlignData(TUint32 anAddr)
- {
- return ((anAddr+0x0f)&~0x0f);
- }
-
-
-////////////////////////////////////////////////////////////////////////
-
-E32Rofs::E32Rofs(CObeyFile *aObey)
-//
-// Constructor
-//
- : iObey( aObey ), iOverhead(0)
- {
-
- iSize=aObey->iRomSize;
- 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;
- HMem::Set(iData, 0xff, iSize);
- }
-
- }
-
-E32Rofs::~E32Rofs()
-//
-// Destructor
-//
- {
-
- if(gLowMem)
- {
- iImageMap->CloseMemoryMap(ETrue);
- delete iImageMap;
- }
- else
- delete iData;
- }
-
-
-TInt E32Rofs::CreateExtension(MRofsImage* aImage)
- {
-
- TUint8* addr=(TUint8*)iData;
-
- TRomNode* pRootDir = aImage->RootDirectory();
-
-
- const TInt extensionRofsheaderSize = KExtensionRofsHeaderSize;
-
- // aImage->iSize contains the max size of the core image
-
- // Layout the directory structure. Does not actually write it
- // to the image. Returns the number of bytes used for the directory
- // structure within the image.
- TInt directoryOffset = extensionRofsheaderSize;
- const TInt directorySize = LayoutDirectory( pRootDir, aImage->Size()+directoryOffset );
- if( directorySize <= 0 )
- {
- Print(EError, "Failed laying out directories - return code %d\n", directorySize);
- return KErrGeneral;
- }
-
- // get offset to start of file data, rounded up to next word boundary
- TInt offs = extensionRofsheaderSize + directorySize;
- const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
-
- // Now we traverse the list of entries placing each file
- // This updates the directory entries to point to the correct offset
- // to the start of the file
- const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset + aImage->Size(), aImage->Size());
- if( fileDataSize <= 0 )
- {
- Print(EError, "Failed placing files - return code %d\n", fileDataSize);
- return KErrGeneral;
- }
-
- // and then put the directory into the image
- TInt err = PlaceDirectory( pRootDir, addr - aImage->Size() ); // offset pointer by size of core image
- if( err != KErrNone )
- {
- Print(EError, "Failed placing directory - return code %d\n", err);
- return err;
- }
-
- directoryOffset+=aImage->Size(); // offset offset by size of core image
- // Now write the header
- TExtensionRofsHeader * pHeader = (TExtensionRofsHeader*)iData;
- pHeader->iIdentifier[0] = 'R';
- pHeader->iIdentifier[1] = 'O';
- pHeader->iIdentifier[2] = 'F';
- pHeader->iIdentifier[3] = 'x';
- pHeader->iHeaderSize = KExtensionRofsHeaderSize;
- pHeader->iDirTreeOffset = directoryOffset;
- pHeader->iDirTreeSize = iTotalDirectoryBlockSize;
- pHeader->iDirFileEntriesOffset = directoryOffset + iTotalDirectoryBlockSize;
- pHeader->iDirFileEntriesSize = iTotalFileBlockSize;
- pHeader->iRofsFormatVersion = KRofsFormatVersion;
- pHeader->iTime = iObey->iTime;
- iSizeUsed = fileDataSize + fileDataStartOffset;
- pHeader->iImageSize = iSizeUsed;
- if (iObey->AutoSize())
- MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
- pHeader->iMaxImageSize = iSize;
- pHeader->iCheckSum = 0; // not used yet
-
- return KErrNone;
- }
-
-void E32Rofs::MakeAutomaticSize(TUint32 aPageSize)
- {
- TUint32 size = iSizeUsed;
- if (iSizeUsed % aPageSize > 0)
- {
- //used size needs to be rounded up to nearest page size
- size = (iSizeUsed/aPageSize + 1)*aPageSize;
- }
- iSize = size;
- }
-
-TInt E32Rofs::Create()
-//
-// This is the main entry point to the ROFS image creation
-//
- {
- TUint8* addr=(TUint8*)iData;
-
- TRomNode* pRootDir = iObey->iRootDirectory;
- const TInt headerSize = KRofsHeaderSize;
- // Layout the directory structure. Does not actually write it
- // to the image. Returns the number of bytes used for the directory
- // structure within the image.
- const TInt directoryOffset = headerSize;
- const TInt directorySize = LayoutDirectory( pRootDir, directoryOffset );
- if( directorySize <= 0 )
- {
- Print(EError, "Failed laying out directories - return code %d\n", directorySize);
- return KErrGeneral;
- }
-
- // get offset to start of file data, rounded up to next word boundary
- TInt offs = headerSize + directorySize;
- const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
-
- // Now we traverse the list of entries placing each file
- // This updates the directory entries to point to the correct offset
- // to the start of the file
- const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset );
- if( fileDataSize < 0 )
- {
- Print(EError, "Failed placing files - return code %d\n", fileDataSize);
- return KErrGeneral;
- }
-
- // and then put the directory into the image
- TInt err = PlaceDirectory( pRootDir, addr );
- if( err != KErrNone )
- {
- Print(EError, "Failed placing directory - return code %d\n", err);
- return err;
- }
-
- // Now write the header
- TRofsHeader* pHeader = (TRofsHeader*)iData;
- pHeader->iIdentifier[0] = 'R';
- pHeader->iIdentifier[1] = 'O';
- pHeader->iIdentifier[2] = 'F';
- pHeader->iIdentifier[3] = 'S';
- pHeader->iHeaderSize = KExtensionRofsHeaderSize;
- pHeader->iDirTreeOffset = directoryOffset;
- pHeader->iDirTreeSize = iTotalDirectoryBlockSize;
- pHeader->iDirFileEntriesOffset = directoryOffset + iTotalDirectoryBlockSize;
- pHeader->iDirFileEntriesSize = iTotalFileBlockSize;
- pHeader->iRofsFormatVersion = KRofsFormatVersion;
- pHeader->iTime = iObey->iTime;
- iSizeUsed = fileDataSize + fileDataStartOffset;
- pHeader->iImageSize = iSizeUsed;
- pHeader->iImageVersion = iObey->iVersion;
- if (iObey->AutoSize())
- MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
-
- pHeader->iMaxImageSize = iSize;
- pHeader->iCheckSum = 0; // not used yet
-
- return KErrNone;
- }
-void E32Rofs::DisplaySizes(TPrintType aWhere)
-{
- Print(aWhere, "Summary of file sizes in rofs:\n");
- TRomBuilderEntry *file=iObey->FirstFile();
- while(file)
- {
- file->DisplaySize(aWhere);
- file=iObey->NextFile();
- }
- Print( aWhere, "Directory block size: %d\n"
- "File block size: %d\n"
- "Total directory size: %d\n"
- "Total image size: %d\n",
- iTotalDirectoryBlockSize,
- iTotalFileBlockSize,
- iTotalDirectoryBlockSize + iTotalFileBlockSize,
- iSizeUsed );
-
-}
-
-void E32Rofs::LogExecutableAttributes(E32ImageHeaderV *aHdr)
-{
- Print(ELog, "Uids: %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum);
- Print(ELog, "Data size: %08x\n", aHdr->iDataSize);
- 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, "Secure ID: %08x\n", aHdr->iS.iSecureId);
- Print(ELog, "Vendor ID: %08x\n", aHdr->iS.iVendorId);
- Print(ELog, "Priority: %d\n\n", aHdr->iProcessPriority);
-}
-class Worker : public boost::thread {
- public:
- static void thrd_func(E32Rofs* rofs){
- CBytePair bpe(gFastCompress);
-
- bool deferred = false;
- TPlacingSection* p = rofs->GetFileNode(deferred);
- while(p) {
- if(!deferred)
- p->len = p->node->PlaceFile(p->buf, (TUint32)-1, 0, &bpe);
- p = rofs->GetFileNode(deferred);
- }
- rofs->ArriveDeferPoint();
- p = rofs->GetDeferredJob();
- while(p) {
- p->len = p->node->PlaceFile(p->buf, (TUint32)-1, 0, &bpe);
- p = rofs->GetDeferredJob();
- }
- }
- Worker(E32Rofs* rofs) : boost::thread(thrd_func,rofs) {
- }
-};
-
-TPlacingSection* E32Rofs::GetFileNode(bool &aDeferred) {
- //get a node from the node list, the node list is protected by mutex iMuxTree.
- //The iMuxTree also helps to make sure the order in iVPS is consistent with the node list.
- //And this is the guarantee of same outputs regardless of how many threads being used.
- boost::mutex::scoped_lock lock(iMuxTree);
- aDeferred = false;
- TRomNode* node = iLastNode;
- while(node) {
- if( node->IsFile()) {
- if(!node->iHidden) {
- iLastNode = node->NextNode();
- break;
- }
- }
- node = node->NextNode();
- }
-
- if(node && node->IsFile() && !node->iHidden) {
- TPlacingSection* pps = new TPlacingSection(node);
- iVPS.push_back(pps);
- if(node->iAlias) {
- iQueueAliasNode.push(pps);
- aDeferred = true;
- }
- return pps;
- }
- return NULL;
-}
-TPlacingSection* E32Rofs::GetDeferredJob() {
- // waiting all the normal node have been placed.
- while(iWorkerArrived < gThreadNum)
- boost::this_thread::sleep(boost::posix_time::milliseconds(10));
-
- // now we can safely handle the alias nodes.
- boost::mutex::scoped_lock lock(iMuxTree);
- TPlacingSection* p = NULL;
- if(!iQueueAliasNode.empty()) {
- p = iQueueAliasNode.front();
- iQueueAliasNode.pop();
- }
- return p;
-}
-void E32Rofs::ArriveDeferPoint() {
- boost::mutex::scoped_lock lock(iMuxTree);
- ++iWorkerArrived;
-}
-TInt E32Rofs::PlaceFiles( TRomNode* /*aRootDir*/, TUint8* aDestBase, TUint aBaseOffset, TInt aCoreSize )
- //
- // Traverses all entries placing all files and updating directory entry pointers.
- // Returns number of bytes placed or -ve error code.
- //
- {
- iLastNode = TRomNode::FirstNode();
- iWorkerArrived = 0;
-
- boost::thread_group thrds;
- Worker** workers = new Worker*[gThreadNum];
- int i;
- for (i = 0; i < gThreadNum; ++i) {
- workers[i] = new Worker(this);
- thrds.add_thread(workers[i]);
- }
-
- thrds.join_all();
- delete [] workers;
-
- TUint offset = aBaseOffset;
- TUint8* dest = aDestBase;
- TBool aIgnoreHiddenAttrib = ETrue;
- TInt len = iVPS.size();
- TInt maxSize;
- for(i=0;i<len;i++) {
- maxSize = aCoreSize + iSize - offset;
- if(maxSize <= 0) {
- // Image size is too low to proceed.
- return maxSize;
- }
- if(iVPS[i]->node->iFileStartOffset != (TUint)KFileHidden) {
- memcpy(dest,iVPS[i]->buf,iVPS[i]->len);
- if(iVPS[i]->node->iEntry->iFileOffset == -1) {
- iVPS[i]->node->iEntry->iFileOffset = offset;
- iVPS[i]->node->iFileStartOffset = iVPS[i]->node->iEntry->iFileOffset;
- }
- else {
- TRomBuilderEntry* aEntry = (TRomBuilderEntry*)(iVPS[i]->node->iFileStartOffset);
- iVPS[i]->node->iFileStartOffset = aEntry->iFileOffset;
- }
- }
- iVPS[i]->len += (4-iVPS[i]->len) & 3;// round up to next word boundary
- dest += iVPS[i]->len;
- offset += iVPS[i]->len;
-
- if(gLogLevel > DEFAULT_LOG_LEVEL )
- {
- TRomNode* node = iVPS[i]->node;
- TInt aLen = node->FullNameLength(aIgnoreHiddenAttrib);
- char *aBuf = new char[aLen+1];
- if(gLogLevel & LOG_LEVEL_FILE_DETAILS)
- {
- node->GetFullName(aBuf, aIgnoreHiddenAttrib);
- if(node->iEntry->iFileName)
- Print(ELog,"%s\t%d\t%s\t%s\n", node->iEntry->iFileName, node->iEntry->RealFileSize(), (node->iHidden || node->iEntry->iHidden)? "hidden":"", aBuf);
- else
- Print(ELog,"%s\t%s\n", (node->iHidden || node->iEntry->iHidden) ? "hidden":"", aBuf);
- }
-
- if(gLogLevel & LOG_LEVEL_FILE_ATTRIBUTES)
- {
- if(!node->iHidden && !node->iEntry->iHidden)
- Print(ELog, "Device file name: %s\n", aBuf);
- if(node->iEntry->iExecutable)
- LogExecutableAttributes((E32ImageHeaderV*)(dest-len));
- }
- delete[] aBuf;
- }
- }
- return offset - aBaseOffset; // number of bytes used
- }
-
-
-
-
-
-
-TInt E32Rofs::LayoutDirectory( TRomNode* /*aRootDir*/, TUint aBaseOffset )
- //
- // Creates the directory layout but does not write it to the image.
- // All directories are given a location in the image.
- // Returns the total number of bytes used for the directory (rounded
- // up to the nearest word) or a -ve error code.
- //
- {
- TRomNode* node = TRomNode::FirstNode();
-
- TUint offset = aBaseOffset;
- while( node )
- {
- if( node->IsDirectory())
- {
- // it is a directory block so we have to give it a location
- node->SetImagePosition( offset );
-
- // work out how much space it requires for the directory block
- TInt dirLen;
- TInt fileLen;
- TInt err = node->CalculateDirectoryEntrySize( dirLen, fileLen );
- if( err != KErrNone )
- {
- return err;
- }
- Print( ELog, "Directory '%s' @offs=0x%x, size=%d\n", node->iName, offset, dirLen );
- dirLen += (4-dirLen) & 3; // round up to next word boundary
- offset += dirLen;
- }
-
- node = node->NextNode();
- }
-
- TInt totalDirectoryBlockSize = offset - aBaseOffset; // number of bytes used
- totalDirectoryBlockSize += (4 - totalDirectoryBlockSize) & 3; // round up
-
- // Now go round again placing the file blocks
- offset = aBaseOffset + totalDirectoryBlockSize;
- const TUint fileBlockStartOffset = offset;
- node = TRomNode::FirstNode();
- while( node )
- {
- if( node->IsDirectory() )
- {
- // work out how much space it requires for the file block
- TInt dummy;
- TInt fileLen;
- TInt err = node->CalculateDirectoryEntrySize( dummy, fileLen );
-
- if( err != KErrNone )
- {
- return fileLen;
- }
- if( fileLen )
- {
- node->SetFileBlockPosition( offset );
- Print( ELog, "File block for dir '%s' @offs=0x%x, size=%d\n", node->iName, offset, fileLen );
- }
-
- fileLen += (4-fileLen) & 3; // round up to next word boundary
- offset += fileLen;
- }
-
- node = node->NextNode();
- }
-
- TInt totalFileBlockSize = offset - fileBlockStartOffset; // number of bytes used
- totalFileBlockSize += (4 - totalFileBlockSize) & 3; // round up
-
- iTotalDirectoryBlockSize = totalDirectoryBlockSize;
- iTotalFileBlockSize = totalFileBlockSize;
-
- return totalDirectoryBlockSize + totalFileBlockSize;
- }
-
-
-TInt E32Rofs::PlaceDirectory( TRomNode* /*aRootDir*/, TUint8* aDestBase )
- //
- // Writes the directory into the image.
- // Returns KErrNone on success, or error code
- //
- {
- TRomNode* node = TRomNode::FirstNode();
-
- while( node )
- {
- if( node->IsDirectory() )
- {
- TInt err = node->Place( aDestBase );
- if( err != KErrNone )
- {
- return err;
- }
- }
- node = node->NextNode();
- }
- return KErrNone;
- }
-
-TInt E32Rofs::WriteImage( TInt aHeaderType )
- {
- 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();
-
- return KErrNone;
- }
-
-TRomNode* E32Rofs::CopyDirectory(TRomNode*& aLastExecutable)
- {
- return iObey->iRootDirectory->CopyDirectory(aLastExecutable);
- }
-
-
-void E32Rofs::Write(ofstream &os, TInt aHeaderType)
-
-// Output a rom image
-
- {
-
- switch (aHeaderType)
- {
- default:
- case 0:
- Print(EAlways, "\nWriting Rom image without");
- break;
- case 2:
- Print(EAlways, "\nWriting Rom image with PE-COFF");
- {
- 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);
- os.write( iData, iSizeUsed );
- }
-
-
-TRomNode* E32Rofs::RootDirectory()
- {
- return iObey->iRootDirectory;
- }
-void E32Rofs::SetRootDirectory(TRomNode* aDir)
- {
- iObey->iRootDirectory = aDir;
- }
-TText* E32Rofs::RomFileName()
- {
- return iObey->iRomFileName;
- }
-TInt E32Rofs::Size()
- {
- return iSize;
- }
-
-///////////////////
-
+/*
+* 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 <f32file.h>
+#include "h_utl.h"
+#include <string.h>
+#include <stdlib.h>
+#include "r_obey.h"
+#include "r_rofs.h"
+#include "r_coreimage.h"
+#include "memmap.h"
+#include "symbolgenerator.h"
+extern TInt gLogLevel;
+extern TBool gLowMem;
+extern TInt gThreadNum;
+extern TBool gGenSymbols;
+////////////////////////////////////////////////////////////////////////
+
+
+
+inline TUint32 AlignData(TUint32 anAddr) {
+ return ((anAddr+0x0f)&~0x0f);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+
+E32Rofs::E32Rofs(CObeyFile *aObey)
+//
+// Constructor
+//
+ : iObey( aObey ), iOverhead(0)
+ {
+ if(gGenSymbols)
+ iSymGen = SymbolGenerator::GetInstance();
+ else
+ iSymGen = NULL;
+
+ iSize=aObey->iRomSize;
+ 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;
+ HMem::Set(iData, 0xff, iSize);
+ }
+
+}
+
+E32Rofs::~E32Rofs() {
+
+ if(gLowMem) {
+ iImageMap->CloseMemoryMap(ETrue);
+ delete iImageMap;
+ }
+ else if(iData)
+ delete []iData;
+}
+
+
+TInt E32Rofs::CreateExtension(MRofsImage* aImage) {
+
+ TUint8* addr=(TUint8*)iData;
+
+ TRomNode* pRootDir = aImage->RootDirectory();
+
+
+ const TInt extensionRofsheaderSize = KExtensionRofsHeaderSize;
+
+ // aImage->iSize contains the max size of the core image
+
+ // Layout the directory structure. Does not actually write it
+ // to the image. Returns the number of bytes used for the directory
+ // structure within the image.
+ TInt directoryOffset = extensionRofsheaderSize;
+ const TInt directorySize = LayoutDirectory( pRootDir, aImage->Size()+directoryOffset );
+ if( directorySize <= 0 ) {
+ Print(EError, "Failed laying out directories - return code %d\n", directorySize);
+ return KErrGeneral;
+ }
+
+ // get offset to start of file data, rounded up to next word boundary
+ TInt offs = extensionRofsheaderSize + directorySize;
+ const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
+
+ // Now we traverse the list of entries placing each file
+ // This updates the directory entries to point to the correct offset
+ // to the start of the file
+ const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset + aImage->Size(), aImage->Size());
+ if( fileDataSize <= 0 ) {
+ Print(EError, "Failed placing files - return code %d\n", fileDataSize);
+ return KErrGeneral;
+ }
+
+ // and then put the directory into the image
+ TInt err = PlaceDirectory( pRootDir, addr - aImage->Size() ); // offset pointer by size of core image
+ if( err != KErrNone ) {
+ Print(EError, "Failed placing directory - return code %d\n", err);
+ return err;
+ }
+
+ directoryOffset+=aImage->Size(); // offset offset by size of core image
+ // Now write the header
+ TExtensionRofsHeader * pHeader = (TExtensionRofsHeader*)iData;
+ pHeader->iIdentifier[0] = 'R';
+ pHeader->iIdentifier[1] = 'O';
+ pHeader->iIdentifier[2] = 'F';
+ pHeader->iIdentifier[3] = 'x';
+ pHeader->iHeaderSize = KExtensionRofsHeaderSize;
+ pHeader->iDirTreeOffset = directoryOffset;
+ pHeader->iDirTreeSize = iTotalDirectoryBlockSize;
+ pHeader->iDirFileEntriesOffset = directoryOffset + iTotalDirectoryBlockSize;
+ pHeader->iDirFileEntriesSize = iTotalFileBlockSize;
+ pHeader->iRofsFormatVersion = KRofsFormatVersion;
+ pHeader->iTime = iObey->iTime;
+ iSizeUsed = fileDataSize + fileDataStartOffset;
+ pHeader->iImageSize = iSizeUsed;
+ if (iObey->AutoSize())
+ MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
+ pHeader->iMaxImageSize = iSize;
+ pHeader->iCheckSum = 0; // not used yet
+
+ return KErrNone;
+}
+
+void E32Rofs::MakeAutomaticSize(TUint32 aPageSize) {
+ TUint32 size = iSizeUsed;
+ if (iSizeUsed % aPageSize > 0) {
+ //used size needs to be rounded up to nearest page size
+ size = (iSizeUsed/aPageSize + 1)*aPageSize;
+ }
+ iSize = size;
+}
+
+//
+// This is the main entry point to the ROFS image creation
+//
+TInt E32Rofs::Create() {
+ TUint8* addr=(TUint8*)iData;
+
+ TRomNode* pRootDir = iObey->iRootDirectory;
+ const TInt headerSize = KRofsHeaderSize;
+ // Layout the directory structure. Does not actually write it
+ // to the image. Returns the number of bytes used for the directory
+ // structure within the image.
+ const TInt directoryOffset = headerSize;
+ const TInt directorySize = LayoutDirectory( pRootDir, directoryOffset );
+ if( directorySize <= 0 ) {
+ Print(EError, "Failed laying out directories - return code %d\n", directorySize);
+ return KErrGeneral;
+ }
+
+ // get offset to start of file data, rounded up to next word boundary
+ TInt offs = headerSize + directorySize;
+ const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
+
+ // Now we traverse the list of entries placing each file
+ // This updates the directory entries to point to the correct offset
+ // to the start of the file
+ const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset );
+ if( fileDataSize < 0 ) {
+ Print(EError, "Failed placing files - rofssize is too small\n", fileDataSize);
+ return KErrGeneral;
+ }
+
+ // and then put the directory into the image
+ TInt err = PlaceDirectory( pRootDir, addr );
+ if( err != KErrNone ) {
+ Print(EError, "Failed placing directory - return code %d\n", err);
+ return err;
+ }
+
+ // Now write the header
+ TRofsHeader* pHeader = (TRofsHeader*)iData;
+ pHeader->iIdentifier[0] = 'R';
+ pHeader->iIdentifier[1] = 'O';
+ pHeader->iIdentifier[2] = 'F';
+ pHeader->iIdentifier[3] = 'S';
+ pHeader->iHeaderSize = KExtensionRofsHeaderSize;
+ pHeader->iDirTreeOffset = directoryOffset;
+ pHeader->iDirTreeSize = iTotalDirectoryBlockSize;
+ pHeader->iDirFileEntriesOffset = directoryOffset + iTotalDirectoryBlockSize;
+ pHeader->iDirFileEntriesSize = iTotalFileBlockSize;
+ pHeader->iRofsFormatVersion = KRofsFormatVersion;
+ pHeader->iTime = iObey->iTime;
+ iSizeUsed = fileDataSize + fileDataStartOffset;
+ pHeader->iImageSize = iSizeUsed;
+ pHeader->iImageVersion = iObey->iVersion;
+ if (iObey->AutoSize())
+ MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
+
+ pHeader->iMaxImageSize = iSize;
+ pHeader->iCheckSum = 0; // not used yet
+
+ return KErrNone;
+}
+void E32Rofs::DisplaySizes(TPrintType aWhere) {
+ Print(aWhere, "Summary of file sizes in rofs:\n");
+ TRomBuilderEntry *file=iObey->FirstFile();
+ while(file) {
+ file->DisplaySize(aWhere);
+ file=iObey->NextFile();
+ }
+ Print( aWhere, "Directory block size: %d\n"
+ "File block size: %d\n"
+ "Total directory size: %d\n"
+ "Total image size: %d\n",
+ iTotalDirectoryBlockSize,
+ iTotalFileBlockSize,
+ iTotalDirectoryBlockSize + iTotalFileBlockSize,
+ iSizeUsed );
+
+}
+
+void E32Rofs::LogExecutableAttributes(E32ImageHeaderV *aHdr) {
+ Print(ELog, "Uids: %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum);
+ Print(ELog, "Data size: %08x\n", aHdr->iDataSize);
+ 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, "Secure ID: %08x\n", aHdr->iS.iSecureId);
+ Print(ELog, "Vendor ID: %08x\n", aHdr->iS.iVendorId);
+ Print(ELog, "Priority: %d\n\n", aHdr->iProcessPriority);
+}
+class Worker : public boost::thread {
+ public:
+ static void thrd_func(E32Rofs* rofs){
+ CBytePair bpe;
+
+ bool deferred = false;
+ TPlacingSection* p = rofs->GetFileNode(deferred);
+ while(p) {
+ if(!deferred) {
+ p->len = p->node->PlaceFile(p->buf, (TUint32)-1, 0, &bpe);
+ //no symbol for hidden file
+ if(rofs->iSymGen && !p->node->iEntry->iHidden)
+ rofs->iSymGen->AddFile(p->node->iEntry->iFileName,(p->node->iEntry->iCompressEnabled|| p->node->iEntry->iExecutable));
+ }
+ p = rofs->GetFileNode(deferred);
+ }
+ rofs->ArriveDeferPoint();
+ p = rofs->GetDeferredJob();
+ while(p) {
+ p->len = p->node->PlaceFile(p->buf, (TUint32)-1, 0, &bpe);
+ p = rofs->GetDeferredJob();
+ }
+ }
+ Worker(E32Rofs* rofs) : boost::thread(thrd_func,rofs) {
+ }
+};
+
+TPlacingSection* E32Rofs::GetFileNode(bool &aDeferred) {
+ //get a node from the node list, the node list is protected by mutex iMuxTree.
+ //The iMuxTree also helps to make sure the order in iVPS is consistent with the node list.
+ //And this is the guarantee of same outputs regardless of how many threads being used.
+ boost::mutex::scoped_lock lock(iMuxTree);
+ aDeferred = false;
+ TRomNode* node = iLastNode;
+ while(node) {
+ if( node->IsFile()) {
+ if(!node->iHidden) {
+ iLastNode = node->NextNode();
+ break;
+ }
+ }
+ node = node->NextNode();
+ }
+
+ if(node && node->IsFile() && !node->iHidden) {
+ TPlacingSection* pps = new TPlacingSection(node);
+ iVPS.push_back(pps);
+ if(node->iAlias) {
+ iQueueAliasNode.push(pps);
+ aDeferred = true;
+ }
+ return pps;
+ }
+ return NULL;
+}
+TPlacingSection* E32Rofs::GetDeferredJob() {
+ // waiting all the normal node have been placed.
+ while(iWorkerArrived < gThreadNum)
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+
+ // now we can safely handle the alias nodes.
+ boost::mutex::scoped_lock lock(iMuxTree);
+ TPlacingSection* p = NULL;
+ if(!iQueueAliasNode.empty()) {
+ p = iQueueAliasNode.front();
+ iQueueAliasNode.pop();
+ }
+ return p;
+}
+void E32Rofs::ArriveDeferPoint() {
+ boost::mutex::scoped_lock lock(iMuxTree);
+ ++iWorkerArrived;
+}
+TInt E32Rofs::PlaceFiles( TRomNode* /*aRootDir*/, TUint8* aDestBase, TUint aBaseOffset, TInt aCoreSize )
+ //
+ // Traverses all entries placing all files and updating directory entry pointers.
+ // Returns number of bytes placed or -ve error code.
+ //
+ {
+ if(iSymGen)
+ iSymGen->SetSymbolFileName((const char *)iObey->iRomFileName);
+ iLastNode = TRomNode::FirstNode();
+ iWorkerArrived = 0;
+
+ boost::thread_group thrds;
+ Worker** workers = new Worker*[gThreadNum];
+ int i;
+ for (i = 0; i < gThreadNum; ++i) {
+ workers[i] = new Worker(this);
+ thrds.add_thread(workers[i]);
+ }
+
+ thrds.join_all();
+ delete [] workers;
+ if(iSymGen)
+ iSymGen->AddFile("",false);
+
+ TUint offset = aBaseOffset;
+ TUint8* dest = aDestBase;
+ TBool aIgnoreHiddenAttrib = ETrue;
+ TInt len = iVPS.size();
+ TInt maxSize;
+ for(i=0;i<len;i++) {
+ maxSize = aCoreSize + iSize - offset;
+ if(maxSize <= 0) {
+ // Image size is too low to proceed.
+ return maxSize;
+ }
+ if(iVPS[i]->node->iFileStartOffset != (TUint)KFileHidden) {
+ if (iVPS[i]->len > maxSize) {
+ // Image size is too low to proceed.
+ return maxSize - iVPS[i]->len;
+ }
+ memcpy(dest,iVPS[i]->buf,iVPS[i]->len);
+ if(iVPS[i]->node->iEntry->iFileOffset == -1) {
+ iVPS[i]->node->iEntry->iFileOffset = offset;
+ iVPS[i]->node->iFileStartOffset = iVPS[i]->node->iEntry->iFileOffset;
+ }
+ else {
+ TRomBuilderEntry* aEntry = (TRomBuilderEntry*)(iVPS[i]->node->iFileStartOffset);
+ iVPS[i]->node->iFileStartOffset = aEntry->iFileOffset;
+ }
+ }
+ iVPS[i]->len += (4-iVPS[i]->len) & 3;// round up to next word boundary
+ dest += iVPS[i]->len;
+ offset += iVPS[i]->len;
+
+ if(gLogLevel > DEFAULT_LOG_LEVEL )
+ {
+ TRomNode* node = iVPS[i]->node;
+ TInt aLen = node->FullNameLength(aIgnoreHiddenAttrib);
+ char *aBuf = new char[aLen+1];
+ if(gLogLevel & LOG_LEVEL_FILE_DETAILS)
+ {
+ node->GetFullName(aBuf, aIgnoreHiddenAttrib);
+ if(node->iEntry->iFileName)
+ Print(ELog,"%s\t%d\t%s\t%s\n", node->iEntry->iFileName, node->iEntry->RealFileSize(), (node->iHidden || node->iEntry->iHidden)? "hidden":"", aBuf);
+ else
+ Print(ELog,"%s\t%s\n", (node->iHidden || node->iEntry->iHidden) ? "hidden":"", aBuf);
+ }
+
+ if(gLogLevel & LOG_LEVEL_FILE_ATTRIBUTES)
+ {
+ if(!node->iHidden && !node->iEntry->iHidden)
+ Print(ELog, "Device file name: %s\n", aBuf);
+ if(node->iEntry->iExecutable)
+ LogExecutableAttributes((E32ImageHeaderV*)(dest-len));
+ }
+ delete[] aBuf;
+ }
+ }
+ return offset - aBaseOffset; // number of bytes used
+ }
+
+
+
+
+
+
+//
+// Creates the directory layout but does not write it to the image.
+// All directories are given a location in the image.
+// Returns the total number of bytes used for the directory (rounded
+// up to the nearest word) or a -ve error code.
+//
+TInt E32Rofs::LayoutDirectory( TRomNode* /*aRootDir*/, TUint aBaseOffset ) {
+ TRomNode* node = TRomNode::FirstNode();
+
+ TUint offset = aBaseOffset;
+ while( node ) {
+ if( node->IsDirectory()) {
+ // it is a directory block so we have to give it a location
+ node->SetImagePosition( offset );
+
+ // work out how much space it requires for the directory block
+ TInt dirLen;
+ TInt fileLen;
+ TInt err = node->CalculateDirectoryEntrySize( dirLen, fileLen );
+ if( err != KErrNone ) {
+ return err;
+ }
+ Print( ELog, "Directory '%s' @offs=0x%x, size=%d\n", node->iName, offset, dirLen );
+ dirLen += (4-dirLen) & 3; // round up to next word boundary
+ offset += dirLen;
+ }
+
+ node = node->NextNode();
+ }
+
+ TInt totalDirectoryBlockSize = offset - aBaseOffset; // number of bytes used
+ totalDirectoryBlockSize += (4 - totalDirectoryBlockSize) & 3; // round up
+
+ // Now go round again placing the file blocks
+ offset = aBaseOffset + totalDirectoryBlockSize;
+ const TUint fileBlockStartOffset = offset;
+ node = TRomNode::FirstNode();
+ while( node ) {
+ if( node->IsDirectory() ) {
+ // work out how much space it requires for the file block
+ TInt dummy;
+ TInt fileLen;
+ TInt err = node->CalculateDirectoryEntrySize( dummy, fileLen );
+
+ if( err != KErrNone ) {
+ return fileLen;
+ }
+ if( fileLen ) {
+ node->SetFileBlockPosition( offset );
+ Print( ELog, "File block for dir '%s' @offs=0x%x, size=%d\n", node->iName, offset, fileLen );
+ }
+
+ fileLen += (4-fileLen) & 3; // round up to next word boundary
+ offset += fileLen;
+ }
+
+ node = node->NextNode();
+ }
+
+ TInt totalFileBlockSize = offset - fileBlockStartOffset; // number of bytes used
+ totalFileBlockSize += (4 - totalFileBlockSize) & 3; // round up
+
+ iTotalDirectoryBlockSize = totalDirectoryBlockSize;
+ iTotalFileBlockSize = totalFileBlockSize;
+
+ return totalDirectoryBlockSize + totalFileBlockSize;
+}
+//
+// Writes the directory into the image.
+// Returns KErrNone on success, or error code
+//
+
+TInt E32Rofs::PlaceDirectory( TRomNode* /*aRootDir*/, TUint8* aDestBase ) {
+ TRomNode* node = TRomNode::FirstNode();
+
+ while( node ) {
+ if( node->IsDirectory() ) {
+ TInt err = node->Place( aDestBase );
+ if( err != KErrNone ) {
+ return err;
+ }
+ }
+ node = node->NextNode();
+ }
+ return KErrNone;
+}
+
+TInt E32Rofs::WriteImage( TInt aHeaderType ) {
+ 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();
+ if(iSymGen)
+ SymbolGenerator::Release();
+
+ return KErrNone;
+}
+
+TRomNode* E32Rofs::CopyDirectory(TRomNode*& aLastExecutable) {
+ return iObey->iRootDirectory->CopyDirectory(aLastExecutable);
+}
+
+
+// Output a rom image
+void E32Rofs::Write(ofstream &os, TInt aHeaderType) {
+
+ switch (aHeaderType) {
+ default:
+ case 0:
+ Print(EAlways, "\nWriting Rom image without");
+ break;
+ case 2:
+ Print(EAlways, "\nWriting Rom image with PE-COFF"); {
+ 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);
+ os.write( iData, iSizeUsed );
+}
+
+
+TRomNode* E32Rofs::RootDirectory() {
+ return iObey->iRootDirectory;
+}
+void E32Rofs::SetRootDirectory(TRomNode* aDir) {
+ iObey->iRootDirectory = aDir;
+}
+const char* E32Rofs::RomFileName() const {
+ return iObey->iRomFileName;
+}
+TInt E32Rofs::Size() const {
+ return iSize;
+}
+
+///////////////////
+