imgtools/romtools/rofsbuild/r_build.cpp
changeset 2 39c28ec933dd
equal deleted inserted replaced
1:820b22e13ff1 2:39c28ec933dd
       
     1 /*
       
     2 * Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * @internalComponent * @released
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <stdlib.h>
       
    21 #include <string.h>
       
    22 #include <ctype.h>
       
    23 #include <e32std.h>
       
    24 #include <e32std_private.h>
       
    25 #include <e32rom.h>
       
    26 #include <u32std.h>
       
    27 #include <e32uid.h>
       
    28 #include <f32file.h>
       
    29 
       
    30 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
    31 	#include <iomanip>
       
    32 	#include <sstream>
       
    33 #else //!__MSVCDOTNET__
       
    34 	#include <iomanip.h>
       
    35 #endif //__MSVCDOTNET__
       
    36 
       
    37 #ifdef _L
       
    38 #undef _L
       
    39 #endif
       
    40 
       
    41 #include "h_utl.h"
       
    42 #include "r_obey.h"
       
    43 #include "rofs.h"
       
    44 #include "e32image.h"
       
    45 #include "patchdataprocessor.h"
       
    46 
       
    47 extern TUint checkSum(const void* aPtr);
       
    48 
       
    49 extern ECompression gCompress;
       
    50 extern TUint gCompressionMethod;
       
    51 extern TInt  gCodePagingOverride;
       
    52 extern TInt  gDataPagingOverride;
       
    53 extern TInt  gLogLevel;
       
    54 TBool gDriveImage=EFalse;	// for drive image support.
       
    55 
       
    56 
       
    57 TInt TRomNode::Count=0;
       
    58 TRomNode* TRomNode::TheFirstNode = NULL;
       
    59 TRomNode* TRomNode::TheLastNode = NULL;
       
    60 
       
    61 // introduced for data drive files' attribute
       
    62 TUint8 TRomNode::sDefaultInitialAttr = (TUint8)KEntryAttReadOnly;
       
    63 
       
    64 struct SortableEntry
       
    65 	{
       
    66 	TRofsEntry* iEntry;
       
    67 	TBool iIsDir;
       
    68 	TUint16 iOffset;
       
    69 	};
       
    70 
       
    71 int compare(const void* l, const void* r)
       
    72 	{
       
    73 	const SortableEntry* left  = (const SortableEntry*)l;
       
    74 	const SortableEntry* right = (const SortableEntry*)r;
       
    75 	if (left->iIsDir)
       
    76 		{
       
    77 		if (!right->iIsDir)
       
    78 			return -1;	// dir < file
       
    79 		}
       
    80 	else
       
    81 		{
       
    82 		if (right->iIsDir)
       
    83 			return +1;	// file > dir
       
    84 		}
       
    85 
       
    86 	// both the same type of entry, sort by name
       
    87 	// must first convert to an 8 bit string
       
    88 	// array and NULL terminate it.
       
    89 	char temp1[500];
       
    90 	char temp2[500];
       
    91 
       
    92 
       
    93 TInt i=0;
       
    94 	for (i = 0; i < left->iEntry->iNameLength; i++)
       
    95 		{
       
    96 		temp1[i]=(char) left->iEntry->iName[i];
       
    97 		}
       
    98 	temp1[i]=0;
       
    99 
       
   100 	for (i = 0; i < right->iEntry->iNameLength; i++)
       
   101 		{
       
   102 		temp2[i]=(char) right->iEntry->iName[i];
       
   103 		}
       
   104 	temp2[i]=0;
       
   105 
       
   106 	return stricmp((const char*)&temp1[0], (const char*)&temp2[0]);
       
   107 	}
       
   108 
       
   109 TRomNode::TRomNode(TText* aName, TRomBuilderEntry* aEntry)
       
   110 //
       
   111 // Constructor
       
   112 //
       
   113 	:
       
   114 	iNextNode(NULL),
       
   115 	iParent(NULL), iSibling(0), iChild(0), iNextNodeForSameFile(0), 
       
   116 	iTotalDirectoryBlockSize(0),
       
   117 	iTotalFileBlockSize(0),
       
   118 	iImagePosition(0),
       
   119 	iFileBlockPosition(0),
       
   120 	iAtt(sDefaultInitialAttr),
       
   121 	iAttExtra(0xFF),
       
   122 	iHidden(EFalse),
       
   123 	iEntry(aEntry),
       
   124 	iFileStartOffset(0), 
       
   125 	iSize(0), 
       
   126 	iOverride(0),
       
   127 	iFileUpdate(EFalse),
       
   128     iAlias(false)
       
   129 	{
       
   130 	iName = (TText*)NormaliseFileName((const char*)aName);
       
   131 	iIdentifier=TRomNode::Count++;
       
   132 
       
   133 	// Add this node to the flat linked list
       
   134 	if( !TheFirstNode )
       
   135 		{
       
   136 		TheFirstNode = this;
       
   137 		}
       
   138 	else
       
   139 		{
       
   140 		TheLastNode->iNextNode = this;
       
   141 		}
       
   142 	TheLastNode = this;
       
   143 
       
   144 	if (iEntry)
       
   145 		{
       
   146 		iEntry->SetRomNode(this);
       
   147 		}
       
   148 	else
       
   149 		{
       
   150 		iAtt = (TUint8)KEntryAttDir;
       
   151 		}
       
   152 	}
       
   153 
       
   154 TRomNode::~TRomNode()
       
   155 	{
       
   156 	if (iEntry && !iAlias)
       
   157         {
       
   158 		delete iEntry;
       
   159         }
       
   160     iEntry = 0;
       
   161 	if(iName)
       
   162 		free(iName);
       
   163     iName = 0;
       
   164 	}
       
   165 
       
   166 TRomNode *TRomNode::FindInDirectory(TText *aName)
       
   167 //
       
   168 // Check if the TRomNode for aName exists in aDir, and if so, return it.
       
   169 //
       
   170 	{
       
   171 
       
   172 	TRomNode *entry=iChild; // first subdirectory or file
       
   173 	while (entry)
       
   174 		{
       
   175 		if ((stricmp((const char *)aName, (const char *)entry->iName))==0) 
       
   176 			return entry;
       
   177 		else
       
   178 			entry=entry->iSibling;
       
   179 		}
       
   180 	return 0;
       
   181 	}
       
   182 
       
   183 
       
   184 
       
   185 TInt indend = 0;
       
   186 
       
   187 void indendStructure(TInt i)
       
   188        {
       
   189 	while(i > 0)
       
   190 	   {
       
   191 	     cout << "    ";
       
   192 	     i--;
       
   193 	   }
       
   194        };  
       
   195 
       
   196 // displays the directory structure
       
   197 void TRomNode::DisplayStructure(ostream* aOut)
       
   198 	{
       
   199 	  indendStructure(indend);
       
   200       *aOut  << iName << "\n";
       
   201 	  if (iChild)
       
   202 	    {
       
   203 	      indend++; 
       
   204 	      iChild->DisplayStructure(aOut);
       
   205 	      indend--;
       
   206 	    }
       
   207 	  if (iSibling)
       
   208 	    iSibling->DisplayStructure(aOut);
       
   209 	}
       
   210 
       
   211 
       
   212 void TRomNode::deleteTheFirstNode()
       
   213 {
       
   214 
       
   215 	TheFirstNode = NULL;
       
   216 }
       
   217 
       
   218 
       
   219 void TRomNode::InitializeCount()
       
   220 {
       
   221 	Count = 0;
       
   222 }
       
   223 void TRomNode::displayFlatList()
       
   224 {
       
   225 	TRomNode* current =	TheFirstNode;
       
   226 	TInt i = 0;
       
   227 	while(current)
       
   228 	{
       
   229 		i++;
       
   230 		cout <<  "\n" << i <<": " << current->iName << endl;
       
   231 		current = current->NextNode();
       
   232 	}
       
   233 
       
   234 	}
       
   235 
       
   236 
       
   237 
       
   238 void TRomNode::AddFile(TRomNode* aChild)
       
   239 	{
       
   240 	if (iEntry)
       
   241 		{
       
   242 		Print(EError, "Adding subdirectory to a file!!!\n");
       
   243 		return;
       
   244 		}
       
   245 	Add(aChild);
       
   246 	}
       
   247 
       
   248 TRomNode* TRomNode::NewSubDir(TText *aName)
       
   249 	{
       
   250 	if (iEntry)
       
   251 		{
       
   252 		Print(EError, "Adding subdirectory to a file!!!\n");
       
   253 		return 0;
       
   254 		}
       
   255 
       
   256 	TRomNode* node = new TRomNode(aName );
       
   257 	if (node==0)
       
   258 		{
       
   259 		Print(EError, "TRomNode::NewNode: Out of memory\n");
       
   260 		return 0;
       
   261 		}
       
   262 	node->iParent = this;
       
   263 	Add(node);
       
   264 	return node;
       
   265 	}
       
   266 
       
   267 void TRomNode::Add(TRomNode* aChild)
       
   268 	{
       
   269 	if (iChild) // this node is a non-empty directory
       
   270 		{
       
   271 		TRomNode* dir = iChild; // find where to link in the new node
       
   272 		while (dir->iSibling)
       
   273 			dir = dir->iSibling;
       
   274 		dir->iSibling = aChild;
       
   275 		}
       
   276 	else
       
   277 		iChild = aChild; // else just set it up as the child of the dir
       
   278 	aChild->iSibling = 0;
       
   279 	aChild->iParent = this;
       
   280 	}
       
   281 
       
   282 TInt TRomNode::SetAttExtra(TText *anAttWord, TRomBuilderEntry* aFile, enum EKeyword aKeyword)
       
   283 //
       
   284 // Set the file extra attribute byte from the letters passed
       
   285 // Note: The iAttExtra bits are inverted. '0' represent enabled
       
   286 //
       
   287 	{
       
   288 	iAttExtra=0xFF;
       
   289 	if (anAttWord==0 || anAttWord[0]=='\0')
       
   290 		return Print(EError, "Missing argument for keyword 'exattrib'.\n");
       
   291 	for (TText *letter=anAttWord;*letter!=0;letter++)
       
   292 		{
       
   293 		switch (*letter)
       
   294 			{
       
   295 		case 'u':
       
   296 			iAttExtra |= (KEntryAttUnique >> 23);	// '1' represents disabled in iAttExtra
       
   297 			break;
       
   298 		case 'U':
       
   299 			iAttExtra &= ~(KEntryAttUnique >> 23);	// '0' represent enabled in iAttExtra
       
   300 			break;
       
   301 		default:
       
   302 			return Print(EError, "Unrecognised exattrib - '%c'.\n", *letter);
       
   303 			break;
       
   304 			}
       
   305 		}
       
   306 
       
   307 	if((~iAttExtra & (KEntryAttUnique >> 23))!=0)	// If the unique file attribute is set
       
   308 		{
       
   309 		if(aKeyword==EKeywordFile || aKeyword==EKeywordData)	// If the Keyword is File or Data
       
   310 			{
       
   311 				if(strlen(aFile->iFileName) > (KMaxFileName-KRofsMangleNameLength)) // check whether we have enough space to add the mangle tage
       
   312 					return Print(EError, "Lengthy filename with unique attribute to name mangle.\n");
       
   313 			}
       
   314 		else	// for all other keywords
       
   315 			return Print(EError, "exattrib field not allowed for entries except data and file.\n");
       
   316 		}
       
   317 	return KErrNone;
       
   318 	}
       
   319 
       
   320 
       
   321 TInt TRomNode::SetAtt(TText *anAttWord)
       
   322 //
       
   323 // Set the file attribute byte from the letters passed
       
   324 //
       
   325 	{
       
   326 	iAtt=0;
       
   327 	if (anAttWord==0 || anAttWord[0]=='\0')
       
   328 		return Print(EError, "Missing argument for keyword 'attrib'.\n");
       
   329 	for (TText *letter=anAttWord;*letter!=0;letter++)
       
   330 		{
       
   331 		switch (*letter)
       
   332 			{
       
   333 		case 'R':
       
   334 		case 'w':
       
   335 			iAtt |= KEntryAttReadOnly;
       
   336 			break;
       
   337 		case 'r':
       
   338 		case 'W':
       
   339 			iAtt &= ~KEntryAttReadOnly;
       
   340 			break;
       
   341 		case 'H':
       
   342 			iAtt |= KEntryAttHidden;
       
   343 			break;
       
   344 		case 'h':
       
   345 			iAtt &= ~KEntryAttHidden;
       
   346 			break;
       
   347 		case 'S':
       
   348 			iAtt |= KEntryAttSystem;
       
   349 			break;
       
   350 		case 's':
       
   351 			iAtt &= ~KEntryAttSystem;
       
   352 			break;
       
   353 		default:
       
   354 			return Print(EError, "Unrecognised attrib - '%c'.\n", *letter);
       
   355 			break;
       
   356 			}
       
   357 		}
       
   358 	return KErrNone;
       
   359 	}
       
   360 
       
   361 
       
   362 
       
   363 TInt TRomNode::CalculateEntrySize() const
       
   364 	// Calculates the amount of ROM space required to hold
       
   365 	// this entry. The return is the actual size of the TRofsEntry
       
   366 	// structure, not rounded up
       
   367 	{
       
   368 	TInt requiredSizeBytes = KRofsEntryHeaderSize +	NameLengthUnicode();
       
   369 	return requiredSizeBytes;
       
   370 	}
       
   371 
       
   372 TInt TRomNode::CalculateDirectoryEntrySize( TInt& aDirectoryBlockSize,
       
   373 										    TInt& aFileBlockSize )
       
   374 	// Calculates the total size of the TRofsDir structure required
       
   375 	// for this directory and the size of the files block. Traverses all the
       
   376 	// children adding their entry sizes. The result is not rounded up.
       
   377 	//
       
   378 	// On return aDirectoryBlockSize is the number of bytes required for the
       
   379 	//	main directory structure. aFileBlockSize is the number of bytes
       
   380 	//	required to hold the list of files.
       
   381 	//
       
   382 	// Returns KErrNone on success
       
   383 	{
       
   384 
       
   385 	TInt offsetBytes=0;
       
   386 	TInt padBytes=0;
       
   387 	if( 0 == iTotalDirectoryBlockSize )
       
   388 		{
       
   389 		// need to calculate by walking children	
       
   390 		if( !iChild )
       
   391 			{
       
   392 			return Print(EError, "TRomNode structure corrupt\n");
       
   393 			}
       
   394 
       
   395 		TInt dirBlockSize = KRofsDirHeaderSize;
       
   396 		TInt fileBlockSize = 0;
       
   397 		TInt fileCount=0;
       
   398 		TInt dirCount=0;
       
   399 
       
   400 		TRomNode* node = iChild;
       
   401 		while (node)
       
   402 			{
       
   403 			TInt entrySize = node->CalculateEntrySize();
       
   404 			if( node->IsDirectory() )
       
   405 				{
       
   406 				dirBlockSize += (4 - dirBlockSize) & 3;	// pad to next word boundary
       
   407 				dirBlockSize += entrySize;
       
   408 				dirCount++;
       
   409 				}
       
   410 			else
       
   411 				{
       
   412 				fileBlockSize += (4 - fileBlockSize) & 3;	// pad to next word boundary
       
   413 				fileBlockSize += entrySize;
       
   414 				fileCount++;
       
   415 				}
       
   416 			node = node->iSibling;
       
   417 			}
       
   418 		
       
   419 		offsetBytes = ((fileCount + dirCount) * 2) + 4; //the +4 are the two offset counts,
       
   420 		padBytes = offsetBytes % 4;
       
   421 
       
   422 		iTotalDirectoryBlockSize = dirBlockSize;
       
   423 		iTotalFileBlockSize = fileBlockSize;
       
   424 		}
       
   425 
       
   426 	aDirectoryBlockSize = iTotalDirectoryBlockSize + offsetBytes + padBytes;
       
   427 	aFileBlockSize = iTotalFileBlockSize;
       
   428 	return KErrNone;
       
   429 	}
       
   430 
       
   431 /**
       
   432 Place the files and it's attributes (incase of executables)
       
   433 Called for both rofs and datadrive creation.
       
   434  
       
   435 @param aDest   - Destination buffer.
       
   436 @param aOffset - offset value, used for rofs only.
       
   437 @param aMaxSize- Maximum size required for rofs.
       
   438   
       
   439 @return - Returns the number of bytes placed or a -ve error code.
       
   440 */ 
       
   441 TInt TRomNode::PlaceFile( TUint8* &aDest, TUint aOffset, TUint aMaxSize, CBytePair *aBPE )
       
   442 	//
       
   443 	// Place the file into the ROM image, making any necessary conversions
       
   444 	// along the way.
       
   445 	//
       
   446 	// Returns the number of bytes placed or a -ve error code.
       
   447 	{
       
   448 
       
   449 	TInt size=0;
       
   450 	
       
   451 	// file hasn't been placed for drive image. 
       
   452 	if(gDriveImage)
       
   453 	{
       
   454 		size = iEntry->PlaceFile(aDest,aMaxSize,aBPE);
       
   455 		iSize = size;
       
   456 	}
       
   457 	else
       
   458 	{
       
   459 		if (iEntry->iHidden)
       
   460 			iFileStartOffset = KFileHidden;
       
   461 		else
       
   462 		{
       
   463                     if (iEntry->iFileOffset==0)
       
   464                     {
       
   465                         // file hasn't been placed
       
   466                         size = iEntry->PlaceFile( aDest, aMaxSize, aBPE );
       
   467                         if (size>=0)
       
   468                             iEntry->iFileOffset = aOffset;
       
   469                     }
       
   470                     else {
       
   471                         iFileStartOffset = (TInt)iEntry;
       
   472                     }
       
   473 		}
       
   474 	}
       
   475 
       
   476 	// Deal with any override attributes
       
   477 	// (omit paging overrides as these are dealt with in TRomBuilderEntry::PlaceFile
       
   478 	//  and may also be legitimately specified for non-executable files in ROM)
       
   479 	if( iOverride&~(KOverrideCodeUnpaged|KOverrideCodePaged|KOverrideDataUnpaged|KOverrideDataPaged) )
       
   480 		{
       
   481 		E32ImageHeaderV* hdr = (E32ImageHeaderV*)aDest;
       
   482 
       
   483 		TUint hdrfmt = hdr->HeaderFormat();
       
   484 		if (hdrfmt != KImageHdrFmt_V)
       
   485 			{
       
   486 			Print(EError,"%s: Can't load old format binary\n", iEntry->iFileName);
       
   487 			return KErrNotSupported;
       
   488 			}
       
   489 		
       
   490 		// First need to check that it's a real image header
       
   491 		if( (TUint)size > sizeof(E32ImageHeader) )
       
   492 			{
       
   493 			if( ((TInt)hdr->iSignature == 0x434f5045u) && ((TInt)hdr->iUid1 == KExecutableImageUidValue || (TInt)hdr->iUid1 == KDynamicLibraryUidValue) )
       
   494 				{
       
   495 				// Should check the CRC as well here...
       
   496 				// Something for later
       
   497 
       
   498 				// Ok, it looks like an image header
       
   499 				if( iOverride & KOverrideStack )
       
   500 					{
       
   501 					hdr->iStackSize = iStackSize;
       
   502 					}
       
   503 				if( iOverride & KOverrideHeapMin )
       
   504 					{
       
   505 					hdr->iHeapSizeMin = iHeapSizeMin;
       
   506 					}
       
   507 				if( iOverride & KOverrideHeapMax )
       
   508 					{
       
   509 					hdr->iHeapSizeMax = iHeapSizeMax;
       
   510 					}
       
   511 				if( iOverride & KOverrideFixed )
       
   512 					{
       
   513 					if( hdr->iFlags & KImageDll )
       
   514 						{
       
   515 						Print(EError,"%s: Can't used FIXED keyword on a DLL\n", iEntry->iFileName);
       
   516 						return KErrNotSupported;
       
   517 						}
       
   518 					hdr->iFlags |= KImageFixedAddressExe;
       
   519 					}
       
   520 				if( iOverride & (KOverrideUid1|KOverrideUid2|KOverrideUid3))
       
   521 					{
       
   522 					if (iOverride & KOverrideUid1)
       
   523 						{
       
   524 						hdr->iUid1 = iUid1;
       
   525 						}
       
   526 					if (iOverride & KOverrideUid2)
       
   527 						{
       
   528 						hdr->iUid2 = iUid2;
       
   529 						}
       
   530 					if (iOverride & KOverrideUid3)
       
   531 						{
       
   532 						hdr->iUid3 = iUid3;
       
   533 						}
       
   534 					// Need to re-checksum the UIDs
       
   535 					TUidType ut(TUidType(TUid::Uid(hdr->iUid1), TUid::Uid(hdr->iUid2), TUid::Uid(hdr->iUid3)));
       
   536 					hdr->iUidChecksum =  (checkSum(((TUint8*)&ut)+1)<<16)|checkSum(&ut);
       
   537 					}
       
   538 				if( iOverride & KOverridePriority )
       
   539 					{
       
   540 					hdr->iProcessPriority = (TUint16)iPriority;
       
   541 					}
       
   542 				if( iOverride & KOverrideCapability )
       
   543 					{
       
   544 					hdr->iS.iCaps = iCapability;
       
   545 					}
       
   546 
       
   547 				// Need to re-CRC the header
       
   548 				hdr->iHeaderCrc = KImageCrcInitialiser;
       
   549 				TUint32 crc = 0;
       
   550 				TInt hdrsz = hdr->TotalSize();
       
   551 				HMem::Crc32(crc, hdr, hdrsz);
       
   552 				hdr->iHeaderCrc = crc;
       
   553 				}
       
   554 			}
       
   555 		}
       
   556 
       
   557 	return size;
       
   558 	}
       
   559 
       
   560 TInt TRomNode::CountFileAndDir(TInt& aFileCount, TInt& aDirCount)
       
   561 	{
       
   562 	//
       
   563 	// Count the number of file and directory entries for this node
       
   564 	//
       
   565 	TRomNode* node = iChild;
       
   566 
       
   567 	aFileCount=0;
       
   568 	aDirCount=0;
       
   569 	while( node )
       
   570 		{
       
   571 		if( node->IsFile() )
       
   572 			{
       
   573 			aFileCount++;
       
   574 			}
       
   575 		else
       
   576 			{
       
   577 			aDirCount++;
       
   578 			}
       
   579 
       
   580 		node = node->iSibling;
       
   581 		}
       
   582 	return KErrNone;
       
   583 	}
       
   584 
       
   585 TInt TRomNode::Place( TUint8* aDestBase )
       
   586 	//
       
   587 	// Writes this directory entry out to the image.
       
   588 	// The image starts at aDestBase.
       
   589 	// The position in the image must already have been set with SetImagePosition()
       
   590 	// and SetFileBlockPosition().
       
   591 	// Returns KErrNone on success
       
   592 	//
       
   593 	{
       
   594 	TUint8* dirBlockBase = aDestBase + iImagePosition;
       
   595 	TUint8* fileBlockBase = aDestBase + iFileBlockPosition;
       
   596 
       
   597 	TRofsDir* pDir = (TRofsDir*)dirBlockBase;
       
   598 	pDir->iFirstEntryOffset = KRofsDirFirstEntryOffset;
       
   599 	pDir->iFileBlockAddress = iFileBlockPosition;
       
   600 	pDir->iFileBlockSize = iTotalFileBlockSize;
       
   601 	pDir->iStructSize = (TUint16)iTotalDirectoryBlockSize;
       
   602 
       
   603 	TRofsEntry* pDirEntry = &(pDir->iSubDir);
       
   604 	TRofsEntry* pFileEntry = (TRofsEntry*)fileBlockBase;
       
   605 
       
   606 	TInt dirCount;
       
   607 	TInt fileCount;
       
   608 	TInt index = 0;
       
   609 	CountFileAndDir(fileCount, dirCount);
       
   610 
       
   611 	SortableEntry* array = new SortableEntry[fileCount + dirCount];
       
   612 	TRomNode* node = iChild;
       
   613 
       
   614 	while( node )
       
   615 		{
       
   616 		TRofsEntry* entry;
       
   617 
       
   618 		if( node->IsFile() )
       
   619 			{
       
   620 			entry = pFileEntry;
       
   621 
       
   622 			//Offset in 32bit words from start of file block
       
   623 			array[index].iOffset = (TUint16) ((((TUint8*) entry) - fileBlockBase) >> 2);
       
   624 			array[index].iIsDir = EFalse;
       
   625 			}
       
   626 		else
       
   627 			{
       
   628 			entry = pDirEntry;
       
   629 
       
   630 			//Offset in 32bit words from start of directory block
       
   631 			array[index].iOffset = (TUint16) ((((TUint8*) entry) - dirBlockBase) >> 2);
       
   632 			array[index].iIsDir = ETrue;
       
   633 			}
       
   634 		array[index].iEntry = entry;
       
   635 		index++;
       
   636 
       
   637 		entry->iNameOffset = KRofsEntryNameOffset;
       
   638 		entry->iAtt = node->iAtt;
       
   639 		entry->iAttExtra = node->iAttExtra;
       
   640 
       
   641 		TInt entryLen = KRofsEntryHeaderSize;
       
   642 		entryLen += node->NameCpy( (char*)&entry->iName, entry->iNameLength );
       
   643 		entryLen += (4 - entryLen) & 3;	// round up to nearest word
       
   644 		entry->iStructSize = (TUint16)entryLen;
       
   645 
       
   646 
       
   647 		if( node->IsFile() )
       
   648 			{
       
   649 			// node is a file, entry points to the file
       
   650 			// write an entry out into the file block
       
   651 			pFileEntry->iFileAddress = node->iFileStartOffset;
       
   652 			node->iAtt &= ~KEntryAttDir;
       
   653 			pFileEntry->iFileSize = node->iEntry->RealFileSize();
       
   654 			memcpy(&pFileEntry->iUids[0], &node->iEntry->iUids[0], sizeof(pFileEntry->iUids));
       
   655 			pFileEntry = (TRofsEntry*)( (TUint8*)pFileEntry + entryLen );
       
   656 			}
       
   657 		else
       
   658 			{
       
   659 			// node is a subdirectory, entry points to directory
       
   660 			pDirEntry->iFileAddress = node->iImagePosition;
       
   661 			node->iAtt |= KEntryAttDir;
       
   662 			
       
   663 			// the size is just the size of the directory block
       
   664 			pDirEntry->iFileSize = node->iTotalDirectoryBlockSize;
       
   665 			pDirEntry = (TRofsEntry*)( (TUint8*)pDirEntry + entryLen );
       
   666 			}
       
   667 
       
   668 		node = node->iSibling;
       
   669 		}
       
   670 
       
   671 	qsort(array,fileCount + dirCount,sizeof(SortableEntry),&compare);
       
   672 
       
   673 	//Now copy the contents of sorted array to the image
       
   674 	TUint16* currentPtr = (TUint16*) (dirBlockBase + iTotalDirectoryBlockSize);
       
   675 
       
   676 	*currentPtr=(TUint16)dirCount;
       
   677 	currentPtr++;
       
   678 	*currentPtr=(TUint16)fileCount;
       
   679 	currentPtr++;
       
   680 
       
   681 	for (index = 0; index < (fileCount + dirCount); index++)
       
   682 		{
       
   683 		*currentPtr = array[index].iOffset;
       
   684 		currentPtr++;
       
   685 		}
       
   686 	delete[] array;
       
   687 	return KErrNone;
       
   688 	}
       
   689 
       
   690 
       
   691 
       
   692 void TRomNode::Remove(TRomNode* aChild)
       
   693 	{
       
   694 	if (iChild==0)
       
   695 		{
       
   696 		Print(EError, "Removing file from a file!!!\n");
       
   697 		return;
       
   698 		}
       
   699 	if (iChild==aChild) // first child in this directory
       
   700 		{
       
   701 		iChild = aChild->iSibling;
       
   702 		aChild->iSibling = 0;
       
   703 		if(iChild==0)
       
   704 			{
       
   705 				iParent->Remove(this);
       
   706 				TRomNode * current = TheFirstNode;
       
   707 				TRomNode * prev = current;
       
   708 				while(current != this)
       
   709 					{
       
   710 						prev = current;
       
   711 						current = current->NextNode();
       
   712 					}
       
   713 				prev->SetNextNode(current->NextNode());
       
   714 				delete this;
       
   715 			}
       
   716 		return;
       
   717 		}
       
   718 	TRomNode* prev = iChild;
       
   719 	while (prev->iSibling && prev->iSibling != aChild)
       
   720 		prev = prev->iSibling;
       
   721 	if (prev==0)
       
   722 		{
       
   723 		Print(EError, "Attempting to remove file not in this directory!!!\n");
       
   724 		return;
       
   725 		}
       
   726 	prev->iSibling = aChild->iSibling;
       
   727 	aChild->iSibling = 0;
       
   728 	}
       
   729 
       
   730 void TRomNode::CountDirectory(TInt& aFileCount, TInt& aDirCount)
       
   731 	{
       
   732 	TRomNode *current=iChild;
       
   733 	while(current)
       
   734 		{
       
   735 		if (current->iChild)
       
   736 			aDirCount++;
       
   737 		else
       
   738  			aFileCount++;
       
   739 	current=current->iSibling;
       
   740 		}
       
   741 	}
       
   742 
       
   743  void TRomNode::Destroy()
       
   744 //
       
   745 // Follow the TRomNode tree, destroying it
       
   746 //
       
   747 	{
       
   748 
       
   749  	TRomNode *current = this; // root has no siblings
       
   750 	while (current)
       
   751 		{
       
   752 		if (current->iChild)
       
   753 			current->iChild->Destroy();
       
   754 		TRomNode* prev=current;
       
   755 		current=current->iSibling;
       
   756 		delete prev;
       
   757         prev = 0;
       
   758 		}
       
   759  	}
       
   760 
       
   761 
       
   762 
       
   763 
       
   764 TInt TRomNode::NameCpy(char* aDest, TUint8& aUnicodeLength )
       
   765 //
       
   766 // Safely copy a file name in the rom entry
       
   767 // Returns the number of bytes used. Write the length in unicode characters
       
   768 // into aUnicodeLength.
       
   769 //
       
   770 	{
       
   771 
       
   772 	if ((aDest==NULL) || (iName==NULL))
       
   773 		return 0;
       
   774 	const unsigned char* pSourceByte = (const unsigned char*)iName;
       
   775 	unsigned char* pTargetByte=(unsigned char*)aDest;
       
   776 	for (;;)
       
   777 		{
       
   778 		const TUint sourceByte=*pSourceByte;
       
   779 		if (sourceByte==0)
       
   780 			{
       
   781 			break;
       
   782 			}
       
   783 		if ((sourceByte&0x80)==0)
       
   784 			{
       
   785 			*pTargetByte=(unsigned char)sourceByte;
       
   786 			++pTargetByte;
       
   787 			*pTargetByte=0;
       
   788 			++pTargetByte;
       
   789 			++pSourceByte;
       
   790 			}
       
   791 		else if ((sourceByte&0xe0)==0xc0)
       
   792 			{
       
   793 			++pSourceByte;
       
   794 			const TUint secondSourceByte=*pSourceByte;
       
   795 			if ((secondSourceByte&0xc0)!=0x80)
       
   796 				{
       
   797 				Print(EError, "Bad UTF-8 '%s'", iName);
       
   798 				exit(671);
       
   799 				}
       
   800 			*pTargetByte=(unsigned char)((secondSourceByte&0x3f)|((sourceByte&0x03)<<6));
       
   801 			++pTargetByte;
       
   802 			*pTargetByte=(unsigned char)((sourceByte>>2)&0x07);
       
   803 			++pTargetByte;
       
   804 			++pSourceByte;
       
   805 			}
       
   806 		else if ((sourceByte&0xf0)==0xe0)
       
   807 			{
       
   808 			++pSourceByte;
       
   809 			const TUint secondSourceByte=*pSourceByte;
       
   810 			if ((secondSourceByte&0xc0)!=0x80)
       
   811 				{
       
   812 				Print(EError, "Bad UTF-8 '%s'", iName);
       
   813 				exit(672);
       
   814 				}
       
   815 			++pSourceByte;
       
   816 			const TUint thirdSourceByte=*pSourceByte;
       
   817 			if ((thirdSourceByte&0xc0)!=0x80)
       
   818 				{
       
   819 				Print(EError, "Bad UTF-8 '%s'", iName);
       
   820 				exit(673);
       
   821 				}
       
   822 			*pTargetByte=(unsigned char)((thirdSourceByte&0x3f)|((secondSourceByte&0x03)<<6));
       
   823 			++pTargetByte;
       
   824 			*pTargetByte=(unsigned char)(((secondSourceByte>>2)&0x0f)|((sourceByte&0x0f)<<4));
       
   825 			++pTargetByte;
       
   826 			++pSourceByte;
       
   827 			}
       
   828 		else
       
   829 			{
       
   830 			Print(EError, "Bad UTF-8 '%s'", iName);
       
   831 			exit(674);
       
   832 			}
       
   833 		}
       
   834 	const TInt numberOfBytesInTarget=(pTargetByte-(unsigned char*)aDest); // this number excludes the trailing null-terminator
       
   835 	if (numberOfBytesInTarget%2!=0)
       
   836 		{
       
   837 		Print(EError, "Internal error");
       
   838 		exit(675);
       
   839 		}
       
   840 	aUnicodeLength = (TUint8)(numberOfBytesInTarget/2); // returns the length of aDest (in UTF-16 characters for Unicode, not bytes)
       
   841 	return numberOfBytesInTarget;
       
   842 	}
       
   843 
       
   844 
       
   845 TInt TRomNode::NameLengthUnicode() const
       
   846 //
       
   847 // Find the unicode lenght of the name
       
   848 //
       
   849 	{
       
   850 
       
   851 	if (iName==NULL)
       
   852 		return 0;
       
   853 
       
   854 	const unsigned char* pSourceByte = (const unsigned char*)iName;
       
   855 	TInt len = 0;
       
   856 	for (;;)
       
   857 		{
       
   858 		const TUint sourceByte=*pSourceByte;
       
   859 		if (sourceByte==0)
       
   860 			{
       
   861 			break;
       
   862 			}
       
   863 		if ((sourceByte&0x80)==0)
       
   864 			{
       
   865 			len += 2;
       
   866 			++pSourceByte;
       
   867 			}
       
   868 		else if ((sourceByte&0xe0)==0xc0)
       
   869 			{
       
   870 			++pSourceByte;
       
   871 			const TUint secondSourceByte=*pSourceByte;
       
   872 			if ((secondSourceByte&0xc0)!=0x80)
       
   873 				{
       
   874 				Print(EError, "Bad UTF-8 '%s'", iName);
       
   875 				exit(671);
       
   876 				}
       
   877 			len += 2;
       
   878 			++pSourceByte;
       
   879 			}
       
   880 		else if ((sourceByte&0xf0)==0xe0)
       
   881 			{
       
   882 			++pSourceByte;
       
   883 			const TUint secondSourceByte=*pSourceByte;
       
   884 			if ((secondSourceByte&0xc0)!=0x80)
       
   885 				{
       
   886 				Print(EError, "Bad UTF-8 '%s'", iName);
       
   887 				exit(672);
       
   888 				}
       
   889 			++pSourceByte;
       
   890 			const TUint thirdSourceByte=*pSourceByte;
       
   891 			if ((thirdSourceByte&0xc0)!=0x80)
       
   892 				{
       
   893 				Print(EError, "Bad UTF-8 '%s'", iName);
       
   894 				exit(673);
       
   895 				}
       
   896 			len += 2;
       
   897 			++pSourceByte;
       
   898 			}
       
   899 		else
       
   900 			{
       
   901 			Print(EError, "Bad UTF-8 '%s'", iName);
       
   902 			exit(674);
       
   903 			}
       
   904 		}
       
   905 	return len;
       
   906 	}
       
   907 
       
   908 
       
   909 void TRomNode::AddNodeForSameFile(TRomNode* aPreviousNode, TRomBuilderEntry* aFile)
       
   910 	{
       
   911 	// sanity checking
       
   912 	if (iNextNodeForSameFile != 0 || iEntry != aFile || (aPreviousNode && aPreviousNode->iEntry != iEntry))
       
   913 		{
       
   914 		Print(EError, "Adding Node for same file: TRomNode structure corrupted\n");
       
   915 		exit(666);
       
   916 		}
       
   917 	iNextNodeForSameFile = aPreviousNode;
       
   918 	}
       
   919 
       
   920 
       
   921 
       
   922 
       
   923 
       
   924 //**************************************
       
   925 // TRomBuilderEntry
       
   926 //**************************************
       
   927 
       
   928 
       
   929 
       
   930 TRomBuilderEntry::TRomBuilderEntry(const char *aFileName,TText *aName)
       
   931 //
       
   932 // Constructor
       
   933 //
       
   934 :iFirstDllDataEntry(0),	iName(0),iFileName(0),iNext(0), iNextInArea(0),
       
   935 iExecutable(EFalse), iFileOffset(EFalse), iCompressEnabled(0),
       
   936 iHidden(0), iRomNode(0), iRealFileSize(0)		 
       
   937 {
       
   938 	if (aFileName)
       
   939    		iFileName = NormaliseFileName(aFileName);
       
   940 	if (aName)
       
   941 		iName = (TText*)NormaliseFileName((const char*)aName);
       
   942 	memset(iUids,0 ,sizeof(TCheckedUid));
       
   943 }
       
   944 	
       
   945 TRomBuilderEntry::~TRomBuilderEntry()
       
   946 //
       
   947 // Destructor
       
   948 //
       
   949 	{
       
   950 	if(iFileName)
       
   951 	{
       
   952 	free(iFileName);
       
   953 	}
       
   954 	iFileName = 0;
       
   955 	if(iName)
       
   956 	{
       
   957 	free(iName);
       
   958 	}
       
   959 	}
       
   960 
       
   961 void TRomBuilderEntry::SetRomNode(TRomNode* aNode)
       
   962 	{
       
   963 	aNode->AddNodeForSameFile(iRomNode, this);
       
   964 	iRomNode = aNode;
       
   965 	}
       
   966 
       
   967 
       
   968 TInt isNumber(TText *aString)
       
   969 	{
       
   970 	if (aString==NULL)
       
   971 		return 0;
       
   972 	if (strlen((char *)aString)==0)
       
   973 		return 0;
       
   974 	return isdigit(aString[0]);
       
   975 	}
       
   976 
       
   977 TInt getNumber(TText *aStr)
       
   978 	{
       
   979 	TUint a;
       
   980 	#ifdef __TOOLS2__
       
   981 	istringstream val((char *)aStr);
       
   982 	#else
       
   983 	istrstream val((char *)aStr,strlen((char *)aStr));
       
   984 	#endif
       
   985 
       
   986 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
   987 	val >> setbase(0);
       
   988 #endif //__MSVCDOTNET__
       
   989 
       
   990 	val >> a;
       
   991 	return a;
       
   992 	}
       
   993 
       
   994 
       
   995 TInt TRomBuilderEntry::PlaceFile( TUint8* &aDest,TUint aMaxSize, CBytePair *aBPE )
       
   996 	//
       
   997 	// Place the file in ROM. Since we don't support compression yet all
       
   998 	// we have to do is read the file into memory
       
   999 	// compress it, if it isn't already compressed.
       
  1000 	//
       
  1001 	// Returns the number of bytes used, or -ve error code
       
  1002 	{
       
  1003 	TUint compression = 0;
       
  1004 	TBool executable = iExecutable;
       
  1005 	Print(ELog,"Reading file %s to image\n", iFileName );
       
  1006 	TUint32 size=HFile::GetLength((TText*)iFileName);
       
  1007 	if (size==0)
       
  1008 		Print(EWarning, "File %s does not exist or is 0 bytes in length.\n",iFileName);
       
  1009         if (aDest == NULL) {
       
  1010             aMaxSize = size*2;
       
  1011             aMaxSize = (aMaxSize>0) ? aMaxSize : 2;
       
  1012             aDest = new TUint8[aMaxSize];
       
  1013         }
       
  1014 
       
  1015 	if (executable)
       
  1016 		{
       
  1017 		// indicate if the image will overflow without compression
       
  1018 	TBool overflow;
       
  1019 			if(size>aMaxSize)
       
  1020 			overflow = ETrue;
       
  1021 		else
       
  1022 			overflow = EFalse;
       
  1023 
       
  1024 		// try to compress this executable
       
  1025 		E32ImageFile f(aBPE);
       
  1026 		TInt r = f.Open(iFileName);
       
  1027 		// is it really a valid E32ImageFile?
       
  1028 		if (r != KErrNone)
       
  1029 			{
       
  1030 			Print(EWarning, "File '%s' is not a valid executable.  Placing file as data.\n", iFileName);
       
  1031 			executable = EFalse;
       
  1032 			}
       
  1033 		else
       
  1034 			{
       
  1035 
       
  1036 			if(iRomNode->iOverride & KOverrideDllData)
       
  1037 			{
       
  1038 				DllDataEntry *aDllEntry = iRomNode->iEntry->GetFirstDllDataEntry();
       
  1039 				TLinAddr* aExportTbl;
       
  1040 				void *aLocation;
       
  1041 				TUint aDataAddr;
       
  1042 				char *aCodeSeg, *aDataSeg;
       
  1043 
       
  1044 				aExportTbl = (TLinAddr*)((char*)f.iData + f.iOrigHdr->iExportDirOffset);
       
  1045 
       
  1046 				// const data symbol may belong in the Code section. If the address lies within the Code or data section limits, 
       
  1047 				// get the corresponding location and update it.While considering the Data section limits
       
  1048 				// don't include the Bss section, as it doesn't exist as yet in the image.
       
  1049 				while( aDllEntry ){
       
  1050 					if(aDllEntry->iOrdinal != (TUint32)-1){
       
  1051 						if(aDllEntry->iOrdinal < 1 || aDllEntry->iOrdinal > (TUint)f.iOrigHdr->iExportDirCount){
       
  1052 							Print(EWarning, "Invalid ordinal %d specified for DLL %s\n", aDllEntry->iOrdinal, iRomNode->iName);
       
  1053 							aDllEntry = aDllEntry->NextDllDataEntry();
       
  1054 							continue;
       
  1055 						}
       
  1056 					
       
  1057 				//	Get the address of the data field via the export table.
       
  1058 					aDataAddr = (TInt32)(aExportTbl[aDllEntry->iOrdinal - 1] + aDllEntry->iOffset);
       
  1059 					if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){
       
  1060 						aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset);
       
  1061 						aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase );
       
  1062 						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
       
  1063 					}
       
  1064 					else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){
       
  1065 						aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset);
       
  1066 						aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase );
       
  1067 						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
       
  1068 					}
       
  1069 					else
       
  1070 					{
       
  1071 						Print(EWarning, "Patchdata failed as address pointed by ordinal %d of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName);
       
  1072 					}
       
  1073 					}
       
  1074 					else if(aDllEntry->iDataAddress != (TLinAddr)-1){
       
  1075 						aDataAddr = aDllEntry->iDataAddress + aDllEntry->iOffset;
       
  1076 					if( aDataAddr >= f.iOrigHdr->iCodeBase && aDataAddr <= (f.iOrigHdr->iCodeBase + f.iOrigHdr->iCodeSize)){
       
  1077 						aCodeSeg = (char*)(f.iData + f.iOrigHdr->iCodeOffset);
       
  1078 						aLocation = (void*)(aCodeSeg + aDataAddr - f.iOrigHdr->iCodeBase );
       
  1079 						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
       
  1080 					}
       
  1081 					else if(aDataAddr >= f.iOrigHdr->iDataBase && aDataAddr <= (f.iOrigHdr->iDataBase + f.iOrigHdr->iDataSize)){
       
  1082 						aDataSeg = (char*)(f.iData + f.iOrigHdr->iDataOffset);
       
  1083 						aLocation = (void*)(aDataSeg + aDataAddr - f.iOrigHdr->iDataBase );
       
  1084 						memcpy(aLocation, &aDllEntry->iNewValue, aDllEntry->iSize);
       
  1085 					}
       
  1086 					else
       
  1087 					{
       
  1088 						Print(EWarning, "Patchdata failed as address 0x%x of DLL %s doesn't lie within Code or Data section limits\n", aDllEntry->iOrdinal, iRomNode->iName);
       
  1089 					}
       
  1090 					}
       
  1091 					aDllEntry = aDllEntry->NextDllDataEntry();
       
  1092 					}
       
  1093 			}
       
  1094 
       
  1095 			compression = f.iHdr->CompressionType();
       
  1096 			Print(ELog,"Original file:'%s' is compressed by method:%08x\n", iFileName, compression);
       
  1097 
       
  1098 
       
  1099 			TUint32 oldFileComp;
       
  1100 			TUint32 newFileComp;
       
  1101 
       
  1102 			if(compression)
       
  1103 			{
       
  1104 				// The E32 image in release directory is compressed
       
  1105 				oldFileComp = compression;
       
  1106 			}
       
  1107 			else
       
  1108 			{
       
  1109 				// The E32 image in release directory is uncompressed
       
  1110 				oldFileComp = 0;
       
  1111 			}
       
  1112 
       
  1113 			if( iCompressEnabled != ECompressionUnknown)
       
  1114 			{
       
  1115 				// The new state would be as stated in obey file, i.e. 
       
  1116 				// filecompress or fileuncompress
       
  1117 				newFileComp = gCompressionMethod;
       
  1118 			}
       
  1119 			else if (gCompress != ECompressionUnknown)
       
  1120 			{
       
  1121 				// The new state would be as stated set globally
       
  1122 				newFileComp = gCompressionMethod;
       
  1123 			}
       
  1124 			else
       
  1125 			{
       
  1126 				// When not known if compression is to be applied or not,
       
  1127 				// set it same as that of the E32 image in release directory
       
  1128 				newFileComp = oldFileComp;
       
  1129 			}
       
  1130 
       
  1131 			if(!gDriveImage)
       
  1132 			{
       
  1133 				// overide paging flags...
       
  1134 				E32ImageHeaderV* h=f.iHdr;
       
  1135 				if (iRomNode->iOverride & KOverrideCodePaged)
       
  1136 					{
       
  1137 					h->iFlags &= ~KImageCodeUnpaged;
       
  1138 					h->iFlags |= KImageCodePaged;
       
  1139 					}
       
  1140 				if (iRomNode->iOverride & KOverrideCodeUnpaged)
       
  1141 					{
       
  1142 					h->iFlags |= KImageCodeUnpaged;
       
  1143 					h->iFlags &= ~KImageCodePaged;
       
  1144 					}
       
  1145 				if (iRomNode->iOverride & KOverrideDataPaged)
       
  1146 					{
       
  1147 					h->iFlags &= ~KImageDataUnpaged;
       
  1148 					h->iFlags |= KImageDataPaged;
       
  1149 					}
       
  1150 				if (iRomNode->iOverride & KOverrideDataUnpaged)
       
  1151 					{
       
  1152 					h->iFlags |= KImageDataUnpaged;
       
  1153 					h->iFlags &= ~KImageDataPaged;
       
  1154 					}
       
  1155 
       
  1156 				// apply global paging override...
       
  1157 				switch(gCodePagingOverride)
       
  1158 					{
       
  1159 				case EKernelConfigPagingPolicyNoPaging:
       
  1160 					h->iFlags |= KImageCodeUnpaged;
       
  1161 					h->iFlags &= ~KImageCodePaged;
       
  1162 					break;
       
  1163 				case EKernelConfigPagingPolicyAlwaysPage:
       
  1164 					h->iFlags |= KImageCodePaged;
       
  1165 					h->iFlags &= ~KImageCodeUnpaged;
       
  1166 					break;
       
  1167 				case EKernelConfigPagingPolicyDefaultUnpaged:
       
  1168 					if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
       
  1169 						h->iFlags |= KImageCodeUnpaged;
       
  1170 					break;
       
  1171 				case EKernelConfigPagingPolicyDefaultPaged:
       
  1172 					if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
       
  1173 						h->iFlags |= KImageCodePaged;
       
  1174 					break;
       
  1175 					}
       
  1176 				switch(gDataPagingOverride)
       
  1177 					{
       
  1178 				case EKernelConfigPagingPolicyNoPaging:
       
  1179 					h->iFlags |= KImageDataUnpaged;
       
  1180 					h->iFlags &= ~KImageDataPaged;
       
  1181 					break;
       
  1182 				case EKernelConfigPagingPolicyAlwaysPage:
       
  1183 					h->iFlags |= KImageDataPaged;
       
  1184 					h->iFlags &= ~KImageDataUnpaged;
       
  1185 					break;
       
  1186 				case EKernelConfigPagingPolicyDefaultUnpaged:
       
  1187 					if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
       
  1188 						h->iFlags |= KImageDataUnpaged;
       
  1189 					break;
       
  1190 				case EKernelConfigPagingPolicyDefaultPaged:
       
  1191 					if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
       
  1192 						h->iFlags |= KImageDataPaged;
       
  1193 					break;
       
  1194 					}
       
  1195 				f.UpdateHeaderCrc();
       
  1196 
       
  1197 				// make sure paged code has correct compression type...
       
  1198 				if(h->iFlags&KImageCodePaged)
       
  1199 					{
       
  1200 					if(newFileComp!=0)
       
  1201 						newFileComp = KUidCompressionBytePair;
       
  1202 					}
       
  1203 			}
       
  1204 
       
  1205 			if ( oldFileComp != newFileComp )
       
  1206 				{
       
  1207 				
       
  1208 				if( newFileComp == 0)
       
  1209 					{
       
  1210 					Print(ELog,"Decompressing executable '%s'\n", iFileName);
       
  1211 					f.iHdr->iCompressionType = 0;
       
  1212 					}
       
  1213 				else
       
  1214 					{
       
  1215 					Print(ELog,"Compressing executable '%s' with method:%08x\n", iFileName, newFileComp);
       
  1216 					f.iHdr->iCompressionType = newFileComp;
       
  1217 					}
       
  1218 				f.UpdateHeaderCrc();
       
  1219 				if (overflow)
       
  1220 					{
       
  1221 					ostringstream os(ios_base::out|ios_base::binary);
       
  1222 					os << f;
       
  1223 					TUint compressedSize = os.str().size();
       
  1224 					if (compressedSize <= aMaxSize)
       
  1225 						overflow = EFalse;	
       
  1226 					}
       
  1227 				}
       
  1228 			if (overflow)
       
  1229 				{
       
  1230 				Print(EError, "Can't fit '%s' in image\n", iFileName);
       
  1231 				Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize);
       
  1232 				exit(667);
       
  1233 				}
       
  1234   			ostringstream os(ios_base::out|ios_base::binary);
       
  1235 			os << f;
       
  1236 			size = os.str().size();
       
  1237 			compression = f.iHdr->CompressionType();
       
  1238 			memcpy(&iUids[0], aDest, sizeof(iUids));
       
  1239 			}
       
  1240 		}
       
  1241 	if (!executable)
       
  1242 		{
       
  1243 		if ( size > aMaxSize )
       
  1244 			{
       
  1245 			Print(EError, "Can't fit '%s' in image\n", iFileName);
       
  1246 			Print(EError, "Overflowed by approximately 0x%x bytes.\n", size - aMaxSize);
       
  1247 			exit(667);
       
  1248 			}
       
  1249 		size = HFile::Read((TText*)iFileName, (TAny *)aDest);
       
  1250                 TUint32 Uidslen = (size > sizeof(iUids)) ? sizeof(iUids) : size;
       
  1251                 memcpy(&iUids[0], aDest, Uidslen);
       
  1252 		}
       
  1253 
       
  1254 	if (compression)
       
  1255 		Print(ELog,"Compressed executable File '%s' size: %08x, mode:%08x\n", iFileName, size, compression);
       
  1256 	else if (iExecutable)
       
  1257 		Print(ELog,"Executable File '%s' size: %08x\n", iFileName, size);
       
  1258 	else
       
  1259 		Print(ELog,"File '%s' size: %08x\n", iFileName, size);
       
  1260 	iRealFileSize = size;	// required later when directory is written
       
  1261 	
       
  1262 	return size;
       
  1263 	}
       
  1264 
       
  1265 
       
  1266 TRomNode* TRomNode::CopyDirectory(TRomNode*& aLastExecutable)
       
  1267 	{
       
  1268 
       
  1269 	if (iHidden && iChild==0)
       
  1270 		{
       
  1271 		// Hidden file - do not copy (as it wouldn't be visible in the ROM filestructure)
       
  1272 		if (iSibling)
       
  1273 			return iSibling->CopyDirectory(aLastExecutable);
       
  1274 		else
       
  1275 			return 0;
       
  1276 		}
       
  1277 
       
  1278 	TRomNode* copy = new TRomNode(iName);
       
  1279 	if(aLastExecutable==0)
       
  1280 		aLastExecutable = copy;		// this must be the root of the structure
       
  1281 	// recursively copy the sub-structures
       
  1282 	if (iChild)
       
  1283 		copy->iChild = iChild->CopyDirectory(aLastExecutable);
       
  1284 	if (iSibling)
       
  1285 		copy->iSibling = iSibling->CopyDirectory(aLastExecutable);
       
  1286 	copy->Clone(this);
       
  1287 	return copy;
       
  1288 	}
       
  1289 
       
  1290 
       
  1291 
       
  1292 
       
  1293 void TRomNode::Clone(TRomNode* aOriginal)
       
  1294 	{
       
  1295 	iAtt = aOriginal->iAtt;
       
  1296 	iAttExtra = aOriginal->iAttExtra;
       
  1297 	iEntry = aOriginal->iEntry;
       
  1298 	iHidden = aOriginal->iHidden;
       
  1299 	iFileStartOffset = aOriginal->iFileStartOffset;
       
  1300 	iSize = aOriginal->iSize;
       
  1301 	iParent = aOriginal->iParent;
       
  1302     iAlias = aOriginal->iAlias;
       
  1303 	}
       
  1304 
       
  1305 
       
  1306 void TRomNode::Alias(TRomNode* aNode)
       
  1307 	{
       
  1308 	  // sanity checking
       
  1309 	if (aNode->iEntry == 0) 
       
  1310 	{
       
  1311 		Print(EError, "Aliasing: TRomNode structure corrupted\n");
       
  1312 		exit(666);
       
  1313 	}
       
  1314 	Clone(aNode);
       
  1315 	iEntry = aNode->iEntry;
       
  1316 	if (iEntry)
       
  1317 		{
       
  1318 		iEntry->SetRomNode(this);
       
  1319 		}
       
  1320     iAlias = true;
       
  1321 	}
       
  1322 
       
  1323 
       
  1324 void TRomNode::Rename(TRomNode *aOldParent, TRomNode* aNewParent, TText* aNewName)
       
  1325 	{
       
  1326 	aOldParent->Remove(this);
       
  1327 	aNewParent->Add(this);
       
  1328 	delete [] iName;
       
  1329 	iName = new TText[strlen((const char *)aNewName)+1];
       
  1330 	strcpy ((char *)iName, (const char *)aNewName);
       
  1331 	}
       
  1332 
       
  1333 TInt TRomNode::FullNameLength(TBool aIgnoreHiddenAttrib) const
       
  1334 	{
       
  1335 	TInt l = 0;
       
  1336 	// aIgnoreHiddenAttrib is used to find the complete file name length as 
       
  1337 	// in ROM of a hidden file.
       
  1338 	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
       
  1339 		l = iParent->FullNameLength() + 1;
       
  1340 	l += strlen((const char*)iName);
       
  1341 	return l;
       
  1342 	}
       
  1343 
       
  1344 TInt TRomNode::GetFullName(char* aBuf, TBool aIgnoreHiddenAttrib) const
       
  1345 	{
       
  1346 	TInt l = 0;
       
  1347 	TInt nl = strlen((const char*)iName);
       
  1348 	// aIgnoreHiddenAttrib is used to find the complete file name as in ROM of a hidden file.
       
  1349 	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
       
  1350 		l = iParent->GetFullName(aBuf);
       
  1351 	char* b = aBuf + l;
       
  1352 	if (l)
       
  1353 		*b++ = '\\', ++l;
       
  1354 	memcpy(b, iName, nl);
       
  1355 	b += nl;
       
  1356 	*b = 0;
       
  1357 	l += nl;
       
  1358 	return l;
       
  1359 	}
       
  1360 
       
  1361 // Fuction to return first node in the patchdata linked list
       
  1362 DllDataEntry *TRomBuilderEntry::GetFirstDllDataEntry() const
       
  1363 {
       
  1364 	if (iFirstDllDataEntry)
       
  1365 	{
       
  1366 		return iFirstDllDataEntry;
       
  1367 	}
       
  1368 	else
       
  1369 	{
       
  1370 		return NULL;
       
  1371 	}
       
  1372 }
       
  1373 
       
  1374 // Fuction to set first node in the patchdata linked list
       
  1375 void TRomBuilderEntry::SetFirstDllDataEntry(DllDataEntry *aDllDataEntry)
       
  1376 {
       
  1377 	iFirstDllDataEntry = aDllDataEntry;	
       
  1378 }
       
  1379 void TRomBuilderEntry::DisplaySize(TPrintType aWhere)
       
  1380 {
       
  1381 	TBool aIgnoreHiddenAttrib = ETrue;
       
  1382 	TInt aLen = iRomNode->FullNameLength(aIgnoreHiddenAttrib);
       
  1383 	char *aBuf = new char[aLen+1];
       
  1384 	if(gLogLevel & LOG_LEVEL_FILE_DETAILS)
       
  1385 		{
       
  1386 		iRomNode->GetFullName(aBuf, aIgnoreHiddenAttrib);
       
  1387 		if(iFileName)
       
  1388 			Print(aWhere, "%s\t%d\t%s\t%s\n", iFileName, RealFileSize(), (iRomNode->iHidden || iHidden)?"hidden":"", aBuf);
       
  1389 		else
       
  1390 			Print(aWhere, "%s\t%s\n", (iRomNode->iHidden || iHidden)?"hidden":"", aBuf);
       
  1391 		}
       
  1392 	else
       
  1393 		{
       
  1394 		if(iFileName)
       
  1395 			Print(aWhere, "%s\t%d\n", iFileName, RealFileSize());
       
  1396 		}
       
  1397 
       
  1398 }