imgtools/romtools/rombuild/r_obey.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     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 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <string.h>
       
    20 
       
    21 #ifdef __VC32__
       
    22  #ifdef __MSVCDOTNET__
       
    23   #include <strstream>
       
    24   #include <iomanip>
       
    25  #else //!__MSVCDOTNET__
       
    26   #include <strstrea.h>
       
    27   #include <iomanip.h>
       
    28  #endif //__MSVCDOTNET__
       
    29 #else //!__VC32__
       
    30 #ifdef __TOOLS2__
       
    31  #include <sstream>
       
    32   #include <iomanip>
       
    33 #else
       
    34  #include <strstream.h>
       
    35  #include <iomanip.h>
       
    36 #endif 
       
    37 #endif //__VC32__
       
    38 
       
    39 #include <stdlib.h>
       
    40 #include <stdio.h>
       
    41 #include <time.h>
       
    42 #include <assert.h>
       
    43 
       
    44 #include "e32std.h"
       
    45 #include "e32std_private.h"
       
    46 #include "e32rom.h"
       
    47 #include "u32std.h"
       
    48 
       
    49 #include "r_rom.h"
       
    50 #include "r_obey.h"
       
    51 #include "r_global.h"
       
    52 #include "h_utl.h"
       
    53 #include "patchdataprocessor.h"
       
    54 #include "r_coreimage.h"
       
    55 
       
    56 #define _P(word)	word, sizeof(word)-1	// match prefix, optionally followed by [HWVD]
       
    57 #define _K(word)	word, 0					// match whole word
       
    58 
       
    59 const ObeyFileKeyword ObeyFileReader::iKeywords[] =
       
    60 {
       
    61 	{_P("file"),		2,-2, EKeywordFile, "Executable file to be loaded into the ROM"},
       
    62 	{_P("data"),		2,-2, EKeywordData, "Data file to be copied into the ROM"},
       
    63 	{_P("primary"),		1+2,-2, EKeywordPrimary, "An EPOC Kernel"},
       
    64 	{_P("secondary"),	2,-2, EKeywordSecondary, "?"},
       
    65 	{_P("variant"),		1+2,-2, EKeywordVariant, "?"},
       
    66 	{_P("extension"),	1+2,-2, EKeywordExtension, "Kernel extension loaded before the secondary"},
       
    67 	{_P("device"),		1+2,-2, EKeywordDevice, "Kernel extension loaded from the ROM file system"},
       
    68 	{_P("dll"),			2,-2, EKeywordDll, "Executable file whose entry point must be called"},
       
    69 	{_P("filecompress"),	2,-2, EKeywordFileCompress, "Non-XIP Executable to be loaded into the ROM compressed"},
       
    70 	{_P("fileuncompress"),	2,-2, EKeywordFileUncompress, "Non-XIP Executable to be loaded into the ROM uncompressed"},
       
    71 	{_K("area"),	    1, 3, EKeywordArea, "Declare a relocation area"},
       
    72 	{_K("align"),	    2, 1, EKeywordAlign, "Override default alignment for following file"},
       
    73 	{_P("hide"),	    2, -1, EKeywordHide, "Exclude named file from ROM directory structure"},
       
    74 	{_P("alias"),	    2, -2, EKeywordAlias, "Create alias for existing file in ROM directory structure"},
       
    75 	{_P("rename"),	    2, -2, EKeywordRename, "Change the name of a file in the ROM directory structure"},
       
    76 	{_K("singlekernel"),1, 0, EKeywordSingleKernel, "Single Kernel"},
       
    77 	{_K("multikernel"),	1, 0, EKeywordMultiKernel, "Multiple Kernels"},
       
    78 	{_K("bootbinary"),	1, 1, EKeywordBootBinary, "file containing the bootstrap"},
       
    79 	{_K("romname"),		1, 1, EKeywordRomName, "output file for ROM image"},
       
    80 	{_K("romsize"),		1, 1, EKeywordRomSize, "size of ROM image"},
       
    81 	{_K("romlinearbase"),	1, 1, EKeywordRomLinearBase, "linear address of ROM image"},
       
    82 	{_K("romalign"),	1, 1, EKeywordRomAlign, "default alignment of files in ROM image"},
       
    83 	{_K("romchecksum"),	1, 1, EKeywordRomChecksum, "desired 32-bit checksum value for the whole ROM image"},
       
    84 	{_K("kerneldataaddress"),	1, 1, EKeywordKernelDataAddress, "?"},
       
    85 	{_K("kernelheapmin"),	1, 1, EKeywordKernelHeapMin, "Inital size of the kernel heap"},
       
    86 	{_K("kernelheapmax"),	1, 1, EKeywordKernelHeapMax, "Maximum size of the kernel heap"},
       
    87 	{_K("dataaddress"),	1, 1, EKeywordDataAddress, "?"},
       
    88 	{_K("defaultstackreserve"),	1, 1, EKeywordDefaultStackReserve, "?"},
       
    89 	{_K("version"),		1, 1, EKeywordVersion, "ROM version number"},
       
    90 	{_K("romnameodd"),	1, 1, EKeywordRomNameOdd, "output file containing odd halfwords of ROM image"},
       
    91 	{_K("romnameeven"),	1, 1, EKeywordRomNameEven, "output file containing even halfwords of ROM image"},
       
    92 	{_K("srecordfilename"),	1, 1, EKeywordSRecordFileName, "output file containing ROM image in S-Record format"},
       
    93 	{_K("srecordbase"),	1, 1, EKeywordSRecordBase, "Destination address for S-Record download"},
       
    94 	{_K("kerneltrace"),	1, -1, EKeywordKernelTrace, "Initial value for Kernel tracing flags"},
       
    95 	{_K("btrace"),	1, -1, EKeywordBTrace, "Initial value for fast-trace filter"},
       
    96 	{_K("btracemode"),	1, 1, EKeywordBTraceMode, "Initial value for fast-trace mode"},
       
    97 	{_K("btracebuffer"),	1, 1, EKeywordBTraceBuffer, "Initial size for fast-trace buffer"},
       
    98 	{_K("collapse"),	1, 3, EKeywordCollapse, "Additional ROM optimisations"},
       
    99 	{_K("time"),	    1,-1, EKeywordTime, "ROM timestamp"},
       
   100 	{_K("section"),	    2, 1, EKeywordSection, "Start of replaceable section in old-style 2 section ROM"},
       
   101 	{_K("extensionrom"),1+2, 1, EKeywordExtensionRom, "Start of definition of optional Extension ROM"},
       
   102 	{_K("kernelromname"),1, 1, EKeywordKernelRomName, "ROM image on which extension ROM is based"},
       
   103 	{_K("files"),		0, 0, EKeywordNone, 0},	// backwards compatibility, but now ignored
       
   104 	{_K("rem"),			0, 0, EKeywordNone, "comment"},
       
   105 	{_K("stop"),		0, 0, EKeywordNone, "Terminates OBEY file prematurely"},
       
   106 	{_K("dlldatatop"),	1, 1, EKeywordDllDataTop, "Specify top of DLL data region"},
       
   107 	{_K("memmodel"),	1, -1, EKeywordMemModel, "Specifies the memory model to be used at runtime"},
       
   108 	{_K("nowrapper"),	1, 0, EKeywordNoWrapper, "Specifies that no ROM wrapper is required"},
       
   109 	{_K("epocwrapper"),	1, 0, EKeywordEpocWrapper, "Specifies that an EPOC ROM wrapper is required"},
       
   110 	{_K("coffwrapper"),	1, 0, EKeywordCoffWrapper, "Specifies that a COFF ROM wrapper is required"},
       
   111 	{_K("platsecenforcement"),	1, 1, EKeywordPlatSecEnforcement, "Set Platform Security enforment on/off"},
       
   112 	{_K("platsecdiagnostics"),	1, 1, EKeywordPlatSecDiagnostics, "Set Platform Security diagnostics on/off"},
       
   113 	{_K("platsecprocessisolation"), 1, 1, EKeywordPlatSecProcessIsolation, "Set Platform Security process isolation on/off"},
       
   114 	{_K("platsecenforcesysbin"), 1, 1, EKeywordPlatSecEnforceSysBin, "Set Platform Security process isolation on/off"},
       
   115 	{_K("platsecdisabledcaps"), 1, 1, EKeywordPlatSecDisabledCaps, "Disable the listed Platform Security capabilities"},
       
   116 	{_K("pagingpolicy"),	1, 1, EKeywordPagingPolicy, "Set the demand paging policy NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
   117 	{_K("codepagingpolicy"),	1, 1, EKeywordCodePagingPolicy, "Set the code paging policy NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
   118 	{_K("datapagingpolicy"),	1, 1, EKeywordDataPagingPolicy, "Set the data paging policy NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
   119 	{_K("pagingoverride"),	1, 1, EKeywordPagingOverride, "Overide the demand paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
   120 	{_K("codepagingoverride"),	1, 1, EKeywordCodePagingOverride, "Overide the code paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
   121 	{_K("datapagingoverride"),	1, 1, EKeywordDataPagingOverride, "Overide the data paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
   122 	{_K("patchdata"), 2, 5, EKeywordPatchDllData, "Patch exported data"},
       
   123 	{_K("coreimage"),	1, 1, EKeywordCoreImage, "Core image to be used for extension directory structure"},
       
   124 
       
   125 	// things we don't normally report in the help information
       
   126 	{_K("trace"),		1, 1, EKeywordTrace, "(ROMBUILD activity trace flags)"},
       
   127 	{_K("unicode"),		1, 0, EKeywordUnicode, "(UNICODE rom - the default)"},
       
   128 	{_K("ascii"),		1, 0, EKeywordAscii, "(Narrow rom)"},
       
   129 	{_K("languages"),	1,-1, EKeywordLanguages, "(List of supported languages (for test))"},
       
   130 	{_K("hardware"),	1, 1, EKeywordHardware, "(32-bit Hardware identifier (for test))"},
       
   131 	{_K("debugport"),	1, 1, EKeywordDebugPort, "(Debug trace sink (magic cookie passed to ASSP/variant))"},
       
   132 	{_K("compress"),	1, 0, EKeywordCompress, "Compress the ROM image"},
       
   133 	{_K("demandpagingconfig"),	1, -1, EKeywordDemandPagingConfig, "Demand Paging Config [minPages] [maxPages] [ageRatio]"},
       
   134 	{_K("pagedrom"),	1, 0, EKeywordPagedRom, "Build ROM immage suitable for demand paging"},
       
   135 	{_K("filecompressnone"), 		2, -2, EKeywordExecutableCompressionMethodNone, "No compress the individual executable image."},
       
   136 	{_K("filecompressinflate"),     2, -2, EKeywordExecutableCompressionMethodInflate,  "Inflate compression method for the individual executable image."},
       
   137 	{_K("filecompressbytepair"),  	2, -2, EKeywordExecutableCompressionMethodBytePair, "Byte pair compresion method for the individual executable image."},
       
   138 	{_K("kernelconfig"), 1, 2, EKeywordKernelConfig, "Set an arbitrary bit of the kernel config flags to on/off)"},
       
   139 	{_K("maxunpagedsize"),	1, 1, EKeywordMaxUnpagedMemSize, "Maxinum unpaged size in ROM image. Default is no limited."},
       
   140 	{_K("hcrdata") , 2, 2,EKeywordHardwareConfigRepositoryData,"HCR image data"},
       
   141 	{0,0,0,0,EKeywordNone,""} 
       
   142 	
       
   143 };
       
   144 
       
   145 void ObeyFileReader::KeywordHelp() // static
       
   146 	{
       
   147 	cout << "Obey file keywords:\n";
       
   148 
       
   149 	const ObeyFileKeyword* k=0;
       
   150 	for (k=iKeywords; k->iKeyword!=0; k++)
       
   151 		{
       
   152 		if (k->iHelpText==0)
       
   153 			continue;
       
   154 		if (k->iHelpText[0]=='(' && !H.iVerbose)
       
   155 			continue;	// don't normally report things in (parentheses)
       
   156 
       
   157 		char buf[32];
       
   158 		sprintf(buf, "%-20s", k->iKeyword);
       
   159 		if (k->iKeywordLength)
       
   160 			memcpy(buf+k->iKeywordLength,"[HWVD]",6);
       
   161 		if (H.iVerbose)
       
   162 			sprintf(buf+20,"%2d",k->iNumArgs);
       
   163 		cout << "    " << buf << " " << k->iHelpText << endl;
       
   164 		}
       
   165 	cout << endl;
       
   166 
       
   167 	cout << "File attributes:\n";
       
   168 
       
   169 	const FileAttributeKeyword* f=0;
       
   170 	for (f=iAttributeKeywords; f->iKeyword!=0; f++)
       
   171 		{
       
   172 		if (f->iHelpText==0)
       
   173 			continue;
       
   174 		if (f->iHelpText[0]=='(' && !H.iVerbose)
       
   175 			continue;	// don't normally report things in (parentheses)
       
   176 
       
   177 		char buf[32];
       
   178 		sprintf(buf, "%-20s", f->iKeyword);
       
   179 		if (H.iVerbose)
       
   180 			sprintf(buf+20,"%2d",k->iNumArgs);
       
   181 		cout << "    " << buf << " " << f->iHelpText << endl;
       
   182 		}
       
   183 	cout << endl;
       
   184 	}
       
   185 
       
   186 TInt NumberOfVariants=0;
       
   187 
       
   188 ObeyFileReader::ObeyFileReader(TText* aFileName):
       
   189 //
       
   190 // Constructor
       
   191 //
       
   192 	iMark(0), iMarkLine(0), iCurrentMark(0), iCurrentLine(0), imaxLength(0),iSuffix(0),iLine(0)
       
   193 	{
       
   194 
       
   195 	iFileName = new TText[strlen((const char *)aFileName)+1];
       
   196 	strcpy((char *)iFileName,(const char *)aFileName);
       
   197 	}
       
   198 
       
   199 ObeyFileReader::~ObeyFileReader()
       
   200 	{
       
   201 	if (iObeyFile)
       
   202 		fclose(iObeyFile);
       
   203 	iObeyFile=0;
       
   204 	delete [] iFileName;
       
   205 	delete [] iLine;
       
   206 	}
       
   207 
       
   208 TBool ObeyFileReader::Open()
       
   209 //
       
   210 // Open the file & return a status
       
   211 //
       
   212 	{
       
   213 
       
   214  	iObeyFile = fopen((const char *)iFileName,"r");
       
   215 	if (!iObeyFile)
       
   216 		{
       
   217 		Print(EError,"Cannot open obey file %s\n",iFileName);
       
   218 		return EFalse;
       
   219 		}
       
   220 	if (SetLineLengthBuffer() != KErrNone)
       
   221 	 	{
       
   222 		Print(EError,"Insufficent Memory to Continue.");	
       
   223 	 	return EFalse;
       
   224 		}
       
   225 	return ETrue;
       
   226 	}
       
   227 
       
   228 TInt ObeyFileReader::SetLineLengthBuffer()
       
   229 // Get the Max Line length for the given obey file and allocate the buffer.
       
   230 	{
       
   231 	char ch = '\0';
       
   232 	TInt length = 0;
       
   233 		
       
   234 	Rewind();
       
   235 	while ((ch = (char)fgetc(iObeyFile)) != EOF)
       
   236 		{
       
   237 		length++;
       
   238 		if (ch == '\n')
       
   239 			{
       
   240 			if (length > imaxLength)
       
   241 				imaxLength = length;
       
   242 			length = 0;				
       
   243 			}
       
   244 		}
       
   245 	
       
   246 	if (length > imaxLength)
       
   247 		imaxLength = length;
       
   248 		
       
   249 	if (0 == imaxLength)
       
   250 		{
       
   251 		Print(EError,"Empty obey file passed as input.");
       
   252 		exit(-1);
       
   253 		}			
       
   254 	else if (imaxLength < 2)
       
   255 		{
       
   256 		Print(EError,"Invalid obey file passed as input.");
       
   257 		exit(-1);
       
   258 		}
       
   259 		
       
   260 	Rewind();
       
   261 	iLine = new TText[imaxLength+1];
       
   262 	
       
   263 	if(!iLine)
       
   264 		return KErrNoMemory;
       
   265 
       
   266 	return KErrNone;
       
   267 	}
       
   268 
       
   269 void ObeyFileReader::Mark()
       
   270 	{
       
   271 
       
   272 	iMark = iCurrentMark;
       
   273 	iMarkLine = iCurrentLine-1;
       
   274 	}
       
   275 
       
   276 void ObeyFileReader::MarkNext()
       
   277 	{
       
   278 
       
   279 	iMark = ftell(iObeyFile);
       
   280 	iMarkLine = iCurrentLine;
       
   281 	}
       
   282 
       
   283 void ObeyFileReader::Rewind()
       
   284 	{
       
   285 	
       
   286 	fseek(iObeyFile,iMark,SEEK_SET);
       
   287 	iCurrentMark = iMark;
       
   288 	iCurrentLine = iMarkLine;
       
   289 	}
       
   290 
       
   291 void ObeyFileReader::CopyWord(TInt aIndex, TText*& aString)
       
   292 	{
       
   293 	aString = new TText[strlen((const char *)iWord[aIndex])+1];
       
   294 	strcpy((char *)aString, (const char *)iWord[aIndex]);
       
   295 	}
       
   296 
       
   297 TInt ObeyFileReader::ReadAndParseLine()
       
   298 	{
       
   299 	if (feof(iObeyFile))
       
   300 		return KErrEof;
       
   301 	iCurrentLine++;
       
   302 	iCurrentMark = ftell(iObeyFile);
       
   303 	iLine[0]='\0';
       
   304 	fgets((char*)iLine,imaxLength+1,iObeyFile);
       
   305 	iNumWords = Parse();
       
   306 	return KErrNone;
       
   307 	}
       
   308 
       
   309 TInt ObeyFileReader::NextLine(TInt aPass, enum EKeyword& aKeyword)
       
   310 	{
       
   311 
       
   312 NextLine:
       
   313 	TInt err = ReadAndParseLine();
       
   314 	if (err == KErrEof)
       
   315 		return KErrEof;
       
   316 	if (iNumWords == 0 || stricmp((const char*)iWord[0], "rem")==0)
       
   317 		goto NextLine;
       
   318 	if (stricmp((const char*)iWord[0], "stop")==0)
       
   319 		return KErrEof;
       
   320 
       
   321 	const ObeyFileKeyword* k=0;
       
   322 	for (k=iKeywords; k->iKeyword!=0; k++)
       
   323 		{
       
   324 		if (k->iKeywordLength == 0)
       
   325 			{
       
   326 			// Exact case-insensitive match on keyword
       
   327 			if (stricmp((const char*)iWord[0], k->iKeyword) != 0)
       
   328 				continue;
       
   329 			iSuffix = 0;
       
   330 			}
       
   331 		else
       
   332 			{
       
   333 			// Prefix match
       
   334 			if (strnicmp((const char*)iWord[0], k->iKeyword, k->iKeywordLength) != 0)
       
   335 				continue;
       
   336 			// Suffix must be empty, or a variant number in []
       
   337 			iSuffix = iWord[0]+k->iKeywordLength;
       
   338 			if (*iSuffix != '\0' && *iSuffix != '[')
       
   339 				continue;
       
   340 			}
       
   341 		// found a match
       
   342 		if ((k->iPass & aPass) == 0)
       
   343 			goto NextLine;
       
   344 		if (k->iNumArgs>=0 && (1+k->iNumArgs != iNumWords))
       
   345 			{
       
   346 			 
       
   347 			if(EKeywordHardwareConfigRepositoryData == k->iKeywordEnum){ // preq2131 specific 
       
   348 				Print(EWarning, "Incorrect number of arguments for keyword '%s' on line %d. Extra argument(s) are ignored.\n",
       
   349 				iWord[0],iCurrentLine);
       
   350 				aKeyword = k->iKeywordEnum;
       
   351 				return KErrNone;
       
   352 			}else{
       
   353 				Print(EError, "Incorrect number of arguments for keyword %s on line %d.\n",
       
   354 					iWord[0], iCurrentLine);
       
   355 			}
       
   356 			goto NextLine;
       
   357 			}
       
   358 		if (k->iNumArgs<0 && (1-k->iNumArgs > iNumWords))
       
   359 			{
       
   360 			Print(EError, "Too few arguments for keyword %s on line %d.\n",
       
   361 				iWord[0], iCurrentLine);
       
   362 			goto NextLine;
       
   363 			}
       
   364 		
       
   365 		aKeyword = k->iKeywordEnum;
       
   366 		return KErrNone;
       
   367 		}
       
   368 	if (aPass == 1)
       
   369 		Print(EWarning, "Unknown keyword '%s'.  Line %d ignored\n", iWord[0], iCurrentLine);
       
   370 	goto NextLine;
       
   371 	}
       
   372 
       
   373 inline TBool ObeyFileReader::IsGap(char ch)
       
   374 	{
       
   375 	return (ch==' ' || ch=='=' || ch=='\t');
       
   376 	}
       
   377 
       
   378 TInt ObeyFileReader::Parse()
       
   379 //
       
   380 // splits a line into words, and returns the number of words found
       
   381 //
       
   382 
       
   383 	{
       
   384 
       
   385 	TUint i; 
       
   386 	TText *letter=iLine;
       
   387 	TText *end=iLine+strlen((char *)iLine);
       
   388 	for (i=0; i<KNumWords; i++)
       
   389 		iWord[i]=end;
       
   390 
       
   391 	enum TState {EInWord, EInQuotedWord, EInGap};
       
   392 	TState state=EInGap;
       
   393 
       
   394 	i=0;
       
   395 	while (i<KNumWords && letter<end)
       
   396 		{
       
   397 		char ch=*letter;
       
   398 		if (ch==0)
       
   399 			break;
       
   400 		if (ch=='\n')
       
   401 			{
       
   402 			*letter='\0';	// remove trailing newline left by fgets
       
   403 			break;
       
   404 			}
       
   405 		switch (state)
       
   406 			{
       
   407 		case EInGap:
       
   408 			if (ch=='\"')
       
   409 				{
       
   410 				if (letter[1]!=0 && letter[1]!='\"')
       
   411 					iWord[i++]=letter+1;
       
   412 				state=EInQuotedWord;
       
   413 				}
       
   414 			else if (!IsGap(ch))
       
   415 				{
       
   416 				iWord[i++]=letter;
       
   417 				state=EInWord;
       
   418 				}
       
   419 			else
       
   420 				*letter=0;
       
   421 			break;
       
   422 		case EInWord:
       
   423 			if (ch=='\"')
       
   424 				{
       
   425 				*letter=0;
       
   426 				if (letter[1]!=0 && letter[1]!='\"')
       
   427 					iWord[i++]=letter+1;
       
   428 				state=EInQuotedWord;
       
   429 				}
       
   430 			else if (IsGap(ch))
       
   431 				{
       
   432 				*letter=0;
       
   433 				state=EInGap;
       
   434 				}
       
   435 			break;
       
   436 		case EInQuotedWord:
       
   437 			if (ch=='\"')
       
   438 				{
       
   439 				*letter=0;
       
   440 				state=EInGap;
       
   441 				}
       
   442 			break;
       
   443 			}
       
   444 		letter++;
       
   445 		}
       
   446 	return i;
       
   447 	}
       
   448 
       
   449 void ObeyFileReader::ProcessLanguages(TInt64& aLanguageMask)
       
   450 	{
       
   451 	TInt i=1;
       
   452 	while (i<iNumWords)
       
   453 		{
       
   454 		char *aStr=(char *)iWord[i];
       
   455 		TLanguage l=ELangTest;
       
   456 		if (stricmp(aStr, "test")==0)
       
   457 			l=ELangTest;
       
   458 		else if (stricmp(aStr, "english")==0)
       
   459 			l=ELangEnglish;
       
   460 		else if (stricmp(aStr, "french")==0)
       
   461 			l=ELangFrench;
       
   462 		else if (stricmp(aStr, "german")==0)
       
   463 			l=ELangGerman;
       
   464 		else if (stricmp(aStr, "spanish")==0)
       
   465 			l=ELangSpanish;
       
   466 		else if (stricmp(aStr, "italian")==0)
       
   467 			l=ELangItalian;
       
   468 		else if (stricmp(aStr, "swedish")==0)
       
   469 			l=ELangSwedish;
       
   470 		else if (stricmp(aStr, "danish")==0)
       
   471 			l=ELangDanish;
       
   472 		else if (stricmp(aStr, "norwegian")==0)
       
   473 			l=ELangNorwegian;
       
   474 		else if (stricmp(aStr, "finnish")==0)
       
   475 			l=ELangFinnish;
       
   476 		else if (stricmp(aStr, "american")==0)
       
   477 			l=ELangAmerican;
       
   478 		else if (stricmp(aStr, "SwissFrench")==0)
       
   479 			l=ELangSwissFrench;
       
   480 		else if (stricmp(aStr, "SwissGerman")==0)
       
   481 			l=ELangSwissGerman;
       
   482 		else if (stricmp(aStr, "Portuguese")==0)
       
   483 			l=ELangPortuguese;
       
   484 		else if (stricmp(aStr, "Turkish")==0)
       
   485 			l=ELangTurkish;
       
   486 		else if (stricmp(aStr, "Icelandic")==0)
       
   487 			l=ELangIcelandic;
       
   488 		else if (stricmp(aStr, "Russian")==0)
       
   489 			l=ELangRussian;
       
   490 		else if (stricmp(aStr, "Hungarian")==0)
       
   491 			l=ELangHungarian;
       
   492 		else if (stricmp(aStr, "Dutch")==0)
       
   493 			l=ELangDutch;
       
   494 		else if (stricmp(aStr, "BelgianFlemish")==0)
       
   495 			l=ELangBelgianFlemish;
       
   496 		else if (stricmp(aStr, "Australian")==0)
       
   497 			l=ELangAustralian;
       
   498 		else if (stricmp(aStr, "BelgianFrench")==0)
       
   499 			l=ELangBelgianFrench;
       
   500 		else
       
   501 			{
       
   502 			Print(EError, "Unknown language '%s' on line %d", iWord[i], iCurrentLine);
       
   503 			exit(666);
       
   504 			}
       
   505 		aLanguageMask = aLanguageMask+(1<<(TInt)l);
       
   506 		i++;
       
   507 		}
       
   508 	}
       
   509 
       
   510 void ObeyFileReader::ProcessTime(TInt64& aTime)
       
   511 //
       
   512 // Process the timestamp
       
   513 //
       
   514 	{
       
   515 	char timebuf[256];
       
   516 	if (iNumWords>2)
       
   517 		sprintf(timebuf, "%s_%s", iWord[1], iWord[2]);
       
   518 	else
       
   519 		strcpy(timebuf, (char*)iWord[1]);
       
   520 
       
   521 	TInt r=StringToTime(aTime, timebuf);
       
   522 	if (r==KErrGeneral)
       
   523 		{
       
   524 		Print(EError, "incorrect format for time keyword on line %d\n", iCurrentLine);
       
   525 		exit(0x670);
       
   526 		}
       
   527 	if (r==KErrArgument)
       
   528 		{
       
   529 		Print(EError, "Time out of range on line %d\n", iCurrentLine);
       
   530 		exit(0x670);
       
   531 		}
       
   532 	}
       
   533 
       
   534 TInt64 ObeyFileReader::iTimeNow=0;
       
   535 void ObeyFileReader::TimeNow(TInt64& aTime)
       
   536 	{
       
   537 	if (iTimeNow==0)
       
   538 		{
       
   539 		TInt sysTime=time(0);					// seconds since midnight Jan 1st, 1970
       
   540 		sysTime-=(30*365*24*60*60+7*24*60*60);	// seconds since midnight Jan 1st, 2000
       
   541 		TInt64 daysTo2000AD=730497;
       
   542 		TInt64 t=daysTo2000AD*24*3600+sysTime;	// seconds since 0000
       
   543 		t=t+3600;								// BST (?)
       
   544 		iTimeNow=t*1000000;						// milliseconds
       
   545 		}
       
   546 	aTime=iTimeNow;
       
   547 	}
       
   548 
       
   549 TInt ObeyFileReader::ProcessAlign(TInt &aAlign)
       
   550 //
       
   551 // Process the align keyword
       
   552 //
       
   553 	{
       
   554 
       
   555 	TInt align;
       
   556 	if (Val(align, Word(1)))
       
   557 		return Print(EError, "Number required for 'align' keyword on line %d\n", iCurrentLine);
       
   558 	aAlign=align;
       
   559 	TInt i;
       
   560 	for (i=4; i!=0x40000000; i<<=1)
       
   561 		if (i==aAlign)
       
   562 			return KErrNone;
       
   563 	return Print(EError, "Alignment must be a power of 2 and bigger than 4.  Line %d\n", iCurrentLine);
       
   564 	}
       
   565 
       
   566 
       
   567 const FileAttributeKeyword ObeyFileReader::iAttributeKeywords[] =
       
   568 {
       
   569 	{"stackreserve",6	,1,1,EAttributeStackReserve, "?"},
       
   570 	{"stack",3			,1,1,EAttributeStack, "?"},
       
   571 	{"reloc",3			,1,1,EAttributeReloc, "?"},
       
   572 	{"code-align",10	,1,1,EAttributeCodeAlign, "Additional code alignment constraint"},
       
   573 	{"data-align",10	,1,1,EAttributeDataAlign, "Additional data alignment constraint"},
       
   574 	{"fixed",3			,1,0,EAttributeFixed, "Relocate to a fixed address space"},
       
   575 	{"attrib",3			,0,1,EAttributeAtt, "File attributes in ROM file system"},
       
   576 	{"priority",3		,1,1,EAttributePriority, "Override process priority"},
       
   577 	{"patched",5		,1,0,EAttributePatched, "File to be replaced in second section"},
       
   578 	{_K("uid1")			,1,1,EAttributeUid1, "Override first UID"},
       
   579 	{_K("uid2")			,1,1,EAttributeUid2, "Override second UID"},
       
   580 	{_K("uid3")			,1,1,EAttributeUid3, "Override third UID"},
       
   581 	{_K("heapmin")		,1,1,EAttributeHeapMin, "Override initial heap size"},
       
   582 	{_K("heapmax")		,1,1,EAttributeHeapMax, "Override maximum heap size"},
       
   583 	{_K("keepIAT")		,1,0,EAttributeKeepIAT, "(Retain old-style Import Address Table)"},
       
   584 	{_K("hide")			,0,0,EAttributeHidden, "Don't record file in the ROM file system"},
       
   585 	{_K("area")         ,1,1,EAttributeArea, "Relocate file to given area"},
       
   586 	{_K("process")		,1,1,EAttributeProcessSpecific, "Indicate which process a DLL will attach to"},
       
   587 	{_K("capability")	,1,1,EAttributeCapability, "Override capabilities"},
       
   588 	{_K("preferred")	,1,0,EAttributePreferred, "Prefer this over other minor versions of same major version"},
       
   589 	{_K("unpaged")		,1,0,EAttributeUnpaged, "Don't use demand paging for this file"},
       
   590 	{_K("paged")		,1,0,EAttributePaged, "Use demand paging for this file"},
       
   591 	{_K("unpagedcode")	,1,0,EAttributeUnpagedCode, "Don't use code paging for this file"},
       
   592 	{_K("pagedcode")	,1,0,EAttributePagedCode, "Use code paging for this file"},
       
   593 	{_K("unpageddata")	,1,0,EAttributeUnpagedData, "Don't use data paging for this file"},
       
   594 	{_K("pageddata")	,1,0,EAttributePagedData, "Use data paging for this file"},
       
   595 	{0,0,0,0,EAttributeStackReserve,0}
       
   596 };
       
   597 
       
   598 TInt ObeyFileReader::NextAttribute(TInt& aIndex, TInt aHasFile, enum EFileAttribute& aKeyword, TText*& aArg)
       
   599 	{
       
   600 NextAttribute:
       
   601 	if (aIndex >= iNumWords)
       
   602 		return KErrEof;
       
   603 	TText* word=iWord[aIndex++];
       
   604 	const FileAttributeKeyword* k;
       
   605 	for (k=iAttributeKeywords; k->iKeyword!=0; k++)
       
   606 		{
       
   607 		if (k->iKeywordLength == 0)
       
   608 			{
       
   609 			// Exact match on keyword
       
   610 			if (stricmp((const char*)word, k->iKeyword) != 0)
       
   611 				continue;
       
   612 			}
       
   613 		else
       
   614 			{
       
   615 			// Prefix match
       
   616 			if (strnicmp((const char*)word, k->iKeyword, k->iKeywordLength) != 0)
       
   617 				continue;
       
   618 			}
       
   619 		// found a match
       
   620 		if (k->iNumArgs>0)
       
   621 			{
       
   622 			TInt argIndex = aIndex;
       
   623 			aIndex += k->iNumArgs;		// interface only really supports 1 argument
       
   624 			if (aIndex>iNumWords)
       
   625 				{
       
   626 				Print(EError, "Missing argument for attribute %s on line %d\n", word, iCurrentLine);
       
   627 				return KErrArgument;
       
   628 				}
       
   629 			aArg=iWord[argIndex];
       
   630 			}
       
   631 		if (k->iIsFileAttribute && !aHasFile)
       
   632 			{
       
   633 			Print(EError, "File attribute %s applied to non-file on line %d\n", word, iCurrentLine);
       
   634 			return KErrNotSupported;
       
   635 			}
       
   636 		aKeyword=k->iAttributeEnum;
       
   637 		return KErrNone;
       
   638 		}
       
   639 	Print(EWarning, "Unknown attribute '%s' skipped on line %d\n", word, iCurrentLine);
       
   640 	goto NextAttribute;
       
   641 	}
       
   642 
       
   643 
       
   644 
       
   645 
       
   646 CObeyFile::CObeyFile(ObeyFileReader& aReader):
       
   647 	iRomFileName(0),iRomOddFileName(0),iRomEvenFileName(0),
       
   648 	iSRecordFileName(0),iBootFileName(0),iKernelRomName(0),
       
   649 	iRomSize(0),iRomLinearBase(0xffffffff),iRomAlign(0),
       
   650 	iKernDataRunAddress(0),iDataRunAddress(0),iKernelLimit(0xffffffff),
       
   651 	iKernHeapMin(0),iKernHeapMax(0),iSectionStart(0),iSectionPosition(-1),
       
   652 	iVersion(0,0,0),iCheckSum(0),iNumberOfPeFiles(0),iNumberOfDataFiles(0),
       
   653 	iNumberOfPrimaries(0),iNumberOfExtensions(0),iNumberOfVariants(0),
       
   654 	iNumberOfDevices(0),iNumberOfHCRDataFiles (0),
       
   655 	//iAllVariantsMask[256],
       
   656 	iPrimaries(0),iVariants(0),iExtensions(0),iDevices(0),
       
   657 	iLanguage(0),iHardware(0),iTime(0),iMemModel(E_MM_Moving),iPageSize(0x1000),
       
   658 	iChunkSize(0x100000),iVirtualAllocSize(0x1000),iKernelModel(ESingleKernel),
       
   659 	iCollapseMode(ECollapseNone),iSRecordBase(0),iCurrentSectionNumber(0),
       
   660 	iDefaultStackReserve(0),//iTraceMask[KNumTraceMaskWords];iInitialBTraceFilter[8];
       
   661 	iInitialBTraceBuffer(0),iInitialBTraceMode(0),iDebugPort(0),
       
   662 	iDebugPortParsed(EFalse),iRootDirectory(0),iDllDataTop(0x40000000),
       
   663 	iKernelConfigFlags(0),iPagingPolicyParsed(EFalse),iCodePagingPolicyParsed(EFalse),
       
   664 	iDataPagingPolicyParsed(EFalse),iPagingOverrideParsed(EFalse),
       
   665 	iCodePagingOverrideParsed(EFalse),iDataPagingOverrideParsed(EFalse),
       
   666 	/*iPlatSecDisabledCaps(), */iPlatSecDisabledCapsParsed(EFalse),iMaxUnpagedMemSize(0),
       
   667 	iReader(aReader),iMissingFiles(0),iLastExecutable(0),iAreaSet(),iFirstFile(0),
       
   668 	iCurrentFile(0),iLastVariantFile(0),iFirstDllDataEntry(0),
       
   669 	iUpdatedMaxUnpagedMemSize(EFalse),iPatchData(new CPatchDataProcessor)
       
   670 	{
       
   671 
       
   672 	TUint i; 
       
   673 	for (i=0; i<256; i++)
       
   674 		iAllVariantsMask[i]=0;
       
   675 	for (i=0; i<(TUint)KNumTraceMaskWords; i++) 
       
   676 		iTraceMask[i]=0;
       
   677 	for (i=0; i<sizeof(iInitialBTraceFilter)/sizeof(TUint32); i++)
       
   678 		iInitialBTraceFilter[i]=0;	
       
   679 	memset(&iPlatSecDisabledCaps,0,sizeof(SCapabilitySet));
       
   680 	iNextFilePtrPtr = &iFirstFile;
       
   681 	}
       
   682 
       
   683 CObeyFile::~CObeyFile()
       
   684 //
       
   685 // Destructor
       
   686 //
       
   687 	{
       
   688 
       
   689 	Release();
       
   690 	delete [] iRomFileName;
       
   691 	if (iRootDirectory)
       
   692 		iRootDirectory->Destroy();
       
   693 	delete iPatchData;
       
   694 	}
       
   695 
       
   696 void CObeyFile::Release()
       
   697 //
       
   698 // Free resources not needed after building a ROM
       
   699 //
       
   700 	{
       
   701 	iAreaSet.ReleaseAllAreas();
       
   702 
       
   703 	delete [] iBootFileName;
       
   704 	delete [] iPrimaries;
       
   705 	delete [] iVariants;
       
   706 	delete [] iExtensions;
       
   707 	delete [] iDevices;
       
   708 
       
   709 	iBootFileName = 0;
       
   710 	iPrimaries = 0;
       
   711 	iVariants = 0;
       
   712 	iExtensions = 0;
       
   713 	iDevices = 0;
       
   714 	iFirstFile = 0;
       
   715 	iNextFilePtrPtr = &iFirstFile;
       
   716 	}
       
   717 
       
   718 TRomBuilderEntry *CObeyFile::FirstFile()
       
   719 	{
       
   720 	iCurrentFile = iFirstFile;
       
   721 	return iCurrentFile;
       
   722 	}
       
   723 
       
   724 TRomBuilderEntry *CObeyFile::NextFile()
       
   725 	{
       
   726 	iCurrentFile = iCurrentFile ? iCurrentFile->iNext : 0;
       
   727 	return iCurrentFile;
       
   728 	}
       
   729 
       
   730 /*
       
   731 *Set first link in patchdata linked list
       
   732 **/
       
   733 void CObeyFile::SetFirstDllDataEntry(DllDataEntry* aDllDataEntry)
       
   734 {
       
   735   	iFirstDllDataEntry = aDllDataEntry;
       
   736 }
       
   737 
       
   738 /*
       
   739 *Get first link in patchdata linked list
       
   740 **/
       
   741 DllDataEntry* CObeyFile::GetFirstDllDataEntry() const
       
   742 {
       
   743 	return iFirstDllDataEntry;
       
   744 }
       
   745 
       
   746 TInt CObeyFile::ProcessKernelRom()
       
   747 	{
       
   748 	//
       
   749 	// First pass through the obey file to set up key variables
       
   750 	//
       
   751 
       
   752 	iReader.Rewind();
       
   753 
       
   754 	TInt count=0;
       
   755 	enum EKeyword keyword;
       
   756 	while (iReader.NextLine(1,keyword) != KErrEof)
       
   757 		{
       
   758 		if (keyword == EKeywordExtensionRom)
       
   759 			{
       
   760 			if (count==0)
       
   761 				return KErrNotFound;		// no kernel ROM, just extension ROMs.
       
   762 			break;
       
   763 			}
       
   764 
       
   765 		count++;
       
   766 		if (! ProcessKeyword(keyword))
       
   767 			return KErrGeneral;
       
   768 		}
       
   769 
       
   770 	if (!GotKeyVariables())
       
   771 		return KErrGeneral;
       
   772 
       
   773 	if (! CreateDefaultArea())
       
   774 		return KErrGeneral;
       
   775 
       
   776 	//
       
   777 	// second pass to process the file specifications in the obey file building
       
   778 	// up the TRomNode directory structure and the TRomBuilderEntry list
       
   779 	//
       
   780 	iReader.Rewind();
       
   781 
       
   782 	iRootDirectory = new TRomNode((TText*)"");
       
   783 	iLastExecutable = iRootDirectory;
       
   784 
       
   785 	TInt align=0;
       
   786 	while (iReader.NextLine(2,keyword)!=KErrEof)
       
   787 		{
       
   788 		if (keyword == EKeywordExtensionRom)
       
   789 			break;
       
   790 
       
   791 		switch (keyword)
       
   792 			{
       
   793 		case EKeywordSection:
       
   794 			if (ParseSection()!=KErrNone)
       
   795 				return KErrGeneral;
       
   796 			break;
       
   797 		case EKeywordAlign:
       
   798 			if (iReader.ProcessAlign(align)!=KErrNone)
       
   799 				return KErrGeneral;
       
   800 			break;
       
   801 		case EKeywordHide:
       
   802 		case EKeywordAlias:
       
   803 		case EKeywordRename:
       
   804 			if (!ProcessRenaming(keyword))
       
   805 				return KErrGeneral;
       
   806 			break;
       
   807 		case EKeywordPatchDllData:
       
   808 		{
       
   809 			// Collect patchdata statements to process at the end
       
   810 			StringVector patchDataTokens;
       
   811 			SplitPatchDataStatement(patchDataTokens); 
       
   812 			iPatchData->AddPatchDataStatement(patchDataTokens);									
       
   813 			break;
       
   814 		}
       
   815 
       
   816 		default:
       
   817 			if (!ProcessFile(align, keyword))
       
   818 				return KErrGeneral;
       
   819 			align=0;
       
   820 			break;
       
   821 			}
       
   822 		}
       
   823 
       
   824 	if( !ParsePatchDllData())
       
   825 		return KErrGeneral;
       
   826 
       
   827 	iReader.Mark();			// ready for processing the extension rom(s)
       
   828 
       
   829 	if (iMissingFiles!=0)
       
   830 		return KErrGeneral;
       
   831 	if (iNumberOfDataFiles+iNumberOfPeFiles==0)
       
   832 		{
       
   833 		Print(EError, "No files specified.\n");
       
   834 		return KErrGeneral;
       
   835 		}
       
   836 	if (!CheckHardwareVariants())
       
   837 		return KErrGeneral;
       
   838 
       
   839 	return KErrNone;
       
   840 	}
       
   841 
       
   842 
       
   843 TInt CObeyFile::ParseSection()
       
   844 //
       
   845 // Process the section keyword
       
   846 //
       
   847 	{
       
   848 	TInt currentLine = iReader.CurrentLine();
       
   849 	if (iSectionPosition!=-1)
       
   850 		return Print(EError, "Rom already sectioned.  Line %d\n", currentLine);
       
   851 	TInt offset;
       
   852 	if (Val(offset, iReader.Word(1)))
       
   853 		return Print(EError, "Number required for 'section' keyword on line %d\n", currentLine);
       
   854 	iSectionStart=offset+iRomLinearBase;
       
   855 	if (offset>=iRomSize)
       
   856 		return Print(EError, "Sectioned beyond end of Rom.  Line %d\n", currentLine);
       
   857 	if (offset&0x0fff)
       
   858 		return Print(EError, "Section must be on a 4K boundry.  Line %d\n", currentLine);
       
   859 	iSectionPosition=iNumberOfDataFiles+iNumberOfPeFiles;
       
   860 	iCurrentSectionNumber++;	
       
   861 	return KErrNone;
       
   862 	}
       
   863 
       
   864 TInt CObeyFile::ParseFileAttributes(TRomNode *aNode, TRomBuilderEntry* aFile)
       
   865 //
       
   866 // Process any inline keywords
       
   867 //
       
   868 	{
       
   869 	TInt currentLine = iReader.CurrentLine();
       
   870 	enum EFileAttribute attribute;
       
   871 	TInt r=KErrNone;
       
   872 	TInt index=3;
       
   873 	TText* arg=0;
       
   874 
       
   875 	while(r==KErrNone)
       
   876 		{
       
   877 		r=iReader.NextAttribute(index,(aFile!=0),attribute,arg);
       
   878 		if (r!=KErrNone)
       
   879 			break;
       
   880 		switch(attribute)
       
   881 			{
       
   882 		case EAttributeStackReserve:
       
   883 			r=aFile->SetStackReserve(arg);
       
   884 			break;
       
   885 		case EAttributeStack:
       
   886 			r=aFile->SetStackSize(arg);
       
   887 			break;
       
   888 		case EAttributeReloc:
       
   889 			r=aFile->SetRelocationAddress(arg);
       
   890 			break;
       
   891 		case EAttributeCodeAlign:
       
   892 			r=aFile->SetCodeAlignment(arg);
       
   893 			break;
       
   894 		case EAttributeDataAlign:
       
   895 			r=aFile->SetDataAlignment(arg);
       
   896 			break;
       
   897 		case EAttributeFixed:
       
   898 			r=aFile->SetRelocationAddress(NULL);
       
   899 			break;
       
   900 		case EAttributeAtt:
       
   901 			r=aNode->SetAtt(arg);
       
   902 			break;
       
   903 		case EAttributeUid1:
       
   904 			r=aFile->SetUid1(arg);
       
   905 			break;
       
   906 		case EAttributeUid2:
       
   907 			r=aFile->SetUid2(arg);
       
   908 			break;
       
   909 		case EAttributeUid3:
       
   910 			r=aFile->SetUid3(arg);
       
   911 			break;
       
   912 		case EAttributeHeapMin:
       
   913 			r=aFile->SetHeapSizeMin(arg);
       
   914 			break;
       
   915 		case EAttributeHeapMax:
       
   916 			r=aFile->SetHeapSizeMax(arg);
       
   917 			break;
       
   918 		case EAttributePriority:
       
   919 			r=aFile->SetPriority(arg);
       
   920 			break;
       
   921 		case EAttributePatched:
       
   922 			if (iSectionPosition!=-1)
       
   923 				return Print(EError, "Not sensible to patch files in top section.  Line %d.\n", currentLine);
       
   924 			aFile->iPatched=ETrue;
       
   925 			break;
       
   926 		case EAttributeKeepIAT:
       
   927 			aFile->iOverrideFlags |= KOverrideKeepIAT;
       
   928 			break;
       
   929 		case EAttributeHidden:
       
   930 			if (aFile->Extension())
       
   931  				return Print(EError, "Cannot hide Extension. Line %d.\n", currentLine);
       
   932 			aNode->iHidden=ETrue;
       
   933 			break;
       
   934 		case EAttributeArea:
       
   935 			{
       
   936 			TRACE(TAREA, Print(EScreen, "Area Attribute: %s\n", arg));
       
   937 			const Area* area = aFile->iArea;
       
   938 			if (! ParseAreaAttribute(arg, currentLine, area))
       
   939 				return KErrGeneral;
       
   940 			}
       
   941 			break;
       
   942 		case EAttributeProcessSpecific:
       
   943 			if (!IsValidFilePath(arg))
       
   944 				{
       
   945 				Print(EError, "Invalid file path for process attribute on line %d\n", currentLine);
       
   946 				return KErrGeneral;
       
   947 				}
       
   948 			r=aFile->SetAttachProcess(arg);
       
   949 			break;
       
   950 		case EAttributeCapability:
       
   951 			r=aFile->SetCapability(arg);
       
   952 			break;
       
   953 		case EAttributePreferred:
       
   954 			aFile->iPreferred = ETrue;
       
   955 			break;
       
   956 		case EAttributeUnpaged:
       
   957 			aFile->iOverrideFlags |= KOverrideCodeUnpaged | KOverrideDataUnpaged;
       
   958 			aFile->iOverrideFlags &= ~(KOverrideCodePaged | KOverrideDataPaged);
       
   959 			break;
       
   960 		case EAttributePaged:
       
   961 			aFile->iOverrideFlags |= KOverrideCodePaged | KOverrideDataPaged;
       
   962 			aFile->iOverrideFlags &= ~(KOverrideCodeUnpaged | KOverrideDataUnpaged);
       
   963 			break;
       
   964 		case EAttributeUnpagedCode:
       
   965 			aFile->iOverrideFlags |= KOverrideCodeUnpaged;
       
   966 			aFile->iOverrideFlags &= ~KOverrideCodePaged;
       
   967 			break;
       
   968 		case EAttributePagedCode:
       
   969 			aFile->iOverrideFlags |= KOverrideCodePaged;
       
   970 			aFile->iOverrideFlags &= ~KOverrideCodeUnpaged;
       
   971 			break;
       
   972 		case EAttributeUnpagedData:
       
   973 			aFile->iOverrideFlags |= KOverrideDataUnpaged;
       
   974 			aFile->iOverrideFlags &= ~KOverrideDataPaged;
       
   975 			break;
       
   976 		case EAttributePagedData:
       
   977 			aFile->iOverrideFlags |= KOverrideDataPaged;
       
   978 			aFile->iOverrideFlags &= ~KOverrideDataUnpaged;
       
   979 			break;
       
   980 
       
   981 		default:
       
   982 			return Print(EError, "Unrecognised keyword in file attributes on line %d.\n",currentLine);
       
   983 			}
       
   984 		}
       
   985 
       
   986 	// aFile may be null if processing an extension ROM
       
   987 	if (aFile && aFile->iPatched && ! aFile->iArea->IsDefault())
       
   988 		{
       
   989 		return Print(EError, "Relocation to area at line %d forbidden because file is patched\n", currentLine);
       
   990 		}
       
   991 
       
   992 	if (r==KErrEof)
       
   993 		return KErrNone;
       
   994 	return r;
       
   995 	}
       
   996 
       
   997 TUint32 CObeyFile::ParseVariant()
       
   998 	{
       
   999 	char* left=iReader.Suffix();
       
  1000 	if (left == 0 || *left=='\0')
       
  1001 		return KVariantIndependent;
       
  1002 	const char* right=left+strlen(left)-1;
       
  1003 	if (*left=='[' && *right==']')
       
  1004 		{
       
  1005 		TUint variant;
       
  1006 		#ifdef __TOOLS2__
       
  1007 		string s(left+1);
       
  1008 		string s2=s.substr(0,right-(left+1));
       
  1009 		istringstream val(s2,ios::in);
       
  1010 		#else
       
  1011 		istrstream val(left+1, right-(left+1));
       
  1012 		#endif
       
  1013 		
       
  1014 
       
  1015 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1016 		val >> setbase(0);
       
  1017 #endif //__MSVCDOTNET__
       
  1018 
       
  1019 		val >> variant;
       
  1020 		if (val.eof() && !val.fail())
       
  1021 			return variant;
       
  1022 		}
       
  1023 //#endif
       
  1024 	Print(EError,"Syntax error in variant, %s keyword on line %d\n", iReader.Word(0), iReader.CurrentLine());
       
  1025 	return KVariantIndependent;
       
  1026 	}
       
  1027 
       
  1028 TBool CObeyFile::ProcessFile(TInt aAlign, enum EKeyword aKeyword)
       
  1029 //
       
  1030 // Process a parsed line to set up one or more new TRomBuilder entry objects.
       
  1031 // iWord[0] = the keyword (file, primary or secondary)
       
  1032 // iWord[1] = the PC pathname
       
  1033 // iWord[2] = the EPOC pathname
       
  1034 // iWord[3] = start of the file attributes
       
  1035 //
       
  1036 	{
       
  1037 
       
  1038 	TUint imageFlags = 0;
       
  1039 	TUint overrides = 0;
       
  1040 	TBool isPeFile = ETrue;
       
  1041 	TBool isResource = EFalse;
       
  1042 	TBool isNonXIP = EFalse;
       
  1043 	TUint compression = 0;
       
  1044 	TBool callEntryPoint = EFalse;
       
  1045 	TUint hardwareVariant=KVariantIndependent;
       
  1046 	TBool mustBeInSysBin = EFalse;
       
  1047 	TBool tryForSysBin = EFalse;
       
  1048  	TBool warnFlag = EFalse;
       
  1049 
       
  1050 	// do some validation of the keyword
       
  1051 	TInt currentLine = iReader.CurrentLine();
       
  1052 
       
  1053 	switch (aKeyword)
       
  1054 		{
       
  1055 	case EKeywordPrimary:
       
  1056 		imageFlags |= KRomImageFlagPrimary;
       
  1057 		overrides |= KOverrideCodeUnpaged | KOverrideDataUnpaged;
       
  1058 		mustBeInSysBin = gPlatSecEnforceSysBin;
       
  1059  		warnFlag = gEnableStdPathWarning;		
       
  1060 		hardwareVariant=ParseVariant();
       
  1061 		if (iKernelModel==ESingleKernel && !THardwareVariant(hardwareVariant).IsIndependent())
       
  1062 			{
       
  1063 			Print(EError,"Kernel must be independent in single kernel ROMs\n");
       
  1064 			}
       
  1065 		break;
       
  1066 
       
  1067 	case EKeywordSecondary:
       
  1068 		imageFlags |= KRomImageFlagSecondary;
       
  1069 		mustBeInSysBin = gPlatSecEnforceSysBin;
       
  1070  		warnFlag = gEnableStdPathWarning;
       
  1071 		hardwareVariant=ParseVariant();
       
  1072 		break;
       
  1073 
       
  1074 	case EKeywordVariant:
       
  1075 		imageFlags |= KRomImageFlagVariant;
       
  1076 		overrides |= KOverrideCodeUnpaged | KOverrideDataUnpaged;
       
  1077 		mustBeInSysBin = gPlatSecEnforceSysBin;
       
  1078  		warnFlag = gEnableStdPathWarning;		
       
  1079 		hardwareVariant=ParseVariant();
       
  1080 		break;
       
  1081 
       
  1082 	case EKeywordExtension:
       
  1083 		imageFlags |= KRomImageFlagExtension;
       
  1084 		overrides |= KOverrideCodeUnpaged | KOverrideDataUnpaged;
       
  1085 		mustBeInSysBin = gPlatSecEnforceSysBin;
       
  1086  		warnFlag = gEnableStdPathWarning;
       
  1087 		hardwareVariant=ParseVariant();
       
  1088 		break;
       
  1089 
       
  1090 	case EKeywordDevice:
       
  1091 		imageFlags |= KRomImageFlagDevice;
       
  1092 		overrides |= KOverrideCodeUnpaged | KOverrideDataUnpaged;
       
  1093 		mustBeInSysBin = gPlatSecEnforceSysBin;
       
  1094  		warnFlag = gEnableStdPathWarning;		
       
  1095 		hardwareVariant=ParseVariant();
       
  1096 		break;
       
  1097 
       
  1098 	case EKeywordExecutableCompressionMethodBytePair:
       
  1099 		compression=KUidCompressionBytePair;
       
  1100 		
       
  1101 	case EKeywordExecutableCompressionMethodInflate:
       
  1102 	case EKeywordFileCompress:
       
  1103 		compression = compression ? compression : KUidCompressionDeflate;
       
  1104 
       
  1105 	case EKeywordExecutableCompressionMethodNone:	
       
  1106 	case EKeywordFileUncompress:
       
  1107 		isNonXIP = ETrue;
       
  1108 	case EKeywordData:
       
  1109 		iNumberOfDataFiles++;
       
  1110 		isPeFile = EFalse;
       
  1111 		isResource = ETrue;
       
  1112 		hardwareVariant=ParseVariant();
       
  1113 		tryForSysBin = gPlatSecEnforceSysBin;
       
  1114 		break;	 
       
  1115 
       
  1116 	case EKeywordHardwareConfigRepositoryData:
       
  1117 		if(iNumberOfHCRDataFiles){
       
  1118 			Print(EError,"Multiple keywords '%s' on line %d.\n",iReader.Word(0),currentLine);
       
  1119 			return EFalse ;
       
  1120 		}
       
  1121 		compression = EFalse ; 
       
  1122 		overrides |= KOverrideCodeUnpaged | KOverrideDataUnpaged | KOverrideHCRData;
       
  1123 		warnFlag = gEnableStdPathWarning;	 
       
  1124 		iNumberOfHCRDataFiles ++ ;
       
  1125 		isPeFile = EFalse;
       
  1126 		break;
       
  1127 
       
  1128 	case EKeywordDll:
       
  1129 		callEntryPoint = ETrue;
       
  1130 		// and fall through to handling for "file"
       
  1131 	
       
  1132 	case EKeywordFile:
       
  1133 		{
       
  1134 			
       
  1135 		char* nname = NormaliseFileName(iReader.Word(1));
       
  1136 		strupr(nname);
       
  1137 		
       
  1138 		if( gCompressionMethod == 0 || NULL != strstr(nname, ".DLL") || callEntryPoint )
       
  1139 		{
       
  1140 			mustBeInSysBin = gPlatSecEnforceSysBin;
       
  1141  			warnFlag = gEnableStdPathWarning;			
       
  1142 			hardwareVariant=ParseVariant();
       
  1143 		}
       
  1144 		else 
       
  1145 		{
       
  1146 			compression = gCompressionMethod;
       
  1147 			hardwareVariant=ParseVariant();
       
  1148 			tryForSysBin = gPlatSecEnforceSysBin;
       
  1149 		}
       
  1150 		}
       
  1151 		break;
       
  1152 
       
  1153 	default:
       
  1154 		Print(EError,"Unexpected keyword '%s' on line %d.\n",iReader.Word(0),currentLine);
       
  1155 		return EFalse;
       
  1156 		}
       
  1157 
       
  1158 	if (isPeFile)
       
  1159 		iNumberOfPeFiles++;
       
  1160 
       
  1161 	// check the PC file exists
       
  1162 	char* nname = NormaliseFileName(iReader.Word(1));
       
  1163 
       
  1164 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1165 	ifstream test(nname,ios_base::binary );
       
  1166 #else //!__MSVCDOTNET__
       
  1167 	ifstream test(nname,ios::nocreate | ios::binary); 
       
  1168 #endif //__MSVCDOTNET__
       
  1169 
       
  1170 	if (!test.is_open())
       
  1171 		{
       
  1172 		Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
       
  1173 		if(EKeywordHardwareConfigRepositoryData == aKeyword)
       
  1174 			{
       
  1175 			free(nname);
       
  1176 			return EFalse ;
       
  1177 			}
       
  1178 		iMissingFiles++;
       
  1179 		}
       
  1180 		
       
  1181 	if(EKeywordHardwareConfigRepositoryData == aKeyword)
       
  1182 		{ // check hcr file 
       
  1183 
       
  1184 		TUint32 magicWord = 0;
       
  1185 		test.read(reinterpret_cast<char*>(&magicWord),sizeof(TUint32));
       
  1186 		if(0x66524348 != magicWord)
       
  1187 			{
       
  1188 			Print(EError,"Invalid hardware configuration repository data file %s .\n",iReader.Word(1));
       
  1189 			test.close();
       
  1190 			free(nname);
       
  1191 			return EFalse;
       
  1192 			}
       
  1193 
       
  1194 		}
       
  1195 	test.close();
       
  1196 	free(nname);
       
  1197  	
       
  1198 
       
  1199  	TBool endOfName=EFalse;
       
  1200 	TText *epocStartPtr=IsValidFilePath(iReader.Text(2));
       
  1201 	if (epocStartPtr==NULL)
       
  1202 		{
       
  1203 		Print(EError, "Invalid destination path on line %d\n",currentLine);
       
  1204 		return EFalse;
       
  1205 		}
       
  1206 	epocStartPtr = (TText*)NormaliseFileName((const char*)epocStartPtr);
       
  1207 
       
  1208 	if(tryForSysBin)
       
  1209 		{
       
  1210 		if(strnicmp((const char*)epocStartPtr, "system\\bin\\", 11)==0)
       
  1211 			mustBeInSysBin = 1;
       
  1212 		if(strnicmp((const char*)epocStartPtr, "system\\libs\\", 12)==0)
       
  1213 			mustBeInSysBin = 1;
       
  1214 		if(strnicmp((const char*)epocStartPtr, "system\\programs\\", 16)==0)
       
  1215 			mustBeInSysBin = 1;
       
  1216 		}
       
  1217 
       
  1218 	static const char sysBin[] = "sys\\bin\\";
       
  1219 	static const int sysBinLength = sizeof(sysBin)-1;
       
  1220 
       
  1221  	if (strnicmp((const char*)epocStartPtr, sysBin, sysBinLength)!=0)
       
  1222  	{		
       
  1223  		if(mustBeInSysBin)
       
  1224 		{
       
  1225  			TInt len = strlen((char*)epocStartPtr);
       
  1226  			TInt i = len;
       
  1227  			while(--i>=0) if(epocStartPtr[i]=='\\') break;
       
  1228  			++i;
       
  1229  			char* old = (char*)epocStartPtr;
       
  1230  			epocStartPtr = (TText*)malloc(sysBinLength+(len-i)+1);
       
  1231  			strcpy((char*)epocStartPtr,sysBin);
       
  1232  			strcat((char*)epocStartPtr,old+i);
       
  1233 
       
  1234  			Print(EDiagnostic, "%s moved to %s\n", old, epocStartPtr);
       
  1235  			delete old;
       
  1236 		}
       
  1237  		else if (warnFlag)
       
  1238  		{
       
  1239  			Print(EWarning, "Outside standard path at %s\n", epocStartPtr);
       
  1240  		}		
       
  1241  	}	
       
  1242 
       
  1243 	TText *epocEndPtr=epocStartPtr;
       
  1244 	AUTO_FREE(epocStartPtr);	
       
  1245 		
       
  1246 	TRomNode* dir=iRootDirectory;
       
  1247 	TRomNode* subDir=0;
       
  1248 	TRomBuilderEntry *file=0;
       
  1249 	while (!endOfName)
       
  1250 		{
       
  1251 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1252 		if (endOfName) // file
       
  1253 			{
       
  1254 			TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr,hardwareVariant);
       
  1255 			if (alreadyExists) // duplicate file
       
  1256 				{
       
  1257 				Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1258 				return EFalse;
       
  1259 				}
       
  1260 			file = new TRomBuilderEntry(iReader.Word(1),epocStartPtr);
       
  1261 			file->iRomImageFlags = imageFlags;
       
  1262 			file->iResource = isResource;
       
  1263 			file->iNonXIP = isNonXIP;
       
  1264 			file->iCompression = compression;
       
  1265 			
       
  1266 			file->iArea = iAreaSet.FindByName(AreaSet::KDefaultAreaName);
       
  1267 			file->iRomSectionNumber = iCurrentSectionNumber;
       
  1268 			file->iHardwareVariant = hardwareVariant;
       
  1269 			file->iOverrideFlags |= overrides;
       
  1270 			if (callEntryPoint)
       
  1271 				file->SetCallEntryPoint(callEntryPoint);
       
  1272 			file->iAlignment=aAlign;
       
  1273 			TUint32 uid;
       
  1274 			file->iBareName = SplitFileName((const char*)file->iName, uid, file->iVersionInName, file->iVersionPresentInName);
       
  1275 			assert(uid==0 && !(file->iVersionPresentInName & EUidPresent));
       
  1276 			if (strchr(file->iBareName, '{') || strchr(file->iBareName, '}'))
       
  1277 				{
       
  1278 				Print(EError, "Illegal character in name %s on line %d\n", file->iName, iReader.CurrentLine());
       
  1279 				delete file;
       
  1280 				return EFalse;
       
  1281 				}
       
  1282 			TRomNode* node=new TRomNode(epocStartPtr, file);
       
  1283 			if (node==0){
       
  1284 				delete file;
       
  1285 				return EFalse;
       
  1286 			}
       
  1287 				
       
  1288 			TInt r=ParseFileAttributes(node, file);
       
  1289 			if (r!=KErrNone){
       
  1290 				delete file;
       
  1291 				delete node;
       
  1292 				return EFalse;
       
  1293 			}
       
  1294 
       
  1295 			TRACE(TAREA, Print(EScreen, "File %s area '%s'\n", iReader.Word(1), file->iArea->Name()));
       
  1296 
       
  1297 			// Apply some specific overrides to the primary
       
  1298 			if (imageFlags & KRomImageFlagPrimary)
       
  1299 				{
       
  1300 				if (file->iCodeAlignment < iPageSize)
       
  1301 					file->iCodeAlignment = iPageSize;	// Kernel code is at least page aligned
       
  1302 				file->iHeapSizeMin = iKernHeapMin;
       
  1303 				file->iHeapSizeMax = iKernHeapMax;
       
  1304 				file->iOverrideFlags |= KOverrideHeapMin+KOverrideHeapMax;
       
  1305 				}
       
  1306 
       
  1307 			if (!file->iPatched)
       
  1308 				dir->AddFile(node);	// to ROM directory structure, though possibly hidden
       
  1309 			if (isPeFile)
       
  1310 				TRomNode::AddExecutableFile(iLastExecutable, node);
       
  1311 			
       
  1312 			AddFile(file);
       
  1313 			}		 
       
  1314 		else // directory
       
  1315 			{
       
  1316 			subDir = dir->FindInDirectory(epocStartPtr);
       
  1317 			if (!subDir) // sub directory does not exist
       
  1318 				{
       
  1319 				subDir = dir->NewSubDir(epocStartPtr);
       
  1320 				if (!subDir)
       
  1321 					return EFalse;
       
  1322 				}
       
  1323 			dir=subDir;
       
  1324 			epocStartPtr = epocEndPtr;
       
  1325 			}
       
  1326 		}
       
  1327 	return ETrue;
       
  1328 	}
       
  1329 
       
  1330 
       
  1331 void CObeyFile::AddFile(TRomBuilderEntry* aFile)
       
  1332 	{
       
  1333 	aFile->iArea->AddFile(aFile);
       
  1334 
       
  1335 	*iNextFilePtrPtr = aFile;
       
  1336 	iNextFilePtrPtr = &(aFile->iNext);
       
  1337 	}
       
  1338 
       
  1339 
       
  1340 TBool CObeyFile::ProcessRenaming(enum EKeyword aKeyword)
       
  1341 	{
       
  1342 	TUint hardwareVariant=ParseVariant();
       
  1343 
       
  1344 	// find existing file
       
  1345 	TBool endOfName=EFalse;
       
  1346 
       
  1347 	// Store the current name and new name to maintain renamed file map
       
  1348 	String currentName=iReader.Word(1);
       
  1349 	String newName=iReader.Word(2);
       
  1350 
       
  1351 	TText *epocStartPtr=IsValidFilePath(iReader.Text(1));
       
  1352 	if (epocStartPtr==NULL)
       
  1353 		{
       
  1354 		Print(EError, "Invalid source path on line %d\n",iReader.CurrentLine());
       
  1355 		return EFalse;
       
  1356 		}
       
  1357 	epocStartPtr = (TText*)NormaliseFileName((const char*)epocStartPtr);
       
  1358 	TText *epocEndPtr=epocStartPtr;
       
  1359 	AUTO_FREE(epocStartPtr);
       
  1360 
       
  1361 	char saved_srcname[257];
       
  1362 	strcpy(saved_srcname, iReader.Word(1));
       
  1363 
       
  1364 	TRomNode* dir=iRootDirectory;
       
  1365 	TRomNode* existingFile=0;
       
  1366 	while (!endOfName)
       
  1367 		{
       
  1368 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1369 		if (endOfName) // file
       
  1370 			{
       
  1371 			existingFile=dir->FindInDirectory(epocStartPtr,hardwareVariant);
       
  1372 			if (existingFile)
       
  1373 				{
       
  1374 				TInt fileCount=0;
       
  1375 				TInt dirCount=0;
       
  1376 				existingFile->CountDirectory(fileCount, dirCount);
       
  1377 				if (dirCount != 0 || fileCount != 0)
       
  1378 					{
       
  1379 					Print(EError, "Keyword %s not applicable to directories - line %d\n",iReader.Word(0),iReader.CurrentLine());
       
  1380 					return EFalse;
       
  1381 					}
       
  1382 				}
       
  1383 			}
       
  1384 		else // directory
       
  1385 			{
       
  1386 			TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
       
  1387 			if (!subDir) // sub directory does not exist
       
  1388 				break;
       
  1389 			dir=subDir;
       
  1390 			epocStartPtr = epocEndPtr;
       
  1391 			}
       
  1392 		}
       
  1393 	if (aKeyword == EKeywordHide)
       
  1394 		{
       
  1395 		if (!existingFile)
       
  1396 			{
       
  1397 			Print(EWarning, "Hiding non-existent file %s on line %d\n", 
       
  1398 				saved_srcname, iReader.CurrentLine());
       
  1399 			// Just a warning, as we've achieved the right overall effect.
       
  1400 			}
       
  1401 		else
       
  1402 			{
       
  1403 			existingFile->iHidden = ETrue;
       
  1404 			}
       
  1405 		return ETrue;
       
  1406 		}
       
  1407 
       
  1408 	if (!existingFile)
       
  1409 		{
       
  1410 		Print(EError, "Can't %s non-existent source file %s on line %d\n",
       
  1411 			iReader.Word(0), saved_srcname, iReader.CurrentLine());
       
  1412 		return EFalse;
       
  1413 		}
       
  1414 
       
  1415 	epocStartPtr=IsValidFilePath(iReader.Text(2));
       
  1416 	epocEndPtr=epocStartPtr;
       
  1417 	endOfName=EFalse;
       
  1418 	if (epocStartPtr==NULL)
       
  1419 		{
       
  1420 		Print(EError, "Invalid destination path on line %d\n",iReader.CurrentLine());
       
  1421 		return EFalse;
       
  1422 		}
       
  1423 
       
  1424 	TRomNode* newdir=iRootDirectory;
       
  1425 	while (!endOfName)
       
  1426 		{
       
  1427 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1428 		if (endOfName) // file
       
  1429 			{
       
  1430 			TRomNode* alreadyExists=newdir->FindInDirectory(epocStartPtr,existingFile->HardwareVariant());
       
  1431 			if (alreadyExists) // duplicate file
       
  1432 				{
       
  1433 				Print(EError, "Duplicate file for %s on line %d\n",saved_srcname,iReader.CurrentLine());
       
  1434 				return EFalse;
       
  1435 				}
       
  1436 			}
       
  1437 		else // directory
       
  1438 			{
       
  1439 			TRomNode* subDir = newdir->FindInDirectory(epocStartPtr);
       
  1440 			if (!subDir) // sub directory does not exist
       
  1441 				{
       
  1442 				subDir = newdir->NewSubDir(epocStartPtr);
       
  1443 				if (!subDir)
       
  1444 					return EFalse;
       
  1445 				}
       
  1446 			newdir=subDir;
       
  1447 			epocStartPtr = epocEndPtr;
       
  1448 			}
       
  1449 		}
       
  1450 
       
  1451 	if (aKeyword == EKeywordRename)
       
  1452 		{
       
  1453 		// rename => remove existingFile and insert into tree at new place
       
  1454 		// has no effect on the iNextExecutable or iNextNodeForSameFile links
       
  1455 
       
  1456 		TInt r=ParseFileAttributes(existingFile, existingFile->iRomFile->iRbEntry);
       
  1457 		if (r!=KErrNone)
       
  1458 			return EFalse;
       
  1459 		r = existingFile->Rename(dir, newdir, epocStartPtr);
       
  1460 		if (r==KErrBadName)
       
  1461 			{
       
  1462 			Print(EError, "Bad name %s at line %d\n", epocStartPtr, iReader.CurrentLine());
       
  1463 			return EFalse;
       
  1464 			}
       
  1465 		else if (r==KErrArgument)
       
  1466 			{
       
  1467 			Print(EError, "Version in name %s does not match version in file header at line %d\n", epocStartPtr, iReader.CurrentLine());
       
  1468 			return EFalse;
       
  1469 			}
       
  1470 		// Store the current and new name of file in the renamed file map.
       
  1471 		iPatchData->AddToRenamedFileMap(currentName, newName);
       
  1472 		return ETrue;
       
  1473 		}
       
  1474 	
       
  1475 	// alias => create new TRomNode entry and insert into tree
       
  1476 
       
  1477 	TRomNode* node = new TRomNode(epocStartPtr, existingFile);
       
  1478 	if (node == 0)
       
  1479 		{
       
  1480 		Print(EError, "Out of memory\n");
       
  1481 		return EFalse;
       
  1482 		}
       
  1483 
       
  1484 	TInt r = node->Alias(existingFile, iLastExecutable);
       
  1485 	if (r==KErrBadName)
       
  1486 		{
       
  1487 		Print(EError, "Bad name %s at line %d\n", epocStartPtr, iReader.CurrentLine());
       
  1488 		return EFalse;
       
  1489 		}
       
  1490 	else if (r==KErrArgument)
       
  1491 		{
       
  1492 		Print(EError, "Version in name %s does not match version in file header at line %d\n", epocStartPtr, iReader.CurrentLine());
       
  1493 		return EFalse;
       
  1494 		}
       
  1495 	r=ParseFileAttributes(node, 0);
       
  1496 	if (r!=KErrNone)
       
  1497 		return EFalse;
       
  1498 
       
  1499 	newdir->AddFile(node);	// to ROM directory structure, though possibly hidden
       
  1500 
       
  1501 	return ETrue;
       
  1502 	}
       
  1503 
       
  1504 
       
  1505 TInt ParsePagingPolicy(const char* policy)
       
  1506 	{
       
  1507 	if(stricmp(policy,"NOPAGING")==0)
       
  1508 		return EKernelConfigPagingPolicyNoPaging;
       
  1509 	else if (stricmp(policy,"ALWAYSPAGE")==0)
       
  1510 		return EKernelConfigPagingPolicyAlwaysPage;
       
  1511 	else if(stricmp(policy,"DEFAULTUNPAGED")==0)
       
  1512 		return EKernelConfigPagingPolicyDefaultUnpaged;
       
  1513 	else if(stricmp(policy,"DEFAULTPAGED")==0)
       
  1514 		return EKernelConfigPagingPolicyDefaultPaged;
       
  1515 	return KErrArgument;
       
  1516 	}
       
  1517 
       
  1518 
       
  1519 TBool CObeyFile::ProcessKeyword(enum EKeyword aKeyword)
       
  1520 	{
       
  1521 	TUint hardwareVariant=KVariantIndependent;
       
  1522 
       
  1523 	#ifdef __TOOLS2__
       
  1524 	istringstream val(iReader.Word(1));
       
  1525 	#else
       
  1526 	istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  1527 	#endif
       
  1528 
       
  1529 #if defined(__MSVCDOTNET__) || defined (__TOOLS2__)
       
  1530 	val >> setbase(0);
       
  1531 #endif //__MSVCDOTNET__
       
  1532 
       
  1533 	TBool success = ETrue;
       
  1534 
       
  1535 	switch (aKeyword)
       
  1536 		{
       
  1537 	case EKeywordUnicode:
       
  1538 		Unicode=ETrue;
       
  1539 		break;
       
  1540 	case EKeywordAscii:
       
  1541 		Unicode=EFalse;
       
  1542 		break;
       
  1543 
       
  1544 	case EKeywordSingleKernel:
       
  1545 		iKernelModel=ESingleKernel;
       
  1546 		break;
       
  1547 	case EKeywordMultiKernel:
       
  1548 		iKernelModel=EMultipleKernels;
       
  1549 		break;
       
  1550 
       
  1551 	case EKeywordBootBinary:
       
  1552 		iReader.CopyWord(1, iBootFileName);
       
  1553 		break;
       
  1554 	case EKeywordRomName:
       
  1555 		iReader.CopyWord(1, iRomFileName);
       
  1556 		break;
       
  1557 	case EKeywordRomNameOdd:
       
  1558 		iReader.CopyWord(1, iRomOddFileName);
       
  1559 		break;
       
  1560 	case EKeywordRomNameEven:
       
  1561 		iReader.CopyWord(1, iRomEvenFileName);
       
  1562 		break;
       
  1563 	case EKeywordSRecordFileName:
       
  1564 		iReader.CopyWord(1, iSRecordFileName);
       
  1565 		break;
       
  1566 
       
  1567 	case EKeywordRomLinearBase:
       
  1568 		val >> iRomLinearBase;
       
  1569 		break;
       
  1570 	case EKeywordRomSize:
       
  1571 		val >> iRomSize;
       
  1572 		break;
       
  1573 	case EKeywordRomAlign:
       
  1574 		val >> iRomAlign;
       
  1575 		break;
       
  1576 	case EKeywordKernelDataAddress:
       
  1577 		val >> iKernDataRunAddress;
       
  1578 		break;
       
  1579 	case EKeywordKernelHeapMin:
       
  1580 		val >> iKernHeapMin;
       
  1581 		break;
       
  1582 	case EKeywordKernelHeapMax:
       
  1583 		val >> iKernHeapMax;
       
  1584 		break;
       
  1585 	case EKeywordDataAddress:
       
  1586 		val >> iDataRunAddress;
       
  1587 		break;
       
  1588 	case EKeywordDefaultStackReserve:
       
  1589 		val >> iDefaultStackReserve;
       
  1590 		break;
       
  1591 	case EKeywordVersion:
       
  1592 		val >> iVersion;
       
  1593 		break;
       
  1594 	case EKeywordSRecordBase:
       
  1595 		val >> iSRecordBase;
       
  1596 		break;
       
  1597 	case EKeywordRomChecksum:
       
  1598 		val >> iCheckSum;
       
  1599 		break;
       
  1600 	case EKeywordHardware:
       
  1601 		val >> iHardware;
       
  1602 		break;
       
  1603 	case EKeywordLanguages:
       
  1604 		iReader.ProcessLanguages(iLanguage);
       
  1605 		break;
       
  1606 	case EKeywordTime:
       
  1607 		iReader.ProcessTime(iTime);
       
  1608 		break;
       
  1609 	case EKeywordDllDataTop:
       
  1610 		val >> iDllDataTop;
       
  1611 		break;
       
  1612 
       
  1613 	case EKeywordMemModel:
       
  1614 		{
       
  1615 		char* arg1=iReader.Word(1);
       
  1616 		char* arg2=iReader.Word(2);
       
  1617 		char* arg3=iReader.Word(3);
       
  1618 		char* arg4=iReader.Word(4);
       
  1619 		if (strnicmp(arg1, "moving", 6)==0)
       
  1620 			iMemModel=E_MM_Moving;
       
  1621 		else if (strnicmp(arg1, "direct", 6)==0)
       
  1622 			iMemModel=E_MM_Direct;
       
  1623 		else if (strnicmp(arg1, "multiple", 8)==0)
       
  1624 			iMemModel=E_MM_Multiple;
       
  1625 		else if (strnicmp(arg1, "flexible", 8)==0)
       
  1626 			iMemModel=E_MM_Flexible;
       
  1627 		else
       
  1628 			{
       
  1629 			Print(EError, "Unknown memory model specified\n");
       
  1630 			success = EFalse;
       
  1631 			}
       
  1632 		if (strlen(arg2))
       
  1633 			{
       
  1634 			#ifdef __TOOLS2__
       
  1635 			istringstream arg2s(arg2);
       
  1636 			#else
       
  1637 			istrstream arg2s(arg2,strlen(arg2));
       
  1638 			#endif
       
  1639 
       
  1640 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1641 			arg2s >> setbase(0);
       
  1642 #endif //__MSVCDOTNET__
       
  1643 
       
  1644 			arg2s >> iChunkSize;
       
  1645 			}
       
  1646 		if (iMemModel!=E_MM_Direct && strlen(arg3))
       
  1647 			{
       
  1648 				#ifdef __TOOLS2__
       
  1649 			istringstream arg3s(arg3);
       
  1650 			#else
       
  1651 			istrstream arg3s(arg3,strlen(arg3));
       
  1652 			#endif
       
  1653 
       
  1654 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1655 			arg3s >> setbase(0);
       
  1656 #endif //__MSVCDOTNET__
       
  1657 
       
  1658 			arg3s >> iPageSize;
       
  1659 			}
       
  1660 		else if (iMemModel==E_MM_Direct)
       
  1661 			iPageSize=iChunkSize;
       
  1662 		if (iMemModel!=E_MM_Direct && strlen(arg4))
       
  1663 			{
       
  1664 			#ifdef __TOOLS2__
       
  1665 			istringstream arg4s(arg4);
       
  1666 			#else
       
  1667 			istrstream arg4s(arg4,strlen(arg4));
       
  1668 			#endif
       
  1669 
       
  1670 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1671 			arg4s >> setbase(0);
       
  1672 #endif //__MSVCDOTNET__
       
  1673 
       
  1674 			arg4s >> iVirtualAllocSize;
       
  1675 			}
       
  1676 		else
       
  1677 			iVirtualAllocSize = iPageSize;
       
  1678 		
       
  1679 		break;
       
  1680 		}
       
  1681 	case EKeywordNoWrapper:
       
  1682 		if (gHeaderType<0)
       
  1683 			gHeaderType=0;
       
  1684 		break;
       
  1685 	case EKeywordEpocWrapper:
       
  1686 		if (gHeaderType<0)
       
  1687 			gHeaderType=1;
       
  1688 		break;
       
  1689 	case EKeywordCoffWrapper:
       
  1690 		if (gHeaderType<0)
       
  1691 			gHeaderType=2;
       
  1692 		break;
       
  1693 
       
  1694 	case EKeywordPlatSecEnforcement:
       
  1695 		ParseBoolArg(gPlatSecEnforcement,iReader.Word(1));
       
  1696 		if(gPlatSecEnforcement)
       
  1697 			iKernelConfigFlags |= EKernelConfigPlatSecEnforcement;
       
  1698 		else
       
  1699 			iKernelConfigFlags &= ~EKernelConfigPlatSecEnforcement;
       
  1700 		break;
       
  1701 	case EKeywordPlatSecDiagnostics:
       
  1702 		ParseBoolArg(gPlatSecDiagnostics,iReader.Word(1));
       
  1703 		if(gPlatSecDiagnostics)
       
  1704 			iKernelConfigFlags |= EKernelConfigPlatSecDiagnostics;
       
  1705 		else
       
  1706 			iKernelConfigFlags &= ~EKernelConfigPlatSecDiagnostics;
       
  1707 		break;
       
  1708 	case EKeywordPlatSecProcessIsolation:
       
  1709 		{
       
  1710 		TInt processIsolation;
       
  1711 		ParseBoolArg(processIsolation,iReader.Word(1));
       
  1712 		if(processIsolation)
       
  1713 			iKernelConfigFlags |= EKernelConfigPlatSecProcessIsolation;
       
  1714 		else
       
  1715 			iKernelConfigFlags &= ~EKernelConfigPlatSecProcessIsolation;
       
  1716 		break;
       
  1717 		}
       
  1718 	case EKeywordPlatSecEnforceSysBin:
       
  1719 		{
       
  1720 		ParseBoolArg(gPlatSecEnforceSysBin,iReader.Word(1));
       
  1721 		if(gPlatSecEnforceSysBin)
       
  1722 			iKernelConfigFlags |= EKernelConfigPlatSecEnforceSysBin;
       
  1723 		else
       
  1724 			iKernelConfigFlags &= ~EKernelConfigPlatSecEnforceSysBin;
       
  1725 		break;
       
  1726 		}
       
  1727 	case EKeywordPlatSecDisabledCaps:
       
  1728 		if(iPlatSecDisabledCapsParsed)
       
  1729 			Print(EWarning, "PlatSecDisabledCaps redefined - previous values lost\n");
       
  1730 		{
       
  1731 		ParseCapabilitiesArg(iPlatSecDisabledCaps, iReader.Word(1));
       
  1732 		gPlatSecDisabledCaps = iPlatSecDisabledCaps;
       
  1733 		iPlatSecDisabledCapsParsed=ETrue;
       
  1734 		}
       
  1735 		break;
       
  1736 	case EKeywordPagingPolicy:
       
  1737 		{
       
  1738 		if(iPagingPolicyParsed)
       
  1739 			Print(EWarning, "PagingPolicy redefined - previous PagingPolicy values lost\n");
       
  1740 		if(iDataPagingPolicyParsed)
       
  1741 			Print(EWarning, "PagingPolicy defined - previous DataPagingPolicy values lost\n");
       
  1742 		if(iCodePagingPolicyParsed)
       
  1743 			Print(EWarning, "PagingPolicy defined - previous DataPagingPolicy values lost\n");
       
  1744 		iPagingPolicyParsed = true;
       
  1745 		iKernelConfigFlags &= ~(EKernelConfigCodePagingPolicyMask|EKernelConfigDataPagingPolicyMask);
       
  1746 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1747 		if(policy<0)
       
  1748 			{
       
  1749 			Print(EError,"Unrecognised option for PAGINGPOLICY keyword\n");
       
  1750 			success = false;
       
  1751 			}
       
  1752 		else 	{
       
  1753 #ifndef SYMBIAN_WRITABLE_DATA_PAGING
       
  1754 			if ((policy != EKernelConfigPagingPolicyNoPaging) && (iMemModel == E_MM_Flexible))
       
  1755 				Print(EWarning, "SYMBIAN_WRITABLE_DATA_PAPING is not defined. Writable data paging is not warranted on this version of Symbian.");
       
  1756 #endif
       
  1757 			iKernelConfigFlags |= policy << EKernelConfigCodePagingPolicyShift;
       
  1758 			iKernelConfigFlags |= policy << EKernelConfigDataPagingPolicyShift;
       
  1759 			}
       
  1760 		}
       
  1761 		break;
       
  1762 	case EKeywordCodePagingPolicy:
       
  1763 		{
       
  1764 		if(iCodePagingPolicyParsed)
       
  1765 			Print(EWarning, "CodePagingPolicy redefined - previous CodePagingPolicy values lost\n");
       
  1766 		if(iPagingPolicyParsed)
       
  1767 			Print(EWarning, "CodePagingPolicy defined - previous PagingPolicy values lost\n");
       
  1768 		iCodePagingPolicyParsed = true;
       
  1769 		iKernelConfigFlags &= ~EKernelConfigCodePagingPolicyMask;
       
  1770 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1771 		if(policy<0)
       
  1772 			{
       
  1773 			Print(EError,"Unrecognised option for CODEPAGINGPOLICY keyword\n");
       
  1774 			success = false;
       
  1775 			}
       
  1776 		else
       
  1777 			iKernelConfigFlags |= policy << EKernelConfigCodePagingPolicyShift;
       
  1778 		}
       
  1779 		break;
       
  1780 	case EKeywordDataPagingPolicy:
       
  1781 		{
       
  1782 		if(iDataPagingPolicyParsed)
       
  1783 			Print(EWarning, "DataPagingPolicy redefined - previous DataPagingPolicy values lost\n");
       
  1784 		if(iPagingPolicyParsed)
       
  1785 			Print(EWarning, "DataPagingPolicy defined - previous PagingPolicy values lost\n");
       
  1786 		iDataPagingPolicyParsed = true;
       
  1787 		iKernelConfigFlags &= ~EKernelConfigDataPagingPolicyMask;
       
  1788 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1789 		if(policy<0)
       
  1790 			{
       
  1791 			Print(EError,"Unrecognised option for DATAPAGINGPOLICY keyword\n");
       
  1792 			success = false;
       
  1793 			}
       
  1794 		else
       
  1795 #ifndef SYMBIAN_WRITABLE_DATA_PAGING
       
  1796 			if ((policy != EKernelConfigPagingPolicyNoPaging) && (iMemModel == E_MM_Flexible))
       
  1797 				Print(EWarning, "SYMBIAN_WRITABLE_DATA_PAPING is not defined. Writable data paging is not warranted on this version of Symbian.");
       
  1798 #endif
       
  1799 			iKernelConfigFlags |= policy << EKernelConfigDataPagingPolicyShift;
       
  1800 		}
       
  1801 		break;
       
  1802 	case EKeywordPagingOverride:
       
  1803 		{
       
  1804 		if(iPagingOverrideParsed)
       
  1805 			Print(EWarning, "PagingOverride redefined - previous PagingOverride values lost\n");
       
  1806 		if(iCodePagingOverrideParsed)
       
  1807 			Print(EWarning, "PagingOverride defined - previous CodePagingOverride valus lost\n");
       
  1808 		if(iDataPagingOverrideParsed)
       
  1809 			Print(EWarning, "PagingOverride defined - previous DataPagingOverride values lostn");
       
  1810 		iPagingOverrideParsed = true;
       
  1811 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1812 		if(policy<0)
       
  1813 			{
       
  1814 			Print(EError,"Unrecognised option for PAGINGOVERRIDE keyword\n");
       
  1815 			success = false;
       
  1816 			}
       
  1817 		else
       
  1818 			{
       
  1819 			gCodePagingOverride = policy;
       
  1820 			gDataPagingOverride = policy;
       
  1821 			}
       
  1822 		}
       
  1823 		break;
       
  1824 	case EKeywordCodePagingOverride:
       
  1825 		{
       
  1826 		if(iCodePagingOverrideParsed)
       
  1827 			Print(EWarning, "CodePagingOverride redefined - previous CodePagingOverride values lost\n");
       
  1828 		if(iPagingOverrideParsed)
       
  1829 			Print(EWarning, "CodePagingOverride defined - previous PagingOverride values lost\n");
       
  1830 		iCodePagingOverrideParsed = true;
       
  1831 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1832 		if(policy<0)
       
  1833 			{
       
  1834 			Print(EError,"Unrecognised option for CODEPAGINGOVERRIDE keyword\n");
       
  1835 			success = false;
       
  1836 			}
       
  1837 		else
       
  1838 			gCodePagingOverride = policy;
       
  1839 		}
       
  1840 		break;
       
  1841 	case EKeywordDataPagingOverride:
       
  1842 		{
       
  1843 		if(iDataPagingOverrideParsed)
       
  1844 			Print(EWarning, "DataPagingOverride redefined - previous DataPagingOverride values lost\n");
       
  1845 		if(iPagingOverrideParsed)
       
  1846 			Print(EWarning, "DataPagingOverride defined - previous PagingOverride values lost\n");
       
  1847 		iDataPagingOverrideParsed = true;
       
  1848 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1849 		if(policy<0)
       
  1850 			{
       
  1851 			Print(EError,"Unrecognised option for DATAPAGINGOVERRIDE keyword\n");
       
  1852 			success = false;
       
  1853 			}
       
  1854 		else
       
  1855 			gDataPagingOverride = policy;
       
  1856 		}
       
  1857 		break;
       
  1858 	case EKeywordDemandPagingConfig:
       
  1859 		{
       
  1860 		memset(&gDemandPagingConfig,0,sizeof(gDemandPagingConfig));
       
  1861 		val >> gDemandPagingConfig.iMinPages;
       
  1862 		if(strlen(iReader.Word(2)))
       
  1863 			{
       
  1864 			#ifdef __TOOLS2__
       
  1865 			istringstream val(iReader.Word(2));
       
  1866 			#else
       
  1867 			istrstream val(iReader.Word(2),strlen(iReader.Word(2)));
       
  1868 		    #endif
       
  1869 			val >> gDemandPagingConfig.iMaxPages;
       
  1870 			if(strlen(iReader.Word(3)))
       
  1871 				{
       
  1872 				#ifdef __TOOLS2__
       
  1873 				istringstream val(iReader.Word(3));
       
  1874 				#else
       
  1875 				istrstream val(iReader.Word(3),strlen(iReader.Word(3)));
       
  1876 				#endif
       
  1877 				val >> gDemandPagingConfig.iYoungOldRatio;
       
  1878 				for(int i=0; i<=2; i++)
       
  1879 					{
       
  1880 					if(!strlen(iReader.Word(4+i)))
       
  1881 						break;
       
  1882 					#ifdef __TOOLS2__
       
  1883 					istringstream val(iReader.Word(4+i));
       
  1884 					#else
       
  1885 					istrstream val(iReader.Word(4+i),strlen(iReader.Word(4+i)));
       
  1886 					#endif
       
  1887 					val >> gDemandPagingConfig.iSpare[i];
       
  1888 					}
       
  1889 				}
       
  1890 			}
       
  1891 		if(gDemandPagingConfig.iMaxPages && gDemandPagingConfig.iMaxPages<gDemandPagingConfig.iMinPages)
       
  1892 			{
       
  1893 			Print(EError,"DemandPagingConfig maxPages must be >= minPages\n");
       
  1894 			success = EFalse;
       
  1895 			break;
       
  1896 			}
       
  1897 		}
       
  1898 		break;
       
  1899 	case EKeywordPagedRom:
       
  1900 		gPagedRom = ETrue;
       
  1901 		break;
       
  1902 
       
  1903 	case EKeywordTrace:
       
  1904 		val >> TraceMask;
       
  1905 		break;
       
  1906 
       
  1907 	case EKeywordKernelTrace:
       
  1908 		{
       
  1909 		TInt i;
       
  1910 		val >> iTraceMask[0];
       
  1911 		i=1;
       
  1912 		while(strlen(iReader.Word(i+1)) && i<KNumTraceMaskWords)
       
  1913 			{
       
  1914 			#ifdef __TOOLS2__
       
  1915 			istringstream val(iReader.Word(i+1));
       
  1916 			#else
       
  1917 			istrstream val(iReader.Word(i+1),strlen(iReader.Word(i+1)));
       
  1918 			#endif
       
  1919 			#if defined(__MSVCDOTNET__) || defined (__TOOLS2__)
       
  1920  				val >> setbase(0);
       
  1921 			#endif
       
  1922 			val >> iTraceMask[i];
       
  1923 			++i;
       
  1924 			}
       
  1925 		}
       
  1926 		break;
       
  1927 
       
  1928 	case EKeywordBTrace:
       
  1929 		{
       
  1930 		TUint i; 
       
  1931 		val >> iInitialBTraceFilter[0];
       
  1932 		i=1;
       
  1933 		while(strlen(iReader.Word(i+1)) && i<sizeof(iInitialBTraceFilter)/sizeof(TUint32))
       
  1934 			{
       
  1935 			#ifdef __TOOLS2__
       
  1936 			istringstream val(iReader.Word(i+1));
       
  1937 			#else
       
  1938 			istrstream val(iReader.Word(i+1),strlen(iReader.Word(i+1)));
       
  1939 			#endif
       
  1940 			#if defined(__MSVCDOTNET__) || defined (__TOOLS2__)
       
  1941  				val >> setbase(0);
       
  1942 			#endif
       
  1943 			val >> iInitialBTraceFilter[i];
       
  1944 			++i;
       
  1945 			}
       
  1946 		}
       
  1947 		break;
       
  1948 
       
  1949 	case EKeywordBTraceMode:
       
  1950 		val >> iInitialBTraceMode;
       
  1951 		break;
       
  1952 
       
  1953 	case EKeywordBTraceBuffer:
       
  1954 		val >> iInitialBTraceBuffer;
       
  1955 		break;
       
  1956 
       
  1957 	case EKeywordDebugPort:
       
  1958 		if (iDebugPortParsed)
       
  1959 			Print(EWarning, "DEBUGPORT redefined - previous value lost\n");
       
  1960 		val >> iDebugPort;
       
  1961 		iDebugPortParsed = ETrue;
       
  1962 		break;
       
  1963 
       
  1964 	case EKeywordCompress:
       
  1965 		gEnableCompress=ETrue; // Set ROM Compression on.
       
  1966 		break;
       
  1967 
       
  1968 	case EKeywordCollapse:
       
  1969 		if (strnicmp(iReader.Word(1), "arm", 3)!=0 || strnicmp(iReader.Word(2), "gcc", 3)!=0)
       
  1970 			{
       
  1971 			Print(EWarning, "COLLAPSE only supported for ARM and GCC - keyword ignored\n");
       
  1972 			}
       
  1973 		else
       
  1974 			{
       
  1975 			TInt cm;
       
  1976 			#ifdef __TOOLS2__
       
  1977 			istringstream cmval(iReader.Word(3));
       
  1978 			#else
       
  1979 			istrstream cmval(iReader.Word(3),strlen(iReader.Word(3)));
       
  1980 			#endif
       
  1981 
       
  1982 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1983 			cmval >> setbase(0);
       
  1984 #endif //__MSVCDOTNET__
       
  1985 
       
  1986 			cmval>>cm;
       
  1987 			if (cm<0 || cm>ECollapseAllChainBranches)
       
  1988 				{
       
  1989 				Print(EWarning, "COLLAPSE mode unrecognised - keyword ignored\n");
       
  1990 				}
       
  1991 			else
       
  1992 				iCollapseMode=cm;
       
  1993 			}
       
  1994 		break;
       
  1995 
       
  1996 	case EKeywordPrimary:
       
  1997 		iNumberOfPrimaries++;
       
  1998 		break;
       
  1999 	case EKeywordVariant:
       
  2000 		hardwareVariant=ParseVariant();
       
  2001 		if (THardwareVariant(hardwareVariant).IsVariant())
       
  2002 			{
       
  2003 			iNumberOfVariants++;
       
  2004 			TUint layer=THardwareVariant(hardwareVariant).Layer();
       
  2005 			TUint vmask=THardwareVariant(hardwareVariant).VMask();
       
  2006 			iAllVariantsMask[layer] |= vmask;
       
  2007 			}
       
  2008 		else
       
  2009 			{
       
  2010 			Print(EError,"Variant DLLs must belong to variant layer - line %d\n", iReader.CurrentLine());
       
  2011 			break;
       
  2012 			}
       
  2013 
       
  2014 		break;
       
  2015 	case EKeywordExtension:
       
  2016 		iNumberOfExtensions++;
       
  2017 		break;
       
  2018 	case EKeywordDevice:
       
  2019 		iNumberOfDevices++;
       
  2020 		break;
       
  2021 
       
  2022 	case EKeywordKernelRomName:
       
  2023 		Print(EError,"Keyword '%s' only valid in extension ROMs - line %d\n", iReader.Word(0), iReader.CurrentLine());
       
  2024 		break;
       
  2025 
       
  2026 	case EKeywordArea:
       
  2027 		if(! ParseAreaKeyword())
       
  2028 			success = EFalse;
       
  2029 		break;
       
  2030 
       
  2031 	case EKeywordExecutableCompressionMethodNone:
       
  2032 		gCompressionMethod = 0;
       
  2033 		break;
       
  2034 		
       
  2035 	case EKeywordExecutableCompressionMethodInflate:
       
  2036 		gCompressionMethod = KUidCompressionDeflate;
       
  2037 		break;
       
  2038 		
       
  2039 	case EKeywordExecutableCompressionMethodBytePair:
       
  2040 		gCompressionMethod = KUidCompressionBytePair;
       
  2041 		break;
       
  2042 		
       
  2043 	case EKeywordKernelConfig:
       
  2044 		{
       
  2045 		TInt bit, setTo;
       
  2046 		val >> bit;
       
  2047 		if(bit<0 || bit>31)
       
  2048 			{
       
  2049 			Print(EError,"KernelConfig bit must be between 0 and 31\n");
       
  2050 			success = EFalse;
       
  2051 			break;
       
  2052 			}
       
  2053 		if(ParseBoolArg(setTo,iReader.Word(2))!=KErrNone)
       
  2054 			{
       
  2055 			success = EFalse;
       
  2056 			break;
       
  2057 			}
       
  2058 		if(setTo)
       
  2059 			iKernelConfigFlags |= 1<<bit;
       
  2060 		else
       
  2061 			iKernelConfigFlags &= ~(1<<bit);
       
  2062 		break;
       
  2063 		}
       
  2064 		
       
  2065 	case EKeywordMaxUnpagedMemSize:
       
  2066 		{
       
  2067 		TInt unpagedSize = -1;
       
  2068 		val >> unpagedSize;
       
  2069 			
       
  2070 		if (!val || unpagedSize < 0)
       
  2071 			{
       
  2072 			Print(EWarning, "Invalid value of MaxUnpagedSize (0 to 0x7FFFFFFF) - value ignored\n");
       
  2073 			break;
       
  2074 			}
       
  2075 			
       
  2076 		iMaxUnpagedMemSize = unpagedSize;
       
  2077 		
       
  2078 		if(iUpdatedMaxUnpagedMemSize)
       
  2079 			{
       
  2080 			Print(EWarning, "MaxUnpagedSize redefined - previous values lost\n");
       
  2081 			}
       
  2082 		else
       
  2083 			{
       
  2084 			iUpdatedMaxUnpagedMemSize = ETrue;
       
  2085 			}
       
  2086 		
       
  2087 		break;
       
  2088 		}
       
  2089 
       
  2090 	default:
       
  2091 		// unexpected keyword iReader.Word(0)
       
  2092 		break;
       
  2093 		}
       
  2094 
       
  2095 	return success;
       
  2096 	}
       
  2097 
       
  2098 TBool CObeyFile::GotKeyVariables()
       
  2099 //
       
  2100 // Checks that the obeyfile has supplied enough variables to continue
       
  2101 //
       
  2102    	{
       
  2103 
       
  2104 	TBool retVal=ETrue;
       
  2105 
       
  2106 	// Mandatory keywords
       
  2107 
       
  2108 	if (iRomFileName==0)
       
  2109 		{
       
  2110 		Print(EAlways,"The name of the ROM has not been supplied.\n");
       
  2111 		Print(EAlways,"Use the keyword \"romname\".\n");
       
  2112 		retVal = EFalse;
       
  2113 		}
       
  2114 	if (iBootFileName==0)
       
  2115 		{
       
  2116 		Print(EAlways,"The name of the bootstrap binary has not been supplied.\n");
       
  2117 		Print(EAlways,"Use the keyword \"bootbinary\".\n");
       
  2118 		retVal = EFalse;
       
  2119 		}
       
  2120 	if (iRomLinearBase==0xFFFFFFFF)
       
  2121 		{
       
  2122 		Print(EAlways,"The base linear address of the ROM has not been supplied.\n");
       
  2123 		Print(EAlways,"Use the keyword \"romlinearbase\".\n");
       
  2124 		retVal = EFalse;
       
  2125 		}
       
  2126 	if (iRomSize==0)
       
  2127 		{
       
  2128 		Print(EAlways,"The size of the ROM has not been supplied.\n");
       
  2129 		Print(EAlways,"Use the keyword \"romsize\".\n");
       
  2130 		retVal = EFalse;
       
  2131 		}
       
  2132 	if (iKernDataRunAddress==0)
       
  2133 		{
       
  2134 		Print(EAlways,"The address for the kernel's data section has not been supplied.\n");
       
  2135 		Print(EAlways,"Use the keyword \"kerneldataaddress\".\n");
       
  2136 		retVal = EFalse;
       
  2137 		}
       
  2138 
       
  2139 	// Validation
       
  2140 	if (iNumberOfPrimaries>1 && iKernelModel==ESingleKernel)
       
  2141 		{
       
  2142 		Print(EError,"More than one primary in single-kernel ROM\n");
       
  2143 		retVal = EFalse;
       
  2144 		}
       
  2145 	if (iNumberOfPrimaries==0)
       
  2146 		{
       
  2147 		Print(EError,"No primary file specified\n");
       
  2148 		retVal = EFalse;
       
  2149 		}
       
  2150 	if (iNumberOfVariants==0)
       
  2151 		{
       
  2152 		Print(EError,"No variants specified\n");
       
  2153 		retVal = EFalse;
       
  2154 		}
       
  2155 	if(iNumberOfHCRDataFiles > 1)
       
  2156 		{
       
  2157 		Print(EError,"More than one hcr data files in ROM.\n");
       
  2158 		retVal = EFalse ;
       
  2159 		}
       
  2160 	// Warn about enabling data paging on OS versions where's it's not officially supported
       
  2161 #ifndef SYMBIAN_WRITABLE_DATA_PAGING
       
  2162 	if (iMemModel == E_MM_Flexible &&
       
  2163 		(iKernelConfigFlags & EKernelConfigDataPagingPolicyMask) != EKernelConfigDataPagingPolicyNoPaging)
       
  2164 		{
       
  2165 		Print(EWarning, "Writable data paging is not warranted on this version of Symbian OS.");
       
  2166 		}
       
  2167 #endif
       
  2168 	
       
  2169 	// Apply defaults as necessary
       
  2170 	TheRomLinearAddress=iRomLinearBase;
       
  2171 
       
  2172 	if (iDataRunAddress==0)
       
  2173 		{
       
  2174 		iDataRunAddress=0x400000;
       
  2175 		Print(EWarning,"The address for a running ROM app's data section (keyword \"dataaddress\") has not been supplied.\n");
       
  2176 		Print(EWarning,"Will use the default value of 0x%0x.\n", iDataRunAddress);
       
  2177 		retVal = EFalse;
       
  2178 		}
       
  2179 	if (iRomAlign==0)
       
  2180 		{
       
  2181 		iRomAlign=0x1000;
       
  2182 		Print(EWarning,"The ROM section alignment (keyword \"romalign\") has not been supplied.\n");
       
  2183 		Print(EWarning,"Will use the default value of 0x%0x.\n", iRomAlign);
       
  2184 		}
       
  2185 	if (iRomAlign&0x3)
       
  2186 		{
       
  2187 		Print(EWarning, "Rounding rom alignment to multiple of 4.\n");
       
  2188 		iRomAlign=(iRomAlign+0x3)&0xfffffffc;
       
  2189 		}
       
  2190 	if (iKernHeapMin==0)
       
  2191 	 	{
       
  2192 	 	iKernHeapMin=0x10000;
       
  2193 		Print(EWarning,"The kernel heap min size (keyword \"kernelheapmin\") has not been supplied.\n");
       
  2194 		Print(EWarning,"Will use the default value of 0x%0x.\n", iKernHeapMin);
       
  2195 		}
       
  2196 	if (iKernHeapMax==0)
       
  2197 	 	{
       
  2198 	 	iKernHeapMax=0x100000;
       
  2199 		Print(EWarning,"The kernel heap max size (keyword \"kernelheapmax\") has not been supplied.\n");
       
  2200 		Print(EWarning,"Will use the default value of 0x%0x.\n", iKernHeapMax);
       
  2201 		}
       
  2202 
       
  2203 	if (iTime==0)
       
  2204 		{
       
  2205 		Print(ELog, "No timestamp specified. Using current time...\n");
       
  2206 		ObeyFileReader::TimeNow(iTime);
       
  2207 		}
       
  2208 
       
  2209 	Print(ELog, "\nCreating Rom image %s\n", iRomFileName);
       
  2210 	Print(ELog, "MemModel: %1d\nChunkSize: %08x\nPageSize: %08x\n", iMemModel, iChunkSize, iPageSize);
       
  2211 	return retVal;
       
  2212 	}
       
  2213 
       
  2214 
       
  2215 TText *CObeyFile::IsValidFilePath(TText *aPath)
       
  2216 //
       
  2217 // Check the path is valid
       
  2218 //
       
  2219 	{
       
  2220 	// skip leading "\"
       
  2221 	if (*aPath=='\\')
       
  2222 		aPath++;
       
  2223 	if (*aPath==0)
       
  2224 		return NULL; // file ends in a backslash
       
  2225 
       
  2226 	TText *p=aPath;
       
  2227 	TInt len=0;
       
  2228 	FOREVER
       
  2229 		{
       
  2230 		if (*p==0)
       
  2231 			return (len ? aPath : NULL);
       
  2232 		if (*p=='\\')
       
  2233 			{
       
  2234 			if (len==0)
       
  2235 				return NULL;
       
  2236 			len=0;
       
  2237 			}
       
  2238 		len++;
       
  2239 		p++;
       
  2240 		}
       
  2241 	}
       
  2242 
       
  2243 TBool CObeyFile::GetNextBitOfFileName(TText **epocEndPtr)
       
  2244 //
       
  2245 // Move the end pointer past the next directory separator, replacing it with 0
       
  2246 //
       
  2247 	{
       
  2248 	while (**epocEndPtr != '\\') // until reach the directory separator
       
  2249 		{
       
  2250 		if (**epocEndPtr==0) // if reach end of string, return TRUE, it's the filename
       
  2251 			return ETrue;
       
  2252 		(*epocEndPtr)++;
       
  2253 		}
       
  2254 	**epocEndPtr=0; // overwrite the directory separator with a 0
       
  2255 	(*epocEndPtr)++; // point past the 0 ready for the next one
       
  2256 	return EFalse;
       
  2257 	}
       
  2258 
       
  2259 
       
  2260 TBool CObeyFile::CheckHardwareVariants()
       
  2261 	{
       
  2262 	iPrimaries=new TRomBuilderEntry*[iNumberOfPrimaries];
       
  2263 	iVariants=new TRomBuilderEntry*[iNumberOfVariants];
       
  2264 	THardwareVariant* primaryHwVariants=new THardwareVariant[iNumberOfPrimaries];
       
  2265 	TInt nVar=0;
       
  2266 	TRomBuilderEntry* current=FirstFile();
       
  2267 	THardwareVariant* variantHwVariants=new THardwareVariant[iNumberOfVariants];
       
  2268 	while(current)
       
  2269 		{
       
  2270 		if (current->Variant())
       
  2271 			{
       
  2272 			TInt i;
       
  2273 			for(i=0; i<nVar; i++)
       
  2274 				{
       
  2275 				if (!current->iHardwareVariant.MutuallyExclusive(variantHwVariants[i]))
       
  2276 					{
       
  2277 					delete[] variantHwVariants;
       
  2278 					delete[] primaryHwVariants;
       
  2279 					Print(EError,"Variants not mutually exclusive\n");
       
  2280 					return EFalse;
       
  2281 					}
       
  2282 				}
       
  2283 			iVariants[nVar]=current;
       
  2284 			variantHwVariants[nVar++]=current->iHardwareVariant;
       
  2285 			}
       
  2286 		current=NextFile();
       
  2287 		}
       
  2288 	delete[] variantHwVariants;
       
  2289 	nVar=0;
       
  2290 	current=FirstFile();
       
  2291 	while(current)
       
  2292 		{
       
  2293 		TInt i;
       
  2294 		for (i=0; i<iNumberOfVariants; i++)
       
  2295 			{
       
  2296 			if (iVariants[i]->iHardwareVariant<=current->iHardwareVariant)
       
  2297 				break;
       
  2298 			}
       
  2299 		if (i==iNumberOfVariants)
       
  2300 			{
       
  2301 			Print(EError,"File %s[%08x] does not correspond to any variant\n",
       
  2302 									current->iName,TUint(current->iHardwareVariant));
       
  2303 			delete[] primaryHwVariants;
       
  2304 			return EFalse;
       
  2305 			}
       
  2306 		if (current->Primary())
       
  2307 			{
       
  2308 			for(i=0; i<nVar; i++)
       
  2309 				{
       
  2310 				if (!current->iHardwareVariant.MutuallyExclusive(primaryHwVariants[i]))
       
  2311 					{
       
  2312 					delete[] primaryHwVariants;
       
  2313 					Print(EError,"Primaries not mutually exclusive\n");
       
  2314 					return EFalse;
       
  2315 					}
       
  2316 				}
       
  2317 			iPrimaries[nVar]=current;
       
  2318 			primaryHwVariants[nVar++]=current->iHardwareVariant;
       
  2319 			}
       
  2320 		current=NextFile();
       
  2321 		}
       
  2322 	delete[] primaryHwVariants;
       
  2323 	if (iNumberOfExtensions)
       
  2324 		{
       
  2325 		nVar=0;
       
  2326 		iExtensions=new TRomBuilderEntry*[iNumberOfExtensions];
       
  2327 		TRomBuilderEntry* current=FirstFile();
       
  2328 		while(current)
       
  2329 			{
       
  2330 			if (current->Extension())
       
  2331 				{
       
  2332 				if (current->iHardwareVariant.IsVariant())
       
  2333 					{
       
  2334 					TUint layer=current->iHardwareVariant.Layer();
       
  2335 					TUint vmask=current->iHardwareVariant.VMask();
       
  2336 					if ((iAllVariantsMask[layer]&vmask)==0)
       
  2337 						{
       
  2338 						Print(EError,"Variant-layer extension %s has no corresponding variant DLL\n",current->iName);
       
  2339 						return EFalse;
       
  2340 						}
       
  2341 					}
       
  2342 				iExtensions[nVar++]=current;
       
  2343 				}
       
  2344 			current=NextFile();
       
  2345 			}
       
  2346 		}
       
  2347 	if (iNumberOfDevices)
       
  2348 		{
       
  2349 		nVar=0;
       
  2350 		iDevices=new TRomBuilderEntry*[iNumberOfDevices];
       
  2351 		TRomBuilderEntry* current=FirstFile();
       
  2352 		while(current)
       
  2353 			{
       
  2354 			if (current->Device())
       
  2355 				{
       
  2356 				if (current->iHardwareVariant.IsVariant())
       
  2357 					{
       
  2358 					TUint layer=current->iHardwareVariant.Layer();
       
  2359 					TUint vmask=current->iHardwareVariant.VMask();
       
  2360 					if ((iAllVariantsMask[layer]&vmask)==0)
       
  2361 						{
       
  2362 						Print(EError,"Variant-layer device %s has no corresponding variant DLL\n",current->iName);
       
  2363 						return EFalse;
       
  2364 						}
       
  2365 					}
       
  2366 				iDevices[nVar++]=current;
       
  2367 				}
       
  2368 			current=NextFile();
       
  2369 			}
       
  2370 		}
       
  2371 	NumberOfVariants=iNumberOfVariants;
       
  2372 	return ETrue;
       
  2373 	}
       
  2374 
       
  2375 
       
  2376 TInt CObeyFile::ProcessExtensionRom(MRomImage*& aKernelRom)
       
  2377 	{
       
  2378 	//
       
  2379 	// First pass through the obey file to set up key variables
       
  2380 	//
       
  2381 
       
  2382 	iReader.Rewind();
       
  2383 
       
  2384 	enum EKeyword keyword;
       
  2385 
       
  2386 	// Deal with the "extensionrom" keyword, which should be first
       
  2387 	
       
  2388 	if (iReader.NextLine(1,keyword) != KErrNone)
       
  2389 		return KErrEof;
       
  2390 	if (keyword != EKeywordExtensionRom)
       
  2391 		return Print(EError, "Unexpected keyword '%s' at start of extension rom - line %d\n",
       
  2392 			iReader.Word(0), iReader.CurrentLine());
       
  2393 	
       
  2394 	iReader.CopyWord(1, iRomFileName);
       
  2395 	Print(ELog, "\n========================================================\n");
       
  2396 	Print(ELog, "Extension ROM %s starting at line %d\n\n", iRomFileName, iReader.CurrentLine());
       
  2397 
       
  2398 	iReader.MarkNext();		// so that we rewind to the line after the extensionrom keyword
       
  2399 
       
  2400 	while (iReader.NextLine(1,keyword) != KErrEof)
       
  2401 		{
       
  2402 		if (keyword == EKeywordExtensionRom)
       
  2403 			break;
       
  2404 		ProcessExtensionKeyword(keyword);
       
  2405 		}
       
  2406 
       
  2407 	if (!GotExtensionVariables(aKernelRom))
       
  2408 		return KErrGeneral;
       
  2409 
       
  2410 	if (! CreateDefaultArea())
       
  2411 		return KErrGeneral;
       
  2412 
       
  2413 	//
       
  2414 	// second pass to process the file specifications in the obey file building
       
  2415 	// up the TRomNode directory structure and the TRomBuilderEntry list
       
  2416 	//
       
  2417 	iReader.Rewind();
       
  2418 
       
  2419 	if (aKernelRom==0)
       
  2420 		return Print(EError, "Option to extend a kernel ROM image not yet implemented\n");
       
  2421 	iLastExecutable = 0;
       
  2422 	iRootDirectory = aKernelRom->CopyDirectory(iLastExecutable);
       
  2423 
       
  2424 
       
  2425 	TInt align=0;
       
  2426 	while (iReader.NextLine(2,keyword)!=KErrEof)
       
  2427 		{
       
  2428 		if (keyword == EKeywordExtensionRom)
       
  2429 			break;
       
  2430 
       
  2431 		switch (keyword)
       
  2432 			{
       
  2433 		case EKeywordSection:
       
  2434 		case EKeywordArea:
       
  2435 		case EKeywordPrimary:
       
  2436 		case EKeywordSecondary:
       
  2437 		case EKeywordExtension:
       
  2438 		case EKeywordDevice:
       
  2439 		case EKeywordVariant:
       
  2440 		case EKeywordHardwareConfigRepositoryData:
       
  2441 			Print(EError, "Keyword '%s' not supported in extension ROMs - line %d\n",
       
  2442 				iReader.Word(0), iReader.CurrentLine());
       
  2443 			break;
       
  2444 
       
  2445 		case EKeywordAlign:
       
  2446 			if (iReader.ProcessAlign(align)!=KErrNone)
       
  2447 				return KErrGeneral;
       
  2448 			break;
       
  2449 
       
  2450 		case EKeywordHide:
       
  2451 		case EKeywordAlias:
       
  2452 		case EKeywordRename:
       
  2453 			if (!ProcessRenaming(keyword))
       
  2454 				return KErrGeneral;
       
  2455 			break;
       
  2456 		case EKeywordPatchDllData:
       
  2457 		{
       
  2458 			// Collect patchdata statements to process at the end
       
  2459 			StringVector patchDataTokens;
       
  2460 			SplitPatchDataStatement(patchDataTokens); 
       
  2461 			iPatchData->AddPatchDataStatement(patchDataTokens);										
       
  2462 			break;
       
  2463 		}
       
  2464 
       
  2465 		default:
       
  2466 			if (!ProcessFile(align, keyword))
       
  2467 				return KErrGeneral;
       
  2468 			align=0;
       
  2469 			break;
       
  2470 			}
       
  2471 		}
       
  2472 
       
  2473 	if( !ParsePatchDllData())
       
  2474 		return KErrGeneral;
       
  2475 
       
  2476 	iReader.Mark();			// ready for processing the next extension rom(s)
       
  2477 
       
  2478 	if (iMissingFiles!=0)
       
  2479 		return KErrGeneral;
       
  2480 	if (iNumberOfDataFiles+iNumberOfPeFiles==0)
       
  2481 		{
       
  2482 		Print(EError, "No files specified.\n");
       
  2483 		return KErrGeneral;
       
  2484 		}
       
  2485 	return KErrNone;
       
  2486 	}
       
  2487 
       
  2488 void CObeyFile::ProcessExtensionKeyword(enum EKeyword aKeyword)
       
  2489 	{
       
  2490 	#ifdef __TOOLS2__
       
  2491 	istringstream val(iReader.Word(1));
       
  2492 	#else
       
  2493 	istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  2494 	#endif
       
  2495 	
       
  2496 
       
  2497 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  2498 	val >> setbase(0);
       
  2499 #endif //__MSVCDOTNET__
       
  2500 
       
  2501 	switch (aKeyword)
       
  2502 		{
       
  2503 	case EKeywordKernelRomName:
       
  2504 		iReader.CopyWord(1, iKernelRomName);
       
  2505 		return;
       
  2506 	case EKeywordRomNameOdd:
       
  2507 		iReader.CopyWord(1, iRomOddFileName);
       
  2508 		return;
       
  2509 	case EKeywordRomNameEven:
       
  2510 		iReader.CopyWord(1, iRomEvenFileName);
       
  2511 		return;
       
  2512 	case EKeywordSRecordFileName:
       
  2513 		iReader.CopyWord(1, iSRecordFileName);
       
  2514 		return;
       
  2515 
       
  2516 	case EKeywordRomLinearBase:
       
  2517 		val >> iRomLinearBase;
       
  2518 		return;
       
  2519 	case EKeywordRomSize:
       
  2520 		val >> iRomSize;
       
  2521 		return;
       
  2522 	case EKeywordRomAlign:
       
  2523 		val >> iRomAlign;
       
  2524 		return;
       
  2525 
       
  2526 	case EKeywordDataAddress:
       
  2527 		val >> iDataRunAddress;
       
  2528 		return;
       
  2529 	case EKeywordDefaultStackReserve:
       
  2530 		val >> iDefaultStackReserve;
       
  2531 		return;
       
  2532 	case EKeywordVersion:
       
  2533 		val >> iVersion;
       
  2534 		return;
       
  2535 	case EKeywordSRecordBase:
       
  2536 		val >> iSRecordBase;
       
  2537 		return;
       
  2538 	case EKeywordRomChecksum:
       
  2539 		val >> iCheckSum;
       
  2540 		return;
       
  2541 	case EKeywordTime:
       
  2542 		iReader.ProcessTime(iTime);
       
  2543 		return;
       
  2544 
       
  2545 	case EKeywordTrace:
       
  2546 		val >> TraceMask;
       
  2547 		return;
       
  2548 
       
  2549 	case EKeywordCollapse:
       
  2550 		if (strnicmp(iReader.Word(1), "arm", 3)!=0 || strnicmp(iReader.Word(2), "gcc", 3)!=0)
       
  2551 			{
       
  2552 			Print(EWarning, "COLLAPSE only supported for ARM and GCC - keyword ignored\n");
       
  2553 			}
       
  2554 		else
       
  2555 			{
       
  2556 			TInt cm;
       
  2557 			#ifdef __TOOLS2__
       
  2558 			istringstream cmval(iReader.Word(3));
       
  2559 			#else
       
  2560 			istrstream cmval(iReader.Word(3),strlen(iReader.Word(3)));
       
  2561 			#endif
       
  2562 
       
  2563 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  2564 			cmval >> setbase(0);
       
  2565 #endif //__MSVCDOTNET__
       
  2566 
       
  2567 			cmval>>cm;
       
  2568 			if (cm<0 || cm>ECollapseAllChainBranches)
       
  2569 				{
       
  2570 				Print(EWarning, "COLLAPSE mode unrecognised - keyword ignored\n");
       
  2571 				}
       
  2572 			else
       
  2573 				{
       
  2574 				Print(EWarning, "COLLAPSE not currently supported for extension roms\n");
       
  2575 				}
       
  2576 			}
       
  2577 		return;
       
  2578 
       
  2579 	case EKeywordCoreImage:
       
  2580 		//Already handled, skip it
       
  2581 		return;
       
  2582 
       
  2583 	default:
       
  2584 		Print(EError,"Keyword '%s' not valid in extension ROMs - line %d\n", iReader.Word(0), iReader.CurrentLine());
       
  2585 		break;
       
  2586 		}
       
  2587 	return;
       
  2588 	}
       
  2589 
       
  2590 TBool CObeyFile::GotExtensionVariables(MRomImage*& aRom)
       
  2591 //
       
  2592 // Checks that the obeyfile has supplied enough variables to continue
       
  2593 //
       
  2594    	{
       
  2595 
       
  2596 	TBool retVal=ETrue;
       
  2597 	TText* kernelRomName = iKernelRomName;
       
  2598 
       
  2599 	// Mandatory keywords
       
  2600 
       
  2601 	if (iRomSize==0)
       
  2602 		{
       
  2603 		Print(EAlways,"The size of the extension ROM has not been supplied.\n");
       
  2604 		Print(EAlways,"Use the keyword \"romsize\".\n");
       
  2605 		retVal = EFalse;
       
  2606 		}
       
  2607 
       
  2608 	// keywords we need if we don't already have a ROM image to work from
       
  2609 
       
  2610 	if (aRom==0)
       
  2611 		{
       
  2612 		if (iKernelRomName==0)
       
  2613 			{
       
  2614 			Print(EAlways,"The name of the kernel ROM has not been supplied.\n");
       
  2615 			Print(EAlways,"Use the keyword \"kernelromname\".\n");
       
  2616 			retVal = EFalse;
       
  2617 			}
       
  2618 		if (iRomLinearBase==0xFFFFFFFF)
       
  2619 			{
       
  2620 			Print(EAlways,"The base linear address of the ROM has not been supplied.\n");
       
  2621 			Print(EAlways,"Use the keyword \"romlinearbase\".\n");
       
  2622 			retVal = EFalse;
       
  2623 			}
       
  2624 		}
       
  2625 	else
       
  2626 		{
       
  2627 		if (iKernelRomName != 0)
       
  2628 			{
       
  2629 			Print(EWarning,"Keyword \"kernelromname\") ignored.\n");
       
  2630 			}
       
  2631 		kernelRomName = aRom->RomFileName();
       
  2632 		}
       
  2633 
       
  2634 	// validation
       
  2635 
       
  2636 	// Apply defaults as necessary
       
  2637 
       
  2638 	if (iRomLinearBase==0xFFFFFFFF && aRom!=0)
       
  2639 		{
       
  2640 		iRomLinearBase = aRom->RomBase() + aRom->RomSize();
       
  2641 		Print(ELog,"Assuming extension ROM is contiguous with kernel ROM\n");
       
  2642 		Print(ELog,"Setting romlinearbase to 0x%08x\n", iRomLinearBase);
       
  2643 		}
       
  2644 	TheRomLinearAddress=iRomLinearBase;
       
  2645 
       
  2646 	if (iDataRunAddress==0)
       
  2647 		{
       
  2648 		iDataRunAddress= aRom->DataRunAddress();
       
  2649 		Print(EWarning,"The address for a running ROM app's data section (keyword \"dataaddress\") has not been supplied.\n");
       
  2650 		Print(EWarning,"Will use the default value of 0x%0x.\n", iDataRunAddress);
       
  2651 		}
       
  2652 	if (iRomAlign==0)
       
  2653 		{
       
  2654 		iRomAlign = aRom->RomAlign();
       
  2655 		Print(EWarning,"The ROM section alignment (keyword \"romalign\") has not been supplied.\n");
       
  2656 		Print(EWarning,"Will use the default value of 0x%0x.\n", iRomAlign);
       
  2657 		}
       
  2658 	if (iRomAlign&0x3)
       
  2659 		{
       
  2660 		Print(EWarning, "Rounding rom alignment to multiple of 4.\n");
       
  2661 		iRomAlign=(iRomAlign+0x3)&0xfffffffc;
       
  2662 		}
       
  2663 	if (iTime==0)
       
  2664 		{
       
  2665 		Print(ELog, "No timestamp specified. Using current time...\n");
       
  2666 		ObeyFileReader::TimeNow(iTime);
       
  2667 		}
       
  2668 
       
  2669 	// fix up "*" in romname
       
  2670 	TText newname[256];
       
  2671 	TText* p=newname;
       
  2672 	TText* q=iRomFileName;
       
  2673 	TText c;
       
  2674 
       
  2675 	while ((c=*q++)!='\0')
       
  2676 		{
       
  2677 		if (c!='*')
       
  2678 			{
       
  2679 			*p++=c;
       
  2680 			continue;
       
  2681 			}
       
  2682 		TText *r=kernelRomName;
       
  2683 		while ((c=*r++)!='\0')
       
  2684 			*p++=c;
       
  2685 		}
       
  2686 	*p = '\0';
       
  2687 	free(iRomFileName);
       
  2688 	iRomFileName = (TText*)strdup((char*)newname);
       
  2689 
       
  2690 	Print(ELog, "\nCreating Rom image %s\n", iRomFileName);
       
  2691 	return retVal;
       
  2692 	}
       
  2693 
       
  2694 
       
  2695 ////////////////////////////////////////////////////////////////////////
       
  2696 // AREA RELATED CODE
       
  2697 ////////////////////////////////////////////////////////////////////////
       
  2698 
       
  2699 /**
       
  2700  Process an area declaration.
       
  2701  */
       
  2702 
       
  2703 TBool CObeyFile::ParseAreaKeyword()
       
  2704 	{
       
  2705 	const char* name = iReader.Word(1);
       
  2706 	TLinAddr start;
       
  2707 	TUint length;
       
  2708 	if(Val(start, iReader.Word(2)) != KErrNone || Val(length, iReader.Word(3)) != KErrNone)
       
  2709 		{
       
  2710 		Print(EError, "Line %d: Wrong area specification: Should be <name> <start address> <length>\n",
       
  2711 			  iReader.CurrentLine());
       
  2712 		return EFalse;
       
  2713 		}
       
  2714 
       
  2715 	if (! AddAreaAndHandleError(name, start, length, iReader.CurrentLine()))
       
  2716 		return EFalse;
       
  2717 
       
  2718 	return ETrue;
       
  2719 	}
       
  2720 
       
  2721 
       
  2722 /**
       
  2723  Process an "area=xxx" file attribute.
       
  2724  */
       
  2725 
       
  2726 TBool CObeyFile::ParseAreaAttribute(const TText* aArg, TInt aLineNumber, const Area*& aArea)
       
  2727 	{
       
  2728 	if (iSectionPosition != -1)
       
  2729 		{
       
  2730 		Print(EError, "Line %d: Relocation to area forbidden in second section\n", aLineNumber);
       
  2731 		return EFalse;
       
  2732 		}
       
  2733 
       
  2734 	aArea = iAreaSet.FindByName(reinterpret_cast<const char*>(aArg));
       
  2735 	if (aArea == 0)
       
  2736 		{
       
  2737 		Print(EError, "Line %d: Attempt to use an unknown area named '%s'\n", aLineNumber, aArg);
       
  2738 		return EFalse;
       
  2739 		}
       
  2740 
       
  2741 	return ETrue;
       
  2742 	}
       
  2743 
       
  2744 
       
  2745 TBool CObeyFile::CreateDefaultArea()
       
  2746 	{
       
  2747 	return AddAreaAndHandleError(AreaSet::KDefaultAreaName, iRomLinearBase, iRomSize);
       
  2748 	}
       
  2749 
       
  2750 
       
  2751 TBool CObeyFile::AddAreaAndHandleError(const char* aName, TLinAddr aDestBaseAddr, TUint aLength, TInt aLineNumber)
       
  2752 	{
       
  2753 	TBool added = EFalse;
       
  2754 	
       
  2755 	const char lineInfoFmt[] = "Line %d:";
       
  2756 	char lineInfo[sizeof(lineInfoFmt)+10];
       
  2757 	if (aLineNumber > 0)
       
  2758 		sprintf(lineInfo, lineInfoFmt, aLineNumber);
       
  2759 	else
       
  2760 		lineInfo[0] = '\0';
       
  2761 
       
  2762 	const char* overlappingArea;
       
  2763 	switch (iAreaSet.AddArea(aName, aDestBaseAddr, aLength, overlappingArea))
       
  2764 		{
       
  2765 	case AreaSet::EAdded:
       
  2766 		TRACE(TAREA, Print(EScreen, "Area '%s' added to AreaSet\n", aName));
       
  2767 		added = ETrue;
       
  2768 		break;
       
  2769 	case AreaSet::EOverlap:
       
  2770 		Print(EError, "%s Area '%s' collides with area '%s'\n", lineInfo, aName, overlappingArea);
       
  2771 		break;
       
  2772 	case AreaSet::EDuplicateName:
       
  2773 		Print(EError, "%s Name '%s' already reserved for another area\n", lineInfo, aName);
       
  2774 		break;
       
  2775 	case AreaSet::EOverflow:
       
  2776 		Print(EError, "%s Area overflow (0x%X+0x%X > 0x%X)\n", lineInfo, aDestBaseAddr, aLength, -1);
       
  2777 		break;
       
  2778 	default:
       
  2779 		assert(0);				// can't happen
       
  2780 		}
       
  2781 
       
  2782 	return added;
       
  2783 	}
       
  2784 
       
  2785 TInt getNumber(TText*);
       
  2786 
       
  2787 
       
  2788 // Fuction to split patchdata statement 
       
  2789 void CObeyFile::SplitPatchDataStatement(StringVector& aPatchDataTokens)
       
  2790 {
       
  2791 	// Get the value of symbol size, address/ordinal and new value 
       
  2792 	// to be patched from the patchdata statement.
       
  2793 	// Syntax of patchdata statements is as follows:
       
  2794 	// 1)	patchdata dll_name  ordinal OrdinalNumber size_in_bytes   new_value 
       
  2795 	// 2)   patchdata dll_name  addr    Address       size_in_bytes   new_value
       
  2796 	for(TInt count=1; count<=5; count++)	
       
  2797 	{
       
  2798 		aPatchDataTokens.push_back(iReader.Word(count));
       
  2799 	}
       
  2800 
       
  2801 	// Store the the value of current line which will be used
       
  2802 	// when displaying error messages.
       
  2803 	OutputStringStream outStrStream;
       
  2804 	outStrStream << iReader.CurrentLine();
       
  2805     aPatchDataTokens.push_back(outStrStream.str());	
       
  2806 }
       
  2807 
       
  2808 TBool CObeyFile::ParsePatchDllData()
       
  2809 {
       
  2810 	// Get the list of patchdata statements
       
  2811 	VectorOfStringVector patchDataStatements=iPatchData->GetPatchDataStatements();
       
  2812 	// Get the list of renamed file map
       
  2813 	MapOfString RenamedFileMap=iPatchData->GetRenamedFileMap();
       
  2814 	DllDataEntry *aDllDataEntry=NULL;
       
  2815 
       
  2816 	for(TUint count=0; count<patchDataStatements.size(); count++)
       
  2817 	{
       
  2818 		StringVector strVector = patchDataStatements.at(count);
       
  2819 		String filename=strVector.at(0);
       
  2820 		String lineNoStr = strVector.at(5);
       
  2821 		TUint lineNo=getNumber(((TText*)lineNoStr.c_str()));
       
  2822 		TRomNode* existingFile = NULL;
       
  2823 			
       
  2824 		do
       
  2825 		{			
       
  2826 			TUint hardwareVariant=ParseVariant();
       
  2827 			TRomNode* dir=iRootDirectory;		
       
  2828 			TBool endOfName=EFalse;
       
  2829 
       
  2830 			TText *epocStartPtr=IsValidFilePath((TText*)filename.c_str());
       
  2831 			if (epocStartPtr==NULL)
       
  2832 			{
       
  2833 				Print(EError, "Invalid source path on line %d\n",lineNo);
       
  2834 				return EFalse;
       
  2835 			}
       
  2836 			epocStartPtr = (TText*)NormaliseFileName((const char*)epocStartPtr);
       
  2837 			TText *epocEndPtr=epocStartPtr;
       
  2838 
       
  2839 			while (!endOfName)
       
  2840 			{
       
  2841 				endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  2842 				if (endOfName) // file
       
  2843 				{
       
  2844 					existingFile=dir->FindInDirectory(epocStartPtr,hardwareVariant,TRUE);
       
  2845 					if (existingFile)
       
  2846 					{
       
  2847 						TInt fileCount=0;
       
  2848 						TInt dirCount=0;
       
  2849 						existingFile->CountDirectory(fileCount, dirCount);
       
  2850 						if (dirCount != 0 || fileCount != 0)
       
  2851 						{
       
  2852 							Print(EError, "Keyword %s not applicable to directories - line %d\n","patchdata",lineNo);
       
  2853 							return EFalse;
       
  2854 						}
       
  2855 					}
       
  2856 				}
       
  2857 				else // directory
       
  2858 				{
       
  2859 					TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
       
  2860 					if (!subDir) // sub directory does not exist
       
  2861 						break;
       
  2862 					dir=subDir;
       
  2863 					epocStartPtr = epocEndPtr;
       
  2864 				}
       
  2865 			}
       
  2866 
       
  2867 			if( !existingFile )
       
  2868 			{
       
  2869 				MapOfStringIterator RenamedFileMapIterator;
       
  2870 
       
  2871 				// If the E32Image file to be patched is not included then check if the
       
  2872 				// file was renamed.
       
  2873 				if ((RenamedFileMapIterator=RenamedFileMap.find(filename)) != RenamedFileMap.end())
       
  2874 					filename = (*RenamedFileMapIterator).second; 
       
  2875 				else
       
  2876 				{
       
  2877 					Print(EError, "File %s not found - line %d\n", filename.c_str(), lineNo);
       
  2878 					return EFalse;
       
  2879 				}
       
  2880 			}
       
  2881 		}while(!existingFile);
       
  2882 
       
  2883 		TUint32 aSize, aOrdinal, aNewValue, aOffset;
       
  2884 		TLinAddr aDataAddr;
       
  2885 
       
  2886 		aOrdinal = (TUint32)-1;
       
  2887 		aDataAddr = (TUint32)-1;
       
  2888 		aOffset = 0;
       
  2889 
       
  2890 		String symbolSize = strVector.at(3);
       
  2891 		aSize = getNumber((TText*)symbolSize.c_str());
       
  2892 		String aValue = strVector.at(4);
       
  2893 		aNewValue = getNumber( (TText*)aValue.c_str());
       
  2894 
       
  2895 		DllDataEntry *dataEntry = new DllDataEntry(aSize, aNewValue);
       
  2896 
       
  2897 		// Set the address of the data or the ordinal number specified in OBY statement.
       
  2898 		String keyword = strVector.at(1);
       
  2899 		String keywordValue = strVector.at(2);
       
  2900 
       
  2901 		/* Check for +OFFSET at the end of the ordinal number or address */
       
  2902 		TUint plus = keywordValue.find("+",0);
       
  2903 		if (plus != std::string::npos)
       
  2904 		{
       
  2905 			/* Get the offset that we found after the + sign */
       
  2906 			String offset = keywordValue.substr(plus+1);
       
  2907 			aOffset = getNumber((TText*)offset.c_str());
       
  2908 
       
  2909 			keywordValue.resize(plus);		
       
  2910 		}
       
  2911 		if(stricmp ((char*)keyword.c_str(), "addr") == 0)
       
  2912 			aDataAddr = getNumber((TText*)keywordValue.c_str());
       
  2913 		
       
  2914 		else 
       
  2915 			 aOrdinal = getNumber((TText*)keywordValue.c_str());
       
  2916 		
       
  2917 		dataEntry->iDataAddress = aDataAddr;
       
  2918 		dataEntry->iOrdinal = aOrdinal;
       
  2919 		dataEntry->iOffset = aOffset;
       
  2920 		dataEntry->iRomNode = existingFile;
       
  2921 
       
  2922 		if (aDllDataEntry==NULL)
       
  2923 		{
       
  2924 			// Set the first node of the patchdata linked list
       
  2925 			aDllDataEntry = dataEntry;
       
  2926 			SetFirstDllDataEntry(aDllDataEntry);
       
  2927 		}
       
  2928 		else
       
  2929 		{
       
  2930 			// Add the new node at the end of linked list
       
  2931 			aDllDataEntry->AddDllDataEntry(dataEntry);
       
  2932 			aDllDataEntry = aDllDataEntry->NextDllDataEntry();
       
  2933 		}
       
  2934 	}
       
  2935 	return ETrue;
       
  2936 }
       
  2937 
       
  2938 int CObeyFile::SkipToExtension()
       
  2939 {
       
  2940 	int found = 0;
       
  2941 
       
  2942 	iReader.Rewind();
       
  2943 	enum EKeyword keyword;
       
  2944 	while (iReader.NextLine(1,keyword) != KErrEof)
       
  2945 	{
       
  2946 		if (keyword == EKeywordExtensionRom)
       
  2947 		{
       
  2948 			found = 1;
       
  2949 			iReader.Mark(); // ready for processing extension
       
  2950 			break;
       
  2951 		}
       
  2952 	}
       
  2953 
       
  2954 	if(!found)
       
  2955 	{
       
  2956 		Print(EError, "Coreimage option requires valid \"extensionrom\" keyword\n");
       
  2957 	}
       
  2958 
       
  2959 	return found;
       
  2960 }
       
  2961 
       
  2962 TText* CObeyFile::ProcessCoreImage()
       
  2963 {
       
  2964 	// check for coreimage keyword and return filename
       
  2965 	iReader.Rewind();
       
  2966 	enum EKeyword keyword;
       
  2967 	TText* coreImageFileName = 0;
       
  2968 
       
  2969 	iRomAlign = KDefaultRomAlign;
       
  2970 	iDataRunAddress = KDefaultDataRunAddress;
       
  2971 
       
  2972 	while (iReader.NextLine(1,keyword) != KErrEof)
       
  2973 	{
       
  2974 		if (keyword == EKeywordCoreImage)
       
  2975 		{
       
  2976 #if defined(__TOOLS2__) && defined (_STLP_THREADS)
       
  2977 			istringstream val(iReader.Word(1),(ios_base::in+ios_base::out));	  
       
  2978 #elif __TOOLS2__
       
  2979 			istringstream val(iReader.Word(1),(std::_Ios_Openmode)(ios_base::in+ios_base::out));
       
  2980 #else
       
  2981 			istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  2982 #endif
       
  2983 			iReader.CopyWord(1, coreImageFileName);
       
  2984 			break;
       
  2985 		}
       
  2986 		else if ((keyword == EKeywordRomAlign) || (keyword == EKeywordDataAddress))
       
  2987 		{
       
  2988 #ifdef __TOOLS2__
       
  2989 			istringstream val(iReader.Word(1));
       
  2990 #else
       
  2991 			istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  2992 #endif
       
  2993 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  2994 	val >> setbase(0);
       
  2995 #endif //__MSVCDOTNET__
       
  2996 			if(keyword == EKeywordRomAlign)
       
  2997 			{
       
  2998 				val >> iRomAlign;
       
  2999 			}
       
  3000 			else
       
  3001 			{
       
  3002 				val >> iDataRunAddress;
       
  3003 			}
       
  3004 		}
       
  3005 	}
       
  3006 
       
  3007 	if (iRomAlign&0x3)
       
  3008 	{
       
  3009 		//Rounding rom alignment to multiple of 4
       
  3010 		iRomAlign=(iRomAlign+0x3)&0xfffffffc;
       
  3011 	}
       
  3012 
       
  3013 	return coreImageFileName;
       
  3014 }
       
  3015