imgtools/romtools/rofsbuild/r_rofs.cpp
changeset 590 360bd6b35136
parent 0 044383f39525
child 654 7c11c3d8d025
equal deleted inserted replaced
588:c7c26511138f 590:360bd6b35136
    25 #include <stdlib.h>
    25 #include <stdlib.h>
    26 #include "r_obey.h"
    26 #include "r_obey.h"
    27 #include "r_rofs.h"
    27 #include "r_rofs.h"
    28 #include "r_coreimage.h"
    28 #include "r_coreimage.h"
    29 #include "memmap.h"
    29 #include "memmap.h"
       
    30 #include "symbolgenerator.h"
    30 extern TInt gLogLevel;
    31 extern TInt gLogLevel;
    31 extern TBool gLowMem;
    32 extern TBool gLowMem;
    32 extern TBool gFastCompress;
       
    33 extern TInt gThreadNum;
    33 extern TInt gThreadNum;
       
    34 extern TBool gGenSymbols;
    34 ////////////////////////////////////////////////////////////////////////
    35 ////////////////////////////////////////////////////////////////////////
    35 
    36 
    36 
    37 
    37 
    38 
    38 inline TUint32 AlignData(TUint32 anAddr)
    39 inline TUint32 AlignData(TUint32 anAddr) {
    39 	{
       
    40 	return ((anAddr+0x0f)&~0x0f);
    40 	return ((anAddr+0x0f)&~0x0f);
    41 	}
    41 }
    42 
    42 
    43 
    43 
    44 ////////////////////////////////////////////////////////////////////////
    44 ////////////////////////////////////////////////////////////////////////
    45 
    45 
    46 E32Rofs::E32Rofs(CObeyFile *aObey)
    46 E32Rofs::E32Rofs(CObeyFile *aObey)
    47 //
    47 //
    48 // Constructor
    48 // Constructor
    49 //
    49 //
    50 	: iObey( aObey ), iOverhead(0)
    50 	: iObey( aObey ), iOverhead(0)
    51 	{
    51 	{
       
    52 	if(gGenSymbols)
       
    53 		iSymGen = SymbolGenerator::GetInstance();
       
    54 	else
       
    55 		iSymGen = NULL;
    52 
    56 
    53 	iSize=aObey->iRomSize;
    57 	iSize=aObey->iRomSize;
    54 	if(gLowMem)
    58 	if(gLowMem) {
    55 	{
       
    56 		iImageMap = new Memmap();
    59 		iImageMap = new Memmap();
    57 
    60 
    58 		if(iImageMap == NULL)
    61 		if(iImageMap == NULL) {
    59 		{
       
    60 			iSize = 0;
    62 			iSize = 0;
    61 			Print(EError, "Out of memory.\n");
    63 			Print(EError, "Out of memory.\n");
    62 		}
    64 		}
    63 		else
    65 		else {
    64 		{
       
    65 			iImageMap->SetMaxMapSize(iSize);
    66 			iImageMap->SetMaxMapSize(iSize);
    66 			if(iImageMap->CreateMemoryMap(0, 0xff) == EFalse)
    67 			if(iImageMap->CreateMemoryMap(0, 0xff) == EFalse) {
    67 			{
       
    68 				iSize = 0;
    68 				iSize = 0;
    69 				Print(EError, "Failed to create image map object");
    69 				Print(EError, "Failed to create image map object");
    70 
    70 
    71 				iImageMap->CloseMemoryMap(ETrue);
    71 				iImageMap->CloseMemoryMap(ETrue);
    72 				delete iImageMap;
    72 				delete iImageMap;
    73 				iImageMap = NULL;
    73 				iImageMap = NULL;
    74 			}
    74 			}
    75 			else
    75 			else {
    76 			{
       
    77 				iData = iImageMap->GetMemoryMapPointer();
    76 				iData = iImageMap->GetMemoryMapPointer();
    78 			}
    77 			}
    79 		}
    78 		}
    80 	}
    79 	}
    81 	else
    80 	else {
    82 	{
       
    83 		iData=new char [iSize];
    81 		iData=new char [iSize];
    84 		if (iData==NULL)
    82 		if (iData==NULL)
    85 			iSize=0;
    83 			iSize=0;
    86 		HMem::Set(iData, 0xff, iSize);
    84 		HMem::Set(iData, 0xff, iSize);
    87 	}
    85 	}
    88 
    86 
    89 	}
    87 }
    90 
    88 
    91 E32Rofs::~E32Rofs()
    89 E32Rofs::~E32Rofs()  {
    92 //
    90 
    93 // Destructor
    91 	if(gLowMem) {
    94 //
       
    95 	{
       
    96 
       
    97 	if(gLowMem)
       
    98 	{
       
    99 		iImageMap->CloseMemoryMap(ETrue);
    92 		iImageMap->CloseMemoryMap(ETrue);
   100 		delete iImageMap;
    93 		delete iImageMap;
   101 	}
    94 	}
   102 	else
    95 	else if(iData)
   103 		delete iData;
    96 		delete []iData;
   104 	}
    97 }
   105 
    98 
   106 
    99 
   107 TInt E32Rofs::CreateExtension(MRofsImage* aImage) 
   100 TInt E32Rofs::CreateExtension(MRofsImage* aImage)  {
   108 	{
       
   109 
   101 
   110 	TUint8* addr=(TUint8*)iData;
   102 	TUint8* addr=(TUint8*)iData;
   111 
   103 
   112 	TRomNode* pRootDir = aImage->RootDirectory();
   104 	TRomNode* pRootDir = aImage->RootDirectory();
   113 	
   105 
   114 
   106 
   115 	const TInt extensionRofsheaderSize = KExtensionRofsHeaderSize;
   107 	const TInt extensionRofsheaderSize = KExtensionRofsHeaderSize;
   116 	
   108 
   117 	// aImage->iSize contains the max size of the core image
   109 	// aImage->iSize contains the max size of the core image
   118 
   110 
   119 	// Layout the directory structure. Does not actually write it
   111 	// Layout the directory structure. Does not actually write it
   120 	// to the image. Returns the number of bytes used for the directory
   112 	// to the image. Returns the number of bytes used for the directory
   121 	// structure within the image.
   113 	// structure within the image.
   122 	TInt directoryOffset = extensionRofsheaderSize;
   114 	TInt directoryOffset = extensionRofsheaderSize;
   123 	const TInt directorySize = LayoutDirectory( pRootDir, aImage->Size()+directoryOffset );
   115 	const TInt directorySize = LayoutDirectory( pRootDir, aImage->Size()+directoryOffset );
   124 	if( directorySize <= 0 )
   116 	if( directorySize <= 0 ) {
   125 		{
       
   126 		Print(EError, "Failed laying out directories - return code %d\n", directorySize);
   117 		Print(EError, "Failed laying out directories - return code %d\n", directorySize);
   127 		return KErrGeneral;
   118 		return KErrGeneral;
   128 		}
   119 	}
   129 
   120 
   130 	// get offset to start of file data, rounded up to next word boundary
   121 	// get offset to start of file data, rounded up to next word boundary
   131 	TInt offs = extensionRofsheaderSize + directorySize;
   122 	TInt offs = extensionRofsheaderSize + directorySize;
   132 	const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
   123 	const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
   133 
   124 
   134 	// Now we traverse the list of entries placing each file
   125 	// Now we traverse the list of entries placing each file
   135 	// This updates the directory entries to point to the correct offset
   126 	// This updates the directory entries to point to the correct offset
   136 	// to the start of the file
   127 	// to the start of the file
   137 	const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset + aImage->Size(), aImage->Size());
   128 	const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset + aImage->Size(), aImage->Size());
   138 	if( fileDataSize <= 0 )
   129 	if( fileDataSize <= 0 ) {
   139 		{
       
   140 		Print(EError, "Failed placing files - return code %d\n", fileDataSize);
   130 		Print(EError, "Failed placing files - return code %d\n", fileDataSize);
   141 		return KErrGeneral;
   131 		return KErrGeneral;
   142 		}
   132 	}
   143 
   133 
   144 	// and then put the directory into the image
   134 	// and then put the directory into the image
   145 	TInt err = PlaceDirectory( pRootDir, addr - aImage->Size() ); // offset pointer by size of core image
   135 	TInt err = PlaceDirectory( pRootDir, addr - aImage->Size() ); // offset pointer by size of core image
   146 	if( err != KErrNone )
   136 	if( err != KErrNone ) {
   147 		{
       
   148 		Print(EError, "Failed placing directory - return code %d\n", err);
   137 		Print(EError, "Failed placing directory - return code %d\n", err);
   149 		return err;
   138 		return err;
   150 		}
   139 	}
   151 		
   140 
   152 	directoryOffset+=aImage->Size(); // offset offset by size of core image
   141 	directoryOffset+=aImage->Size(); // offset offset by size of core image
   153 	// Now write the header
   142 	// Now write the header
   154 	TExtensionRofsHeader * pHeader = (TExtensionRofsHeader*)iData;
   143 	TExtensionRofsHeader * pHeader = (TExtensionRofsHeader*)iData;
   155 	pHeader->iIdentifier[0] = 'R';
   144 	pHeader->iIdentifier[0] = 'R';
   156 	pHeader->iIdentifier[1] = 'O';
   145 	pHeader->iIdentifier[1] = 'O';
   169 		MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
   158 		MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
   170 	pHeader->iMaxImageSize = iSize;
   159 	pHeader->iMaxImageSize = iSize;
   171 	pHeader->iCheckSum = 0;		// not used yet
   160 	pHeader->iCheckSum = 0;		// not used yet
   172 
   161 
   173 	return KErrNone;
   162 	return KErrNone;
   174 	}
   163 }
   175 	
   164 
   176 void E32Rofs::MakeAutomaticSize(TUint32 aPageSize)
   165 void E32Rofs::MakeAutomaticSize(TUint32 aPageSize) {
   177 		{
   166 	TUint32 size = iSizeUsed;
   178 		TUint32 size = iSizeUsed;
   167 	if (iSizeUsed % aPageSize > 0) {
   179 		if (iSizeUsed % aPageSize > 0)
   168 		//used size needs to be rounded up to nearest page size
   180 			{
   169 		size = (iSizeUsed/aPageSize + 1)*aPageSize;
   181 			//used size needs to be rounded up to nearest page size
   170 	}
   182 			size = (iSizeUsed/aPageSize + 1)*aPageSize;
   171 	iSize = size;
   183 			}
   172 }
   184 		iSize = size;
   173 
   185 		}
       
   186 
       
   187 TInt E32Rofs::Create()
       
   188 //
   174 //
   189 // This is the main entry point to the ROFS image creation
   175 // This is the main entry point to the ROFS image creation
   190 //
   176 //
   191 	{
   177 TInt E32Rofs::Create() {
   192 	TUint8* addr=(TUint8*)iData;
   178 	TUint8* addr=(TUint8*)iData;
   193 
   179 
   194 	TRomNode* pRootDir = iObey->iRootDirectory;
   180 	TRomNode* pRootDir = iObey->iRootDirectory;
   195 	const TInt headerSize = KRofsHeaderSize;
   181 	const TInt headerSize = KRofsHeaderSize;
   196 	// Layout the directory structure. Does not actually write it
   182 	// Layout the directory structure. Does not actually write it
   197 	// to the image. Returns the number of bytes used for the directory
   183 	// to the image. Returns the number of bytes used for the directory
   198 	// structure within the image.
   184 	// structure within the image.
   199 	const TInt directoryOffset = headerSize;
   185 	const TInt directoryOffset = headerSize;
   200 	const TInt directorySize = LayoutDirectory( pRootDir, directoryOffset );
   186 	const TInt directorySize = LayoutDirectory( pRootDir, directoryOffset );
   201 	if( directorySize <= 0 )
   187 	if( directorySize <= 0 ) {
   202 		{
       
   203 		Print(EError, "Failed laying out directories - return code %d\n", directorySize);
   188 		Print(EError, "Failed laying out directories - return code %d\n", directorySize);
   204 		return KErrGeneral;
   189 		return KErrGeneral;
   205 		}
   190 	}
   206 
   191 
   207 	// get offset to start of file data, rounded up to next word boundary
   192 	// get offset to start of file data, rounded up to next word boundary
   208 	TInt offs = headerSize + directorySize;
   193 	TInt offs = headerSize + directorySize;
   209 	const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
   194 	const TInt fileDataStartOffset = offs + ( (4 - offs) & 3);
   210 
   195 
   211 	// Now we traverse the list of entries placing each file
   196 	// Now we traverse the list of entries placing each file
   212 	// This updates the directory entries to point to the correct offset
   197 	// This updates the directory entries to point to the correct offset
   213 	// to the start of the file
   198 	// to the start of the file
   214 	const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset );
   199 	const TInt fileDataSize = PlaceFiles( pRootDir, addr + fileDataStartOffset, fileDataStartOffset );
   215 	if( fileDataSize < 0 )
   200 	if( fileDataSize < 0 ) {
   216 		{
   201 		Print(EError, "Failed placing files - rofssize is too small\n", fileDataSize);
   217 		Print(EError, "Failed placing files - return code %d\n", fileDataSize);
       
   218 		return KErrGeneral;
   202 		return KErrGeneral;
   219 		}
   203 	}
   220 
   204 
   221 	// and then put the directory into the image
   205 	// and then put the directory into the image
   222 	TInt err = PlaceDirectory( pRootDir, addr );
   206 	TInt err = PlaceDirectory( pRootDir, addr );
   223 	if( err != KErrNone )
   207 	if( err != KErrNone ) {
   224 		{
       
   225 		Print(EError, "Failed placing directory - return code %d\n", err);
   208 		Print(EError, "Failed placing directory - return code %d\n", err);
   226 		return err;
   209 		return err;
   227 		}
   210 	}
   228 		
   211 
   229 	// Now write the header
   212 	// Now write the header
   230 	TRofsHeader* pHeader = (TRofsHeader*)iData;
   213 	TRofsHeader* pHeader = (TRofsHeader*)iData;
   231 	pHeader->iIdentifier[0] = 'R';
   214 	pHeader->iIdentifier[0] = 'R';
   232 	pHeader->iIdentifier[1] = 'O';
   215 	pHeader->iIdentifier[1] = 'O';
   233 	pHeader->iIdentifier[2] = 'F';
   216 	pHeader->iIdentifier[2] = 'F';
   242 	iSizeUsed = fileDataSize + fileDataStartOffset;
   225 	iSizeUsed = fileDataSize + fileDataStartOffset;
   243 	pHeader->iImageSize = iSizeUsed;
   226 	pHeader->iImageSize = iSizeUsed;
   244 	pHeader->iImageVersion = iObey->iVersion;
   227 	pHeader->iImageVersion = iObey->iVersion;
   245 	if (iObey->AutoSize())
   228 	if (iObey->AutoSize())
   246 		MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
   229 		MakeAutomaticSize(iObey->AutoPageSize()); // change iSize to nearest page size
   247 		
   230 
   248 	pHeader->iMaxImageSize = iSize;
   231 	pHeader->iMaxImageSize = iSize;
   249 	pHeader->iCheckSum = 0;		// not used yet
   232 	pHeader->iCheckSum = 0;		// not used yet
   250 
   233 
   251 	return KErrNone;
   234 	return KErrNone;
   252 	}
   235 }
   253 void E32Rofs::DisplaySizes(TPrintType aWhere)
   236 void E32Rofs::DisplaySizes(TPrintType aWhere) {
   254 {
       
   255 	Print(aWhere, "Summary of file sizes in rofs:\n");
   237 	Print(aWhere, "Summary of file sizes in rofs:\n");
   256 	TRomBuilderEntry *file=iObey->FirstFile();
   238 	TRomBuilderEntry *file=iObey->FirstFile();
   257 	while(file)
   239 	while(file) {
   258 		{
       
   259 		file->DisplaySize(aWhere);
   240 		file->DisplaySize(aWhere);
   260 		file=iObey->NextFile();
   241 		file=iObey->NextFile();
   261 		}
   242 	}
   262 	Print( aWhere, "Directory block size: %d\n"
   243 	Print( aWhere, "Directory block size: %d\n"
   263 					"File block size:      %d\n"
   244 		"File block size:      %d\n"
   264 					"Total directory size: %d\n"
   245 		"Total directory size: %d\n"
   265 					"Total image size:     %d\n",
   246 		"Total image size:     %d\n",
   266 					iTotalDirectoryBlockSize,
   247 		iTotalDirectoryBlockSize,
   267 					iTotalFileBlockSize,
   248 		iTotalFileBlockSize,
   268 					iTotalDirectoryBlockSize + iTotalFileBlockSize,
   249 		iTotalDirectoryBlockSize + iTotalFileBlockSize,
   269 					iSizeUsed );
   250 		iSizeUsed );
   270 
   251 
   271 }
   252 }
   272 
   253 
   273 void E32Rofs::LogExecutableAttributes(E32ImageHeaderV *aHdr)
   254 void E32Rofs::LogExecutableAttributes(E32ImageHeaderV *aHdr) {
   274 {
       
   275 	Print(ELog, "Uids:                    %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum);
   255 	Print(ELog, "Uids:                    %08x %08x %08x %08x\n", aHdr->iUid1, aHdr->iUid2, aHdr->iUid3, aHdr->iUidChecksum);
   276 	Print(ELog, "Data size:               %08x\n", aHdr->iDataSize);
   256 	Print(ELog, "Data size:               %08x\n", aHdr->iDataSize);
   277 	Print(ELog, "Heap min:                %08x\n", aHdr->iHeapSizeMin);
   257 	Print(ELog, "Heap min:                %08x\n", aHdr->iHeapSizeMin);
   278 	Print(ELog, "Heap max:                %08x\n", aHdr->iHeapSizeMax);
   258 	Print(ELog, "Heap max:                %08x\n", aHdr->iHeapSizeMax);
   279 	Print(ELog, "Stack size:              %08x\n", aHdr->iStackSize);
   259 	Print(ELog, "Stack size:              %08x\n", aHdr->iStackSize);
   282 	Print(ELog, "Priority:                %d\n\n", aHdr->iProcessPriority);
   262 	Print(ELog, "Priority:                %d\n\n", aHdr->iProcessPriority);
   283 }
   263 }
   284 class Worker : public boost::thread {
   264 class Worker : public boost::thread {
   285     public:
   265     public:
   286     static void thrd_func(E32Rofs* rofs){
   266     static void thrd_func(E32Rofs* rofs){
   287         CBytePair bpe(gFastCompress);
   267         CBytePair bpe;
   288 
   268 
   289         bool deferred = false;
   269         bool deferred = false;
   290         TPlacingSection* p = rofs->GetFileNode(deferred);
   270         TPlacingSection* p = rofs->GetFileNode(deferred);
   291         while(p) {
   271         while(p) {
   292             if(!deferred) 
   272             if(!deferred) {
   293                 p->len = p->node->PlaceFile(p->buf, (TUint32)-1, 0, &bpe);
   273                 p->len = p->node->PlaceFile(p->buf, (TUint32)-1, 0, &bpe);
       
   274                 //no symbol for hidden file
       
   275                 if(rofs->iSymGen && !p->node->iEntry->iHidden)
       
   276                     rofs->iSymGen->AddFile(p->node->iEntry->iFileName,(p->node->iEntry->iCompressEnabled|| p->node->iEntry->iExecutable));
       
   277             }
   294             p = rofs->GetFileNode(deferred);
   278             p = rofs->GetFileNode(deferred);
   295         }
   279         }
   296         rofs->ArriveDeferPoint();
   280         rofs->ArriveDeferPoint();
   297         p = rofs->GetDeferredJob();
   281         p = rofs->GetDeferredJob();
   298         while(p) {
   282         while(p) {
   303     Worker(E32Rofs* rofs) : boost::thread(thrd_func,rofs) {
   287     Worker(E32Rofs* rofs) : boost::thread(thrd_func,rofs) {
   304     }
   288     }
   305 };
   289 };
   306 
   290 
   307 TPlacingSection* E32Rofs::GetFileNode(bool &aDeferred) {
   291 TPlacingSection* E32Rofs::GetFileNode(bool &aDeferred) {
   308     //get a node from the node list, the node list is protected by mutex iMuxTree.
   292 	//get a node from the node list, the node list is protected by mutex iMuxTree.
   309     //The iMuxTree also helps to make sure the order in iVPS is consistent with the node list.
   293 	//The iMuxTree also helps to make sure the order in iVPS is consistent with the node list.
   310     //And this is the guarantee of same outputs regardless of how many threads being used.
   294 	//And this is the guarantee of same outputs regardless of how many threads being used.
   311     boost::mutex::scoped_lock lock(iMuxTree);
   295 	boost::mutex::scoped_lock lock(iMuxTree);
   312     aDeferred = false;
   296 	aDeferred = false;
   313     TRomNode* node = iLastNode;
   297 	TRomNode* node = iLastNode;
   314     while(node) {
   298 	while(node) {
   315         if( node->IsFile()) {
   299 		if( node->IsFile()) {
   316             if(!node->iHidden) {
   300 			if(!node->iHidden) {
   317                 iLastNode = node->NextNode();
   301 				iLastNode = node->NextNode();
   318                 break;
   302 				break;
   319             }
   303 			}
   320         }
   304 		}
   321         node = node->NextNode();
   305 		node = node->NextNode();
   322     }
   306 	}
   323 
   307 
   324     if(node && node->IsFile() && !node->iHidden) {
   308 	if(node && node->IsFile() && !node->iHidden) {
   325         TPlacingSection* pps = new TPlacingSection(node);
   309 		TPlacingSection* pps = new TPlacingSection(node);
   326         iVPS.push_back(pps);
   310 		iVPS.push_back(pps);
   327         if(node->iAlias) {
   311 		if(node->iAlias) {
   328             iQueueAliasNode.push(pps);
   312 			iQueueAliasNode.push(pps);
   329             aDeferred =  true;
   313 			aDeferred =  true;
   330         }
   314 		}
   331         return pps;
   315 		return pps;
   332     }
   316 	}
   333     return NULL;
   317 	return NULL;
   334 }
   318 }
   335 TPlacingSection* E32Rofs::GetDeferredJob() {
   319 TPlacingSection* E32Rofs::GetDeferredJob() {
   336     // waiting all the normal node have been placed.
   320 	// waiting all the normal node have been placed.
   337     while(iWorkerArrived < gThreadNum)
   321 	while(iWorkerArrived < gThreadNum)
   338         boost::this_thread::sleep(boost::posix_time::milliseconds(10));
   322 		boost::this_thread::sleep(boost::posix_time::milliseconds(10));
   339 
   323 
   340     // now we can safely handle the alias nodes.
   324 	// now we can safely handle the alias nodes.
   341     boost::mutex::scoped_lock lock(iMuxTree);
   325 	boost::mutex::scoped_lock lock(iMuxTree);
   342     TPlacingSection* p = NULL;
   326 	TPlacingSection* p = NULL;
   343     if(!iQueueAliasNode.empty()) {
   327 	if(!iQueueAliasNode.empty()) {
   344         p = iQueueAliasNode.front();
   328 		p = iQueueAliasNode.front();
   345         iQueueAliasNode.pop();
   329 		iQueueAliasNode.pop();
   346     }
   330 	}
   347     return p;
   331 	return p;
   348 }
   332 }
   349 void E32Rofs::ArriveDeferPoint() {
   333 void E32Rofs::ArriveDeferPoint() {
   350     boost::mutex::scoped_lock lock(iMuxTree);
   334 	boost::mutex::scoped_lock lock(iMuxTree);
   351     ++iWorkerArrived;
   335 	++iWorkerArrived;
   352 }
   336 }
   353 TInt E32Rofs::PlaceFiles( TRomNode* /*aRootDir*/, TUint8* aDestBase, TUint aBaseOffset, TInt aCoreSize ) 
   337 TInt E32Rofs::PlaceFiles( TRomNode* /*aRootDir*/, TUint8* aDestBase, TUint aBaseOffset, TInt aCoreSize ) 
   354 	//
   338 	//
   355 	// Traverses all entries placing all files and updating directory entry pointers.
   339 	// Traverses all entries placing all files and updating directory entry pointers.
   356 	// Returns number of bytes placed or -ve error code.
   340 	// Returns number of bytes placed or -ve error code.
   357 	//
   341 	//
   358 	{
   342 	{
       
   343             if(iSymGen)
       
   344                 iSymGen->SetSymbolFileName((const char *)iObey->iRomFileName);
   359             iLastNode = TRomNode::FirstNode();
   345             iLastNode = TRomNode::FirstNode();
   360             iWorkerArrived = 0;
   346             iWorkerArrived = 0;
   361 
   347 
   362             boost::thread_group thrds;
   348             boost::thread_group thrds;
   363             Worker** workers = new Worker*[gThreadNum];
   349             Worker** workers = new Worker*[gThreadNum];
   367                 thrds.add_thread(workers[i]);
   353                 thrds.add_thread(workers[i]);
   368             }
   354             }
   369 
   355 
   370             thrds.join_all();
   356             thrds.join_all();
   371             delete [] workers;
   357             delete [] workers;
       
   358             if(iSymGen)
       
   359                 iSymGen->AddFile("",false);
   372 
   360 
   373             TUint offset = aBaseOffset;
   361             TUint offset = aBaseOffset;
   374             TUint8* dest = aDestBase;
   362             TUint8* dest = aDestBase;
   375             TBool aIgnoreHiddenAttrib = ETrue;
   363             TBool aIgnoreHiddenAttrib = ETrue;
   376             TInt len = iVPS.size();
   364             TInt len = iVPS.size();
   380                 if(maxSize <= 0) {
   368                 if(maxSize <= 0) {
   381                     // Image size is too low to proceed.
   369                     // Image size is too low to proceed.
   382                     return maxSize;
   370                     return maxSize;
   383                 }
   371                 }
   384                 if(iVPS[i]->node->iFileStartOffset != (TUint)KFileHidden) {
   372                 if(iVPS[i]->node->iFileStartOffset != (TUint)KFileHidden) {
       
   373                     if (iVPS[i]->len > maxSize) {
       
   374                        // Image size is too low to proceed.
       
   375                        return maxSize - iVPS[i]->len;
       
   376                     }
   385                     memcpy(dest,iVPS[i]->buf,iVPS[i]->len);
   377                     memcpy(dest,iVPS[i]->buf,iVPS[i]->len);
   386                     if(iVPS[i]->node->iEntry->iFileOffset == -1) {
   378                     if(iVPS[i]->node->iEntry->iFileOffset == -1) {
   387                         iVPS[i]->node->iEntry->iFileOffset = offset;
   379                         iVPS[i]->node->iEntry->iFileOffset = offset;
   388                         iVPS[i]->node->iFileStartOffset = iVPS[i]->node->iEntry->iFileOffset;
   380                         iVPS[i]->node->iFileStartOffset = iVPS[i]->node->iEntry->iFileOffset;
   389                     }
   381                     }
   426 
   418 
   427 
   419 
   428 
   420 
   429 
   421 
   430 
   422 
   431 TInt E32Rofs::LayoutDirectory( TRomNode* /*aRootDir*/, TUint aBaseOffset ) 
   423 //
   432 	//
   424 // Creates the directory layout but does not write it to the image.
   433 	// Creates the directory layout but does not write it to the image.
   425 // All directories are given a location in the image.
   434 	// All directories are given a location in the image.
   426 // Returns the total number of bytes used for the directory (rounded
   435 	// Returns the total number of bytes used for the directory (rounded
   427 // up to the nearest word) or a -ve error code.
   436 	// up to the nearest word) or a -ve error code.
   428 //
   437 	//
   429 TInt E32Rofs::LayoutDirectory( TRomNode* /*aRootDir*/, TUint aBaseOffset )  {
   438 	{
       
   439 	TRomNode* node = TRomNode::FirstNode();
   430 	TRomNode* node = TRomNode::FirstNode();
   440 
   431 
   441 	TUint offset = aBaseOffset;
   432 	TUint offset = aBaseOffset;
   442 	while( node )
   433 	while( node ) {
   443 		{
   434 		if( node->IsDirectory()) {
   444 		if( node->IsDirectory())
       
   445 			{
       
   446 			// it is a directory block so we have to give it a location
   435 			// it is a directory block so we have to give it a location
   447 			node->SetImagePosition( offset );
   436 			node->SetImagePosition( offset );
   448 		
   437 
   449 			// work out how much space it requires for the directory block
   438 			// work out how much space it requires for the directory block
   450 			TInt dirLen;
   439 			TInt dirLen;
   451 			TInt fileLen;
   440 			TInt fileLen;
   452 			TInt err = node->CalculateDirectoryEntrySize( dirLen, fileLen );
   441 			TInt err = node->CalculateDirectoryEntrySize( dirLen, fileLen );
   453 			if( err != KErrNone )
   442 			if( err != KErrNone ) {
   454 				{
       
   455 				return err;
   443 				return err;
   456 				}
   444 			}
   457 			Print( ELog, "Directory '%s' @offs=0x%x, size=%d\n", node->iName, offset, dirLen );
   445 			Print( ELog, "Directory '%s' @offs=0x%x, size=%d\n", node->iName, offset, dirLen );
   458 			dirLen += (4-dirLen) & 3;	// round up to next word boundary
   446 			dirLen += (4-dirLen) & 3;	// round up to next word boundary
   459 			offset += dirLen;
   447 			offset += dirLen;
   460 			}
   448 		}
   461 
   449 
   462 		node = node->NextNode();
   450 		node = node->NextNode();
   463 		}
   451 	}
   464 
   452 
   465 	TInt totalDirectoryBlockSize = offset - aBaseOffset;	// number of bytes used
   453 	TInt totalDirectoryBlockSize = offset - aBaseOffset;	// number of bytes used
   466 	totalDirectoryBlockSize += (4 - totalDirectoryBlockSize) & 3;		// round up
   454 	totalDirectoryBlockSize += (4 - totalDirectoryBlockSize) & 3;		// round up
   467 
   455 
   468 	// Now go round again placing the file blocks
   456 	// Now go round again placing the file blocks
   469 	offset = aBaseOffset + totalDirectoryBlockSize;
   457 	offset = aBaseOffset + totalDirectoryBlockSize;
   470 	const TUint fileBlockStartOffset = offset;
   458 	const TUint fileBlockStartOffset = offset;
   471 	node = TRomNode::FirstNode();
   459 	node = TRomNode::FirstNode();
   472 	while( node )
   460 	while( node ) {
   473 		{
   461 		if( node->IsDirectory() ) {
   474 		if( node->IsDirectory() )
       
   475 			{
       
   476 			// work out how much space it requires for the file block
   462 			// work out how much space it requires for the file block
   477 			TInt dummy;
   463 			TInt dummy;
   478 			TInt fileLen;
   464 			TInt fileLen;
   479 			TInt err = node->CalculateDirectoryEntrySize( dummy, fileLen );
   465 			TInt err = node->CalculateDirectoryEntrySize( dummy, fileLen );
   480 
   466 
   481 			if( err != KErrNone )
   467 			if( err != KErrNone ) {
   482 				{
       
   483 				return fileLen;
   468 				return fileLen;
   484 				}
   469 			}
   485 			if( fileLen )
   470 			if( fileLen ) {
   486 				{
       
   487 				node->SetFileBlockPosition( offset );
   471 				node->SetFileBlockPosition( offset );
   488 				Print( ELog, "File block for dir '%s' @offs=0x%x, size=%d\n", node->iName, offset, fileLen );
   472 				Print( ELog, "File block for dir '%s' @offs=0x%x, size=%d\n", node->iName, offset, fileLen );
   489 				}
   473 			}
   490 		
   474 
   491 			fileLen += (4-fileLen) & 3;	// round up to next word boundary
   475 			fileLen += (4-fileLen) & 3;	// round up to next word boundary
   492 			offset += fileLen;
   476 			offset += fileLen;
   493 			}
   477 		}
   494 
   478 
   495 		node = node->NextNode();
   479 		node = node->NextNode();
   496 		}
   480 	}
   497 
   481 
   498 	TInt totalFileBlockSize = offset - fileBlockStartOffset;	// number of bytes used
   482 	TInt totalFileBlockSize = offset - fileBlockStartOffset;	// number of bytes used
   499 	totalFileBlockSize += (4 - totalFileBlockSize) & 3;		// round up
   483 	totalFileBlockSize += (4 - totalFileBlockSize) & 3;		// round up
   500 
   484 
   501 	iTotalDirectoryBlockSize = totalDirectoryBlockSize;
   485 	iTotalDirectoryBlockSize = totalDirectoryBlockSize;
   502 	iTotalFileBlockSize = totalFileBlockSize;
   486 	iTotalFileBlockSize = totalFileBlockSize;
   503 
   487 
   504 	return totalDirectoryBlockSize + totalFileBlockSize;
   488 	return totalDirectoryBlockSize + totalFileBlockSize;
   505 	}
   489 }
   506 
   490 //
   507 
   491 // Writes the directory into the image. 
   508 TInt E32Rofs::PlaceDirectory( TRomNode* /*aRootDir*/, TUint8* aDestBase ) 
   492 // Returns KErrNone on success, or error code
   509 	//
   493 //
   510 	// Writes the directory into the image. 
   494 
   511 	// Returns KErrNone on success, or error code
   495 TInt E32Rofs::PlaceDirectory( TRomNode* /*aRootDir*/, TUint8* aDestBase )  {
   512 	//
       
   513 	{
       
   514 	TRomNode* node = TRomNode::FirstNode();
   496 	TRomNode* node = TRomNode::FirstNode();
   515 
   497 
   516 	while( node )
   498 	while( node ) {
   517 		{
   499 		if( node->IsDirectory() ) {
   518 		if( node->IsDirectory() )
       
   519 			{
       
   520 			TInt err = node->Place( aDestBase );
   500 			TInt err = node->Place( aDestBase );
   521 			if( err != KErrNone )
   501 			if( err != KErrNone ) {
   522 				{
       
   523 				return err;
   502 				return err;
   524 				}
   503 			}
   525 			}
   504 		}
   526 		node = node->NextNode();
   505 		node = node->NextNode();
   527 		}
   506 	}
   528 	return KErrNone;
   507 	return KErrNone;
   529 	}
   508 }
   530 
   509 
   531 TInt E32Rofs::WriteImage( TInt aHeaderType )
   510 TInt E32Rofs::WriteImage( TInt aHeaderType ) {
   532 	{
   511 	ofstream romFile((const char *)iObey->iRomFileName,ios_base::binary);
   533 	ofstream romFile((const char *)iObey->iRomFileName,ios::binary);
       
   534 	if (!romFile)
   512 	if (!romFile)
   535 		return Print(EError,"Cannot open ROM file %s for output\n",iObey->iRomFileName);
   513 		return Print(EError,"Cannot open ROM file %s for output\n",iObey->iRomFileName);
   536 	Write(romFile, aHeaderType);
   514 	Write(romFile, aHeaderType);
   537 	romFile.close();
   515 	romFile.close();
       
   516         if(iSymGen)
       
   517             SymbolGenerator::Release();
   538 
   518 
   539 	return KErrNone;
   519 	return KErrNone;
   540 	}
   520 }
   541 
   521 
   542 TRomNode* E32Rofs::CopyDirectory(TRomNode*& aLastExecutable)
   522 TRomNode* E32Rofs::CopyDirectory(TRomNode*& aLastExecutable) {
   543 	{
       
   544 	return iObey->iRootDirectory->CopyDirectory(aLastExecutable);
   523 	return iObey->iRootDirectory->CopyDirectory(aLastExecutable);
   545 	}
   524 }
   546 
   525 
   547 
       
   548 void E32Rofs::Write(ofstream &os, TInt aHeaderType)
       
   549 
   526 
   550 // Output a rom image
   527 // Output a rom image
   551 
   528 void E32Rofs::Write(ofstream &os, TInt aHeaderType) {
   552 	{
   529 
   553 
   530 	switch (aHeaderType) {
   554 	switch (aHeaderType)
       
   555 		{
       
   556 	default:
   531 	default:
   557 	case 0:
   532 	case 0:
   558 		Print(EAlways, "\nWriting Rom image without");
   533 		Print(EAlways, "\nWriting Rom image without");
   559 		break;
   534 		break;
   560 	case 2:
   535 	case 2:
   561 		Print(EAlways, "\nWriting Rom image with PE-COFF");
   536 		Print(EAlways, "\nWriting Rom image with PE-COFF"); {
   562 			{
       
   563 			unsigned char coffhead[0x58] = {0};  // zero all the elements
   537 			unsigned char coffhead[0x58] = {0};  // zero all the elements
   564 
   538 
   565 			// fill in the constant bits
   539 			// fill in the constant bits
   566 			// this is supposed to be simple, remember
   540 			// this is supposed to be simple, remember
   567 			coffhead[1] = 0x0a;
   541 			coffhead[1] = 0x0a;
   586 			// now fill in the text segment size
   560 			// now fill in the text segment size
   587 			*(TUint32 *) (&coffhead[0x18]) = ALIGN4K(iSizeUsed);
   561 			*(TUint32 *) (&coffhead[0x18]) = ALIGN4K(iSizeUsed);
   588 			*(TUint32 *) (&coffhead[0x40]) = ALIGN4K(iSizeUsed);
   562 			*(TUint32 *) (&coffhead[0x40]) = ALIGN4K(iSizeUsed);
   589 
   563 
   590 			os.write(reinterpret_cast<char *>(coffhead), sizeof(coffhead));
   564 			os.write(reinterpret_cast<char *>(coffhead), sizeof(coffhead));
   591 			}
   565 		}
   592 		break;
   566 		break;
   593 		}
   567 	}
   594 	Print(EAlways, " header to file %s\n", iObey->iRomFileName);
   568 	Print(EAlways, " header to file %s\n", iObey->iRomFileName);
   595 	os.write( iData, iSizeUsed );
   569 	os.write( iData, iSizeUsed );
   596 	}
   570 }
   597 
   571 
   598 
   572 
   599 TRomNode* E32Rofs::RootDirectory()
   573 TRomNode* E32Rofs::RootDirectory() {
   600 	{
       
   601 	return iObey->iRootDirectory;
   574 	return iObey->iRootDirectory;
   602 	}
   575 }
   603 void E32Rofs::SetRootDirectory(TRomNode* aDir)
   576 void E32Rofs::SetRootDirectory(TRomNode* aDir) {
   604 	{
       
   605 	iObey->iRootDirectory = aDir;
   577 	iObey->iRootDirectory = aDir;
   606 	}
   578 }
   607 TText* E32Rofs::RomFileName()
   579 const char* E32Rofs::RomFileName() const  {
   608 	{
       
   609 	return iObey->iRomFileName;
   580 	return iObey->iRomFileName;
   610 	}
   581 }
   611 TInt E32Rofs::Size()
   582 TInt E32Rofs::Size() const  {
   612 	{
       
   613 	return iSize;
   583 	return iSize;
   614 	}
   584 }
   615 
   585 
   616 ///////////////////
   586 ///////////////////
   617 
   587