--- a/imgtools/romtools/rofsbuild/r_obey.cpp Fri Jun 25 20:58:33 2010 +0800
+++ b/imgtools/romtools/rofsbuild/r_obey.cpp Tue Jun 29 14:52:54 2010 +0800
@@ -1,2274 +1,2061 @@
-/*
-* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description:
-* @internalComponent * @released
-* Rofsbuild Obey file class and its reader class.
-*
-*/
-
-
-#include <string.h>
-
-#ifdef __VC32__
- #ifdef __MSVCDOTNET__
- #include <strstream>
- #include <iomanip>
- #else //__MSVCDOTNET__
- #include <strstrea.h>
- #include <iomanip.h>
- #endif //__MSVCDOTNET__
-#else // !__VC32__
-#ifdef __TOOLS2__
- #include <sstream>
- #include <iomanip>
- #include <sys/stat.h>
- using namespace std;
-#else
- #include <strstrea.h>
- #include <iomanip.h>
-#endif
-
-#endif //__VC32__
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32rom.h>
-#include <u32std.h>
-#include <f32file.h>
-
-#include "h_utl.h"
-#include "r_obey.h"
-#include "r_coreimage.h"
-#include "patchdataprocessor.h"
-#include "filesysteminterface.h"
-#include "r_driveimage.h"
-
-extern TInt gCodePagingOverride;
-extern TInt gDataPagingOverride;
-extern ECompression gCompress;
-extern TBool gEnableStdPathWarning; // Default to not warn if destination path provided for a file is not in standard path.
-
-
-
-#define _P(word) word, sizeof(word)-1 // match prefix, optionally followed by [HWVD]
-#define _K(word) word, 0 // match whole word
-
-const ObeyFileKeyword ObeyFileReader::iKeywords[] =
-{
- {_K("file"), 2,-2, EKeywordFile, "File to be copied into ROFS"},
- {_K("data"), 2,-2, EKeywordData, "same as file"},
-
- {_K("rofsname"), 1, 1, EKeywordRofsName, "output file for ROFS image"},
- {_K("romsize"), 1, 1, EKeywordRomSize, "size of ROM image"},
- {_P("hide"), 2, -1, EKeywordHide, "Exclude named file from ROM directory structure"},
- {_P("alias"), 2, -2, EKeywordAlias, "Create alias for existing file in ROM directory structure"},
- {_P("rename"), 2, -2, EKeywordRename, "Change the name of a file in the ROM directory structure"},
- {_K("rofssize"), 1, 1, EKeywordRofsSize, "maximum size of ROFS image"},
- {_K("romchecksum"), 1, 1, EKeywordRofsChecksum, "desired 32-bit checksum value for the whole image"},
- {_K("version"), 1, 1, EKeywordVersion, "ROFS image version number"},
- {_K("time"), 1,-1, EKeywordTime, "ROFS image timestamp"},
- {_K("extensionrofs"),1+2, 1, EKeywordExtensionRofs, "Start of definition of optional Extension ROFS"},
- {_K("extensionrofsname"),1, 1, EKeywordCoreRofsName, "ROFS image on which extension ROFS is based"},
- {_K("rem"), 0, 0, EKeywordNone, "comment"},
- {_K("stop"), 0, 0, EKeywordNone, "Terminates OBEY file prematurely"},
- {_K("romchecksum"), 1, 1, EKeywordRomChecksum, "desired 32-bit checksum value for the whole ROFS image"},
- {_K("coreimage"), 1, 1, EKeywordCoreImage, "Core image to be used for extension directory structure"},
- {_K("autosize"), 1, 1, EKeywordRofsAutoSize, "Automatically adjust maximum image size to actual used"},
- {_K("pagingoverride"), 1, 1, EKeywordPagingOverride, "Overide the demand paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
- {_K("codepagingoverride"), 1, 1, EKeywordCodePagingOverride, "Overide the code paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
- {_K("datapagingoverride"), 1, 1, EKeywordDataPagingOverride, "Overide the data paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
- {_K("dataimagename"),1, 1,EKeywordDataImageName, "Data Drive image file name"},
- {_K("dataimagefilesystem"),1, 1,EKeywordDataImageFileSystem, "Drive image file system format"},
- {_K("dataimagesize"),1, 1,EKeywordDataImageSize, "Maximum size of Data Drive image"},
- {_K("volume"),1, -1,EKeywordDataImageVolume, "Volume Label of Data Drive image"},
- {_K("sectorsize"),1, 1,EKeywordDataImageSectorSize, "Sector size(in bytes) of Data Drive image"},
- {_K("fattable"),1, 1,EKeywordDataImageNoOfFats, "Number of FATs in the Data Drive image"},
- // things we don't normally report in the help information
- {_K("trace"), 1, 1, EKeywordTrace, "(ROMBUILD activity trace flags)"},
- {_K("filecompress"),2, -2,EKeywordFileCompress,"Non-XIP Executable to be loaded into the ROM compressed" },
- {_K("fileuncompress"),2, -2,EKeywordFileUncompress,"Non-XIP Executable to be loaded into the ROM uncompressed" },
- {_K("patchdata"),2, 5,EKeywordPatchDllData, "Patch exported data"},
- {_K("imagename"), 1, 1, EKeywordSmrImageName, "output file for SMR image"},
- {_K("hcrdata"), 1, 1, EKeywordSmrFileData, "file data for HCR SMR image"},
- {_K("formatversion"), 1, 1, EKeywordSmrFormatVersion, "format version for HCR SMR image"},
- {_K("payloadflags"), 1, 1, EKeywordSmrFlags, "payload flags for the HCR SMR image"},
- {_K("payloaduid"), 1, 1, EKeywordSmrUID, "payload UID for the HCR SMR image"},
- {0,0,0,0,EKeywordNone,""}
-};
-
-extern TInt isNumber(TText *aString);
-extern TInt getNumber(TText *aStr);
-
-void ObeyFileReader::KeywordHelp() // static
- {
- cout << "Obey file keywords:\n";
-
- const ObeyFileKeyword* k=0;
- for (k=iKeywords; k->iKeyword!=0; k++)
- {
- if (k->iHelpText==0)
- continue;
- if (k->iHelpText[0]=='(' && !H.iVerbose)
- continue; // don't normally report things in (parentheses)
-
- char buf[32];
- sprintf(buf, "%-20s", k->iKeyword);
- if (k->iKeywordLength)
- memcpy(buf+k->iKeywordLength,"[HWVD]",6);
- if (H.iVerbose)
- sprintf(buf+20,"%2d",k->iNumArgs);
- cout << " " << buf << " " << k->iHelpText << endl;
- }
- cout << endl;
-
- cout << "File attributes:\n";
-
- const FileAttributeKeyword* f=0;
- for (f=iAttributeKeywords; f->iKeyword!=0; f++)
- {
- if (f->iHelpText==0)
- continue;
- if (f->iHelpText[0]=='(' && !H.iVerbose)
- continue; // don't normally report things in (parentheses)
-
- char buf[32];
- sprintf(buf, "%-20s", f->iKeyword);
- if (H.iVerbose)
- sprintf(buf+20,"%2d",k->iNumArgs);
- cout << " " << buf << " " << f->iHelpText << endl;
- }
- cout << endl;
- }
-
-ObeyFileReader::ObeyFileReader(TText* aFileName):
-iObeyFile(0),iMark(0), iMarkLine(0), iCurrentMark(0), iCurrentLine(0), imaxLength(0)
- {
-
- iFileName = new TText[strlen((const char *)aFileName)+1];
- strcpy((char *)iFileName,(const char *)aFileName);
- iNumWords = 0 ;
- for(unsigned int i = 0 ; i < KNumWords ; i++)
- iWord[i] = 0 ;
- iSuffix = new TText();
- iLine = 0 ;
- iCurrentObeyStatement = 0 ;
- }
-
-
-ObeyFileReader::~ObeyFileReader()
- {
- if (iObeyFile)
- fclose(iObeyFile);
- iObeyFile=0;
- delete [] iFileName;
- delete [] iLine;
- delete [] iCurrentObeyStatement;
- }
-
-TBool ObeyFileReader::Open()
-//
-// Open the file & return a status
-//
-{
- if (!iFileName)
- {
- return EFalse;
- }
-
- iObeyFile = fopen((const char *)iFileName,"r");
- if (!iObeyFile)
- {
- Print(EError,"Cannot open obey file %s\n",iFileName);
- return EFalse;
- }
- if (SetLineLengthBuffer() != KErrNone)
- {
- Print(EError,"Insufficent Memory to Continue.");
- return EFalse;
- }
- return ETrue;
-}
-
- TInt ObeyFileReader::SetLineLengthBuffer()
- // Get the Max Line length for the given obey file and allocate the buffer.
- {
- char ch = '\0';
- TInt length = 0;
-
- Rewind();
- while ((ch = (char)fgetc(iObeyFile)) != EOF)
- {
- length++;
- if (ch == '\n')
- {
- if (length > imaxLength)
- imaxLength = length;
- length = 0;
- }
- }
-
- if (length > imaxLength)
- imaxLength = length;
-
- if (0 == imaxLength)
- {
- Print(EError,"Empty obey file passed as input.");
- exit(-1);
- }
- else if (imaxLength < 2)
- {
- Print(EError,"Invalid obey file passed as input.");
- exit(-1);
- }
-
- Rewind();
- iLine = new TText[imaxLength+1];
-
- if(!iLine)
- return KErrNoMemory;
-
- return KErrNone;
- }
-
-void ObeyFileReader::Mark()
- {
-
- iMark = iCurrentMark;
- iMarkLine = iCurrentLine-1;
- }
-
-void ObeyFileReader::MarkNext()
- {
-
- iMark = ftell(iObeyFile);
- iMarkLine = iCurrentLine;
- }
-
-void ObeyFileReader::Rewind()
- {
-
- fseek(iObeyFile,iMark,SEEK_SET);
- iCurrentMark = iMark;
- iCurrentLine = iMarkLine;
- }
-
-void ObeyFileReader::CopyWord(TInt aIndex, TText*& aString)
- {
- aString = new TText[strlen((const char *)iWord[aIndex])+1];
- strcpy((char *)aString, (const char *)iWord[aIndex]);
- }
-
-TInt ObeyFileReader::ReadAndParseLine()
- {
- if (feof(iObeyFile))
- return KErrEof;
- iCurrentLine++;
- iCurrentMark = ftell(iObeyFile);
- iLine[0]='\0';
- fgets((char*)iLine,imaxLength+1,iObeyFile);
- iCurrentObeyStatement = new TText[imaxLength+1];
- strcpy((char*)iCurrentObeyStatement,(char*)iLine);
- iNumWords = Parse();
- return KErrNone;
- }
-
-TInt ObeyFileReader::NextLine(TInt aPass, enum EKeyword& aKeyword)
- {
-
-NextLine:
- TInt err = ReadAndParseLine();
- if (err == KErrEof)
- return KErrEof;
- if (iNumWords == 0 || stricmp((const char*)iWord[0], "rem")==0)
- goto NextLine;
- if (stricmp((const char*)iWord[0], "stop")==0)
- return KErrEof;
-
- const ObeyFileKeyword* k=0;
- for (k=iKeywords; k->iKeyword!=0; k++)
- {
- if (k->iKeywordLength == 0)
- {
- // Exact case-insensitive match on keyword
- if (stricmp((const char*)iWord[0], k->iKeyword) != 0)
- continue;
- iSuffix = 0;
- }
- else
- {
- // Prefix match
- if (strnicmp((const char*)iWord[0], k->iKeyword, k->iKeywordLength) != 0)
- continue;
- // Suffix must be empty, or a variant number in []
- iSuffix = iWord[0]+k->iKeywordLength;
- if (*iSuffix != '\0' && *iSuffix != '[')
- continue;
- }
- // found a match
- if ((k->iPass & aPass) == 0)
- goto NextLine;
- if (k->iNumArgs>=0 && (1+k->iNumArgs != iNumWords))
- {
- Print(EError, "Incorrect number of arguments for keyword %s on line %d.\n",
- iWord[0], iCurrentLine);
- goto NextLine;
- }
- if (k->iNumArgs<0 && (1-k->iNumArgs > iNumWords))
- {
- Print(EError, "Too few arguments for keyword %s on line %d.\n",
- iWord[0], iCurrentLine);
- goto NextLine;
- }
-
- aKeyword = k->iKeywordEnum;
- return KErrNone;
- }
- if (aPass == 1)
- Print(EWarning, "Unknown keyword '%s'. Line %d ignored\n", iWord[0], iCurrentLine);
- goto NextLine;
- }
-
-inline TBool ObeyFileReader::IsGap(char ch)
- {
- return (ch==' ' || ch=='=' || ch=='\t');
- }
-
-TInt ObeyFileReader::Parse()
-//
-// splits a line into words, and returns the number of words found
-//
- {
-
- TInt i;
- TText *letter=iLine;
- TText *end=iLine+strlen((char *)iLine);
- for (i=0; (TUint)i<KNumWords; i++)
- iWord[i]=end;
-
- enum TState {EInWord, EInQuotedWord, EInGap};
- TState state=EInGap;
-
- i=0;
- while ((TUint)i<KNumWords && letter<end)
- {
- char ch=*letter;
- if (ch==0)
- break;
- if (ch=='\n')
- {
- *letter='\0'; // remove trailing newline left by fgets
- break;
- }
- switch (state)
- {
- case EInGap:
- if (ch=='\"')
- {
- if (letter[1]!=0 && letter[1]!='\"')
- iWord[i++]=letter+1;
- state=EInQuotedWord;
- }
- else if (!IsGap(ch))
- {
- iWord[i++]=letter;
- state=EInWord;
- }
- else
- *letter=0;
- break;
- case EInWord:
- if (ch=='\"')
- {
- *letter=0;
- if (letter[1]!=0 && letter[1]!='\"')
- iWord[i++]=letter+1;
- state=EInQuotedWord;
- }
- else if (IsGap(ch))
- {
- *letter=0;
- state=EInGap;
- }
- break;
- case EInQuotedWord:
- if (ch=='\"')
- {
- *letter=0;
- state=EInGap;
- }
- break;
- }
- letter++;
- }
- return i;
- }
-
-
-void ObeyFileReader::ProcessTime(TInt64& aTime)
-//
-// Process the timestamp
-//
- {
- char timebuf[256];
- if (iNumWords>2)
- sprintf(timebuf, "%s_%s", iWord[1], iWord[2]);
- else
- strcpy(timebuf, (char*)iWord[1]);
-
- TInt r=StringToTime(aTime, timebuf);
- if (r==KErrGeneral)
- {
- Print(EError, "incorrect format for time keyword on line %d\n", iCurrentLine);
- exit(0x670);
- }
- if (r==KErrArgument)
- {
- Print(EError, "Time out of range on line %d\n", iCurrentLine);
- exit(0x670);
- }
- }
-
-TInt64 ObeyFileReader::iTimeNow=0;
-void ObeyFileReader::TimeNow(TInt64& aTime)
- {
- if (iTimeNow==0)
- {
- TInt sysTime=time(0); // seconds since midnight Jan 1st, 1970
- sysTime-=(30*365*24*60*60+7*24*60*60); // seconds since midnight Jan 1st, 2000
- TInt64 daysTo2000AD=730497;
- TInt64 t=daysTo2000AD*24*3600+sysTime; // seconds since 0000
- t=t+3600; // BST (?)
- iTimeNow=t*1000000; // milliseconds
- }
- aTime=iTimeNow;
- }
-
-/**
-Funtion to get the current oby file line
-*/
-TText* ObeyFileReader::GetCurrentObeyStatement() const
-{
- return iCurrentObeyStatement;
-}
-
-// File attributes.
-
-
-const FileAttributeKeyword ObeyFileReader::iAttributeKeywords[] =
-{
- {"attrib",3 ,0,1,EAttributeAtt, "File attributes in ROM file system"},
- {"exattrib",3 ,0,1,EAttributeAttExtra, "File extra attributes in ROM file system"},
-// {_K("compress") ,1,1,EAttributeCompress, "Compress file"},
- {"stack",3 ,1,1,EAttributeStack, "?"},
- {"fixed",3 ,1,0,EAttributeFixed, "Relocate to a fixed address space"},
- {"priority",3 ,1,1,EAttributePriority, "Override process priority"},
- {_K("uid1") ,1,1,EAttributeUid1, "Override first UID"},
- {_K("uid2") ,1,1,EAttributeUid2, "Override second UID"},
- {_K("uid3") ,1,1,EAttributeUid3, "Override third UID"},
- {_K("heapmin") ,1,1,EAttributeHeapMin, "Override initial heap size"},
- {_K("heapmax") ,1,1,EAttributeHeapMax, "Override maximum heap size"},
- {_K("capability") ,1,1,EAttributeCapability, "Override capabilities"},
- {_K("unpaged") ,1,0,EAttributeUnpaged, "Don't page code or data for this file"},
- {_K("paged") ,1,0,EAttributePaged, "Page code and data for this file"},
- {_K("unpagedcode") ,1,0,EAttributeUnpagedCode, "Don't page code for this file"},
- {_K("pagedcode") ,1,0,EAttributePagedCode, "Page code for this file"},
- {_K("unpageddata") ,1,0,EAttributeUnpagedData, "Don't page data for this file"},
- {_K("pageddata") ,1,0,EAttributePagedData, "Page data for this file"},
- {0,0,0,0,EAttributeAtt,0}
-};
-
-TInt ObeyFileReader::NextAttribute(TInt& aIndex, TInt aHasFile, enum EFileAttribute& aKeyword, TText*& aArg)
- {
-NextAttribute:
- if (aIndex >= iNumWords)
- return KErrEof;
- TText* word=iWord[aIndex++];
- const FileAttributeKeyword* k;
- for (k=iAttributeKeywords; k->iKeyword!=0; k++)
- {
- if (k->iKeywordLength == 0)
- {
- // Exact match on keyword
- if (stricmp((const char*)word, k->iKeyword) != 0)
- continue;
- }
- else
- {
- // Prefix match
- if (strnicmp((const char*)word, k->iKeyword, k->iKeywordLength) != 0)
- continue;
- }
- // found a match
- if (k->iNumArgs>0)
- {
- TInt argIndex = aIndex;
- aIndex += k->iNumArgs; // interface only really supports 1 argument
- if (aIndex>iNumWords)
- {
- Print(EError, "Missing argument for attribute %s on line %d\n", word, iCurrentLine);
- return KErrArgument;
- }
- aArg=iWord[argIndex];
- }
- if (k->iIsFileAttribute && !aHasFile)
- {
- Print(EError, "File attribute %s applied to non-file on line %d\n", word, iCurrentLine);
- return KErrNotSupported;
- }
- aKeyword=k->iAttributeEnum;
- return KErrNone;
- }
- Print(EWarning, "Unknown attribute '%s' skipped on line %d\n", word, iCurrentLine);
- goto NextAttribute;
- }
-
-
-
-/**
-Constructor:
-1.Obey file instance.
-2.used by both rofs and datadrive image.
-
-@param aReader - obey file reader object.
-*/
-CObeyFile::CObeyFile(ObeyFileReader& aReader):
- iRomFileName(NULL),
- iExtensionRofsName(0),
- iKernelRofsName(0),
- iRomSize(0),
- iVersion(0,0,0),
- iCheckSum(0),
- iNumberOfFiles(0),
- iTime(0),
- iRootDirectory(0),
- iNumberOfDataFiles(0),
- iDriveFileName(0),
- iDataSize(0),
- iDriveFileFormat(0),
- iConfigurableFatAttributes(new ConfigurableFatAttributes),
- iReader(aReader),
- iMissingFiles(0),
- iLastExecutable(0),
- iFirstFile(0),
- iCurrentFile(0),
- iAutoSize(EFalse),
- iAutoPageSize(4096),
- iPagingOverrideParsed(0),
- iCodePagingOverrideParsed(0),
- iDataPagingOverrideParsed(0),
- iPatchData(new CPatchDataProcessor)
- {
- iNextFilePtrPtr = &iFirstFile ;
- }
-
-/**
-Obey file Destructor.
-1.Release the tree memory.
-2.Release all allocated memory if any.
-*/
-CObeyFile::~CObeyFile()
-//
-// Destructor
-//
- {
- if(iDriveFileName)
- delete[] iDriveFileName;
- if(iDriveFileFormat)
- delete[] iDriveFileFormat;
- iRootDirectory->deleteTheFirstNode();
- iRootDirectory->InitializeCount();
-
- Release();
- delete [] iRomFileName;
- if (iRootDirectory)
- iRootDirectory->Destroy();
-
- delete iConfigurableFatAttributes;
- delete iPatchData;
- }
-
-TBool CObeyFile::AutoSize()
-{
- return iAutoSize;
-}
-
-TUint32 CObeyFile::AutoPageSize()
-{
- return iAutoPageSize;
-}
-
-void CObeyFile::Release()
-//
-// Free resources not needed after building a ROM
-//
- {
- iFirstFile = 0;
- iNextFilePtrPtr = &iFirstFile;
- }
-
-TRomBuilderEntry *CObeyFile::FirstFile()
- {
- iCurrentFile = iFirstFile;
- return iCurrentFile;
- }
-
-TRomBuilderEntry *CObeyFile::NextFile()
- {
- iCurrentFile = iCurrentFile ? iCurrentFile->iNext : 0;
- return iCurrentFile;
- }
-
-TText* CObeyFile::ProcessCoreImage()
- {
- // check for coreimage keyword and return filename
- iReader.Rewind();
- enum EKeyword keyword;
- TText* coreImageFileName = 0;
- while (iReader.NextLine(1,keyword) != KErrEof)
- {
- if (keyword == EKeywordCoreImage)
- {
- #if defined(__TOOLS2__) && defined (_STLP_THREADS)
- istringstream val(iReader.Word(1),(ios_base::in+ios_base::out));
- #elif __TOOLS2__
- istringstream val(iReader.Word(1),(std::_Ios_Openmode)(ios_base::in+ios_base::out));
- #else
- istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
- #endif
- iReader.CopyWord(1, coreImageFileName);
- iReader.MarkNext(); // ready for processing extension
- break;
- }
- }
- return coreImageFileName;
- }
-
-void CObeyFile::SkipToExtension()
- {
- iReader.Rewind();
- enum EKeyword keyword;
- while (iReader.NextLine(1,keyword) != KErrEof)
- {
- if (keyword == EKeywordExtensionRofs)
- {
- iReader.Mark(); // ready for processing extension
- break;
- }
- }
- }
-TInt CObeyFile::ProcessRofs()
- {
- //
- // First pass through the obey file to set up key variables
- //
-
- iReader.Rewind();
-
- TInt count=0;
- enum EKeyword keyword;
- while (iReader.NextLine(1,keyword) != KErrEof)
- {
- if (keyword == EKeywordExtensionRofs)
- {
- if (count==0)
- return KErrNotFound; // no core ROFS, just extension ROFSs.
- break;
- }
-
- count++;
- if (! ProcessKeyword(keyword))
- return KErrGeneral;
- }
-
- if (!GotKeyVariables())
- return KErrGeneral;
-
- //
- // second pass to process the file specifications in the obey file building
- // up the TRomNode directory structure and the TRomBuilderEntry list
- //
- iReader.Rewind();
-
- iRootDirectory = new TRomNode((TText*)"");
- iLastExecutable = iRootDirectory;
-
- TInt align=0;
- while (iReader.NextLine(2,keyword)!=KErrEof)
- {
- if (keyword == EKeywordExtensionRofs)
- break;
-
- if (keyword == EKeywordHide)
- keyword = EKeywordHideV2;
-
- switch (keyword)
- {
-
- case EKeywordHide:
- case EKeywordAlias:
- case EKeywordRename:
- if (!ProcessRenaming(keyword))
- return KErrGeneral;
- break;
- case EKeywordPatchDllData:
- {
- // Collect patchdata statements to process at the end
- StringVector patchDataTokens;
- SplitPatchDataStatement(patchDataTokens);
- iPatchData->AddPatchDataStatement(patchDataTokens);
- break;
- }
- default:
- if (!ProcessFile(align, keyword))
- return KErrGeneral;
- align=0;
- break;
- }
- }
-
- if(!ParsePatchDllData())
- return KErrGeneral;
- iReader.Mark(); // ready for processing the extension rom(s)
-
- if (iMissingFiles!=0)
- {
- return KErrGeneral;
- }
- if ( 0 == iNumberOfFiles )
- {
- Print(EError, "No files specified.\n");
- return KErrGeneral;
- }
-
- return KErrNone;
- }
-
-TBool CObeyFile::Process()
-{
- TBool result = ETrue;
- iReader.Rewind();
- enum EKeyword keyword;
- while(iReader.NextLine(1, keyword) != KErrEof)
- {
- String key = iReader.Word(0);
- String value = iReader.Word(1);
- if(iKeyValues.find(key) != iKeyValues.end())
- {
- iKeyValues[key].push_back(value);
- }
- else
- {
- StringVector values;
- values.push_back(value);
- iKeyValues[key]=values;
- }
-
-
- }
- return result;
-}
-StringVector CObeyFile::getValues(const String& aKey)
-{
- StringVector values;
- if(iKeyValues.find(aKey) != iKeyValues.end())
- {
- values = iKeyValues[aKey];
- }
- return values;
-}
-
-/**
-Process drive obey file and construct the tree.
-
-@return - Return the status,
- 'KErrnone' for Success,
- 'KErrGeneral' for failure (required keywords not there in obey file or failed
- to construct the tree).
-*/
-TInt CObeyFile::ProcessDataDrive()
- {
-
- iReader.Rewind();
- enum EKeyword keyword;
-
- // First pass through the obey file to set up key variables
- while (iReader.NextLine(1,keyword) != KErrEof)
- {
- if (!ProcessDriveKeyword(keyword))
- return KErrGeneral;
- }
-
- if (!GotKeyDriveVariables())
- return KErrGeneral;
-
- // Second pass to process the file specifications in the obey file.
- // Build the TRomNode directory structure and the TRomBuilderEntry list
- iReader.Rewind();
- iRootDirectory = new TRomNode((TText*)"//");
- iLastExecutable = iRootDirectory;
-
- while(iReader.NextLine(2,keyword)!=KErrEof)
- {
- switch (keyword)
- {
- case EKeywordPatchDllData:
- { // Collect patchdata statements to process at the end
- StringVector patchDataTokens;
- SplitPatchDataStatement(patchDataTokens);
- iPatchData->AddPatchDataStatement(patchDataTokens);
- break;
- }
-
- case EKeywordHide:
- case EKeywordFile:
- case EKeywordData:
- case EKeywordFileCompress:
- case EKeywordFileUncompress:
- if (!ProcessDriveFile(keyword))
- return KErrGeneral;
- break;
-
- default:
- break;
- }
- }
-
- if(!ParsePatchDllData())
- return KErrGeneral;
- if (iMissingFiles)
- {
- Print(EError, "Source Files Missing.\n");
- return KErrGeneral;
- }
- if (!iNumberOfFiles)
- Print(EWarning,"No files specified.\n");
-
- return KErrNone;
- }
-
-
-/**
-Process and stores the keyword information.
-
-@param aKeyword - keyword to update its value to variables.
-@return - Return the status i.e Success,
-*/
-TBool CObeyFile::ProcessDriveKeyword(enum EKeyword aKeyword)
- {
-
- TBool success = ETrue;
- switch (aKeyword)
- {
- case EKeywordDataImageName:
- iReader.CopyWord(1, iDriveFileName);
- break;
- case EKeywordDataImageFileSystem:
- iReader.CopyWord(1, iDriveFileFormat);
- break;
- case EKeywordDataImageSize:
- {
- char* bigString = iReader.Word(1);
- if(*bigString == '\0')
- {
- Print(EWarning,"Not a valid Image Size. Default size is considered\n");
- break;
- }
-#ifdef __LINUX__
- errno = 0;
- iDataSize = strtoll(bigString,NULL,10);
- if((iDataSize == LONG_MAX) || (iDataSize == LONG_MIN) ||(errno == ERANGE))
- {
- Print(EWarning,"Invalid Range. Default size is considered\n");
- }
-#else
- iDataSize = _atoi64(bigString);
-#endif
- }
- break;
- case EKeywordDataImageVolume:
- {
- // Get the volume label provided by using "volume" keyword.
- // e.g. vlolume = NO NAME
- String volumeLabel = (char*)iReader.GetCurrentObeyStatement();
- String volumeLabelKeyword = "volume";
-
- TUint position = volumeLabel.find(volumeLabelKeyword.c_str(),0,volumeLabelKeyword.size());
- position += volumeLabelKeyword.size();
- if (volumeLabel.find('=',position) != std::string::npos)
- {
- position=volumeLabel.find('=',position);
- ++position;
- }
-
- position = volumeLabel.find_first_not_of(' ',position);
- if (position != std::string::npos)
- {
- volumeLabel = volumeLabel.substr(position);
-
- // Remove the new line character from the end
- position = volumeLabel.find_first_of("\r\n");
- if (position != std::string::npos)
- volumeLabel = volumeLabel.substr(0,position);
-
- iConfigurableFatAttributes->iDriveVolumeLabel = volumeLabel.data();
- }
- else
- {
- Print(EWarning,"Value for Volume Label is not provided. Default value is considered.\n");
- }
- break;
- }
- case EKeywordDataImageSectorSize:
- {
- char* bigString = iReader.Word(1);
- TInt sectorSize = atoi(bigString);
- if(sectorSize <= 0)
- {
- Print(EWarning,"Invalid Sector Size value. Default value is considered.\n");
- }
- else
- {
- iConfigurableFatAttributes->iDriveSectorSize = atoi(bigString);
- }
- }
- break;
- case EKeywordDataImageNoOfFats:
- {
- char* bigString = iReader.Word(1);
- TInt noOfFats = atoi(bigString);
- if (noOfFats <=0)
- {
- Print(EWarning,"Invalid No of FATs specified. Default value is considered.\n");
- }
- else
- {
- iConfigurableFatAttributes->iDriveNoOfFATs = atoi(bigString);
- }
- }
- break;
- default:
- // unexpected keyword iReader.Word(0), keep going.
- break;
- }
- return success;
- }
-
-
-/**
-Checks whether obeyfile has supplied enough variables to continue.
-
-@return - Return the status
- ETrue - Supplied valid values,
- EFalse- Not valied values.
-*/
-TBool CObeyFile::GotKeyDriveVariables()
- {
-
- TBool retVal=ETrue;
-
- // Mandatory keywords
- if (iDriveFileName==0)
- {
- Print(EError,"The name of the image file has not been supplied.\n");
- Print(EError,"Use the keyword \"dataimagename\".\n");
- retVal = EFalse;
- }
-
- // Check for '-'ve entered value.
- if(iDataSize <= 0)
- {
- Print(EWarning,"Image Size should be positive. Default size is Considered.\n");
- }
-
- // File system format.
- if(iDriveFileFormat==0)
- {
- Print(EError,"The name of the file system not been supplied.\n");
- Print(EError,"Use the keyword \"dataimagefilesystem\".\n");
- retVal = EFalse;
- }
-
- // Checking the validity of file system format.
- if(iDriveFileFormat)
- {
- strupr((char *)iDriveFileFormat);
- enum TFileSystem check = (TFileSystem)0;
- if(!(CDriveImage::FormatTranslation(iDriveFileFormat,check)))
- {
- Print(EError,"The name of the file system not supported : %s\n",iDriveFileFormat);
- retVal = EFalse;
- }
- }
-
- if(retVal)
- Print(ELog,"\nCreating Data Drive image : %s\n", iDriveFileName);
-
- return retVal;
- }
-
-/**
-Process a parsed line to set up one or more new TRomBuilder entry objects.
-
-@param - obey file keyword.
-// iWord[0] = the keyword (file,)
-// iWord[1] = the PC pathname
-// iWord[2] = the EPOC pathname
-// iWord[3] = start of the file attributes
-
-@return - Return the status
- ETrue - Successful generation of tree.
- EFalse- Fail to generate the tree.
-*/
-TBool CObeyFile::ProcessDriveFile(enum EKeyword aKeyword)
- {
-
- TBool isPeFile = ETrue;
- TBool aFileCompressOption, aFileUncompressOption;
-
- TInt epocPathStart=2;
- aFileCompressOption = aFileUncompressOption = EFalse;
- // do some validation of the keyword
- TInt currentLine = iReader.CurrentLine();
-
- switch (aKeyword)
- {
- case EKeywordData:
- case EKeywordHide:
- isPeFile = EFalse;
- break;
-
- case EKeywordFile:
- break;
-
- case EKeywordFileCompress:
- aFileCompressOption = ETrue;
- break;
-
- case EKeywordFileUncompress:
- aFileUncompressOption = ETrue;
- break;
-
- default:
- return EFalse;
- }
-
- if (aKeyword!=EKeywordHide)
- {
- // check the PC file exists
- char* nname = NormaliseFileName(iReader.Word(1));
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
- ifstream test(nname);
-#else //!__MSVCDOTNET__
- ifstream test(nname, ios::nocreate);
-#endif //__MSVCDOTNET__
-
- if (!test)
- {
- Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
- iMissingFiles++;
- }
-
- test.close();
- if(nname)
- free(nname);
- nname = 0;
- }
- else
- epocPathStart=1;
-
- iNumberOfFiles++;
-
- TBool endOfName=EFalse;
- TText *epocStartPtr=IsValidFilePath(iReader.Text(epocPathStart));
- TText *epocEndPtr=epocStartPtr;
-
- if (epocStartPtr==NULL)
- {
- Print(EError, "Invalid destination path on line %d\n",currentLine);
- return EFalse;
- }
-
- TRomNode* dir=iRootDirectory;
- TRomNode* subDir=0;
- TRomBuilderEntry *file=0;
-
- while (!endOfName)
- {
- endOfName = GetNextBitOfFileName(&epocEndPtr);
- if (endOfName) // file
- {
- TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
-
- if ((aKeyword != EKeywordHide) && alreadyExists) // duplicate file
- {
- Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
- return EFalse;
- }
- else if((aKeyword == EKeywordHide) && (alreadyExists))
- {
- alreadyExists->iEntry->iHidden = ETrue;
- alreadyExists->iHidden = ETrue;
- return ETrue;
- }
- else if((aKeyword == EKeywordHide) && (!alreadyExists))
- {
- Print(EWarning, "Hiding non-existent file %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
- return ETrue;
- }
-
- file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);
- file->iExecutable=isPeFile;
- if( aFileCompressOption )
- {
- file->iCompressEnabled = ECompressionCompress;
- }
- else if(aFileUncompressOption )
- {
- file->iCompressEnabled = ECompressionUncompress;
- }
-
- TRomNode* node=new TRomNode(epocStartPtr, file);
- if (node==0)
- return EFalse;
-
- TInt r=ParseFileAttributes(node, file, aKeyword);
- if (r!=KErrNone)
- return EFalse;
-
- if(gCompress != ECompressionUnknown)
- {
- node->iFileUpdate = ETrue;
- }
-
- if((node->iOverride) || (aFileCompressOption) || (aFileUncompressOption))
- {
- node->iFileUpdate = ETrue;
- }
-
- dir->AddFile(node); // to drive directory structure.
- }
- else
- {
- // directory
- subDir = dir->FindInDirectory(epocStartPtr);
- if (!subDir) // sub directory does not exist
- {
- if(aKeyword==EKeywordHide)
- {
- Print(EWarning, "Hiding non-existent file %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
- return ETrue;
- }
- subDir = dir->NewSubDir(epocStartPtr);
- if (!subDir)
- return EFalse;
- }
- dir=subDir;
-
- epocStartPtr = epocEndPtr;
- } // end of else.
- }
- return ETrue;
- }
-
-
-TInt CObeyFile::SetStackSize(TRomNode *aNode, TText *aStr)
- {
- if (isNumber(aStr)==0)
- return Print(EError, "Number required as argument for keyword 'stack'.\n");
- aNode->SetStackSize( getNumber(aStr) );
- return KErrNone;
- }
-
-TInt CObeyFile::SetHeapSizeMin(TRomNode *aNode, TText *aStr)
- {
- if (isNumber(aStr)==0)
- return Print(EError, "Number required as argument for keyword 'heapmin'.\n");
- aNode->SetHeapSizeMin( getNumber(aStr) );
- return KErrNone;
- }
-
-TInt CObeyFile::SetHeapSizeMax(TRomNode *aNode, TText *aStr)
- {
- if (isNumber(aStr)==0)
- return Print(EError, "Number required as argument for keyword 'heapmax'.\n");
- aNode->SetHeapSizeMax( getNumber(aStr) );
- return KErrNone;
- }
-
-TInt CObeyFile::SetCapability(TRomNode *aNode, TText *aStr)
- {
- if (isNumber(aStr))
- {
- Print(EDiagnostic,"Old style numeric CAPABILTY specification ignored.\n");
- return KErrNone;
- }
- SCapabilitySet cap;
- TInt r = ParseCapabilitiesArg(cap, (char*)aStr);
- if( KErrNone == r )
- {
- aNode->SetCapability( cap );
- }
- return r;
- }
-
-TInt CObeyFile::SetPriority(TRomNode *aNode, TText *aStr)
- {
- TProcessPriority priority;
- if (isNumber(aStr))
- {
- priority = (TProcessPriority)getNumber(aStr);
- }
- else
- {
- char *str=(char *)aStr;
- if (stricmp(str, "low")==0)
- priority=EPriorityLow;
- else if (strnicmp(str, "background", 4)==0)
- priority=EPriorityBackground;
- else if (strnicmp(str, "foreground", 4)==0)
- priority=EPriorityForeground;
- else if (stricmp(str, "high")==0)
- priority=EPriorityHigh;
- else if (strnicmp(str, "windowserver",3)==0)
- priority=EPriorityWindowServer;
- else if (strnicmp(str, "fileserver",4)==0)
- priority=EPriorityFileServer;
- else if (strnicmp(str, "realtimeserver",4)==0)
- priority=EPriorityRealTimeServer;
- else if (strnicmp(str, "supervisor",3)==0)
- priority=EPrioritySupervisor;
- else
- return Print(EError, "Unrecognised priority keyword.\n");
- }
- if (priority<EPriorityLow || priority>EPrioritySupervisor)
- return Print(EError, "Priority out of range.\n");
-
- aNode->SetPriority( priority );
- return KErrNone;
- }
-
-TInt CObeyFile::SetUid1(TRomNode *aNode, TText *aStr)
- {
- if (isNumber(aStr)==0)
- return Print(EError, "Number required as argument for keyword 'uid1'.\n");
- aNode->SetUid1( getNumber(aStr) );
- return KErrNone;
- }
-TInt CObeyFile::SetUid2(TRomNode *aNode, TText *aStr)
- {
- if (isNumber(aStr)==0)
- return Print(EError, "Number required as argument for keyword 'uid2'.\n");
- aNode->SetUid2( getNumber(aStr) );
- return KErrNone;
- }
-TInt CObeyFile::SetUid3(TRomNode *aNode, TText *aStr)
- {
- if (isNumber(aStr)==0)
- return Print(EError, "Number required as argument for keyword 'uid3'.\n");
- aNode->SetUid3( getNumber(aStr) );
- return KErrNone;
- }
-
-
-TInt CObeyFile::ParseFileAttributes(TRomNode *aNode, TRomBuilderEntry* aFile, enum EKeyword aKeyword)
-//
-// Process any inline keywords
-//
- {
- TInt currentLine = iReader.CurrentLine();
- enum EFileAttribute attribute;
- TInt r=KErrNone;
- TInt index=3;
- TText* arg=0;
-
- while(r==KErrNone)
- {
- r=iReader.NextAttribute(index,(aFile!=0),attribute,arg);
- if (r!=KErrNone)
- break;
- switch(attribute)
- {
- case EAttributeAtt:
- r=aNode->SetAtt(arg);
- break;
- case EAttributeAttExtra:
- r=aNode->SetAttExtra(arg, aFile, aKeyword);
- break;
- case EAttributeStack:
- r=SetStackSize(aNode, arg);
- break;
- case EAttributeFixed:
- aNode->SetFixed();
- r = KErrNone;
- break;
- case EAttributeUid1:
- r=SetUid1(aNode, arg);
- break;
- case EAttributeUid2:
- r=SetUid2(aNode, arg);
- break;
- case EAttributeUid3:
- r=SetUid3(aNode, arg);
- break;
- case EAttributeHeapMin:
- r=SetHeapSizeMin(aNode, arg);
- break;
- case EAttributeHeapMax:
- r=SetHeapSizeMax(aNode, arg);
- break;
- case EAttributePriority:
- r=SetPriority(aNode, arg);
- break;
- case EAttributeCapability:
- r=SetCapability(aNode, arg);
- break;
- case EAttributeUnpaged:
- aNode->iOverride |= KOverrideCodeUnpaged|KOverrideDataUnpaged;
- aNode->iOverride &= ~(KOverrideCodePaged|KOverrideDataPaged);
- break;
- case EAttributePaged:
- aNode->iOverride |= KOverrideCodePaged|KOverrideDataPaged;
- aNode->iOverride &= ~(KOverrideCodeUnpaged|KOverrideDataUnpaged);
- break;
- case EAttributeUnpagedCode:
- aNode->iOverride |= KOverrideCodeUnpaged;
- aNode->iOverride &= ~KOverrideCodePaged;
- break;
- case EAttributePagedCode:
- aNode->iOverride |= KOverrideCodePaged;
- aNode->iOverride &= ~KOverrideCodeUnpaged;
- break;
- case EAttributeUnpagedData:
- aNode->iOverride |= KOverrideDataUnpaged;
- aNode->iOverride &= ~KOverrideDataPaged;
- break;
- case EAttributePagedData:
- aNode->iOverride |= KOverrideDataPaged;
- aNode->iOverride &= ~KOverrideDataUnpaged;
- break;
-
- default:
- return Print(EError, "Unrecognised keyword in file attributes on line %d.\n",currentLine);
- }
- }
-
- if (r==KErrEof)
- return KErrNone;
- return r;
- }
-
-
-TBool CObeyFile::ProcessFile(TInt /*aAlign*/, enum EKeyword aKeyword)
-//
-// Process a parsed line to set up one or more new TRomBuilder entry objects.
-// iWord[0] = the keyword (file, primary or secondary)
-// iWord[1] = the PC pathname
-// iWord[2] = the EPOC pathname
-// iWord[3] = start of the file attributes
-//
- {
- TBool isPeFile = ETrue;
- TBool aFileCompressOption, aFileUncompressOption;
- TInt epocPathStart=2;
- aFileCompressOption = aFileUncompressOption = EFalse;
- TBool warnFlag = EFalse;
- static const char aStdPath[] = "SYS\\BIN\\";
- static const int sysBinLength = sizeof(aStdPath)-1;
-
- // do some validation of the keyword
- TInt currentLine = iReader.CurrentLine();
-
- switch (aKeyword)
- {
- case EKeywordData:
- case EKeywordHideV2:
- iNumberOfDataFiles++;
- isPeFile = EFalse;
- break;
-
- case EKeywordFile:
- warnFlag = gEnableStdPathWarning;
- break;
- case EKeywordFileCompress:
- aFileCompressOption = ETrue;
- warnFlag = gEnableStdPathWarning;
- break;
- case EKeywordFileUncompress:
- aFileUncompressOption = ETrue;
- warnFlag = gEnableStdPathWarning;
- break;
-
- default:
- Print(EError,"Unexpected keyword '%s' on line %d.\n",iReader.Word(0),currentLine);
- return EFalse;
- }
-
- if (aKeyword!=EKeywordHideV2)
- {
-
- // check the PC file exists
- char* nname = NormaliseFileName(iReader.Word(1));
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
- ifstream test(nname);
-#else //!__MSVCDOTNET__
- ifstream test(nname, ios::nocreate);
-#endif //__MSVCDOTNET__
-
- if (!test)
- {
- Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
- iMissingFiles++;
- }
- test.close();
- free(nname);
- }
- else
- epocPathStart=1;
-
- iNumberOfFiles++;
-
-
- TBool endOfName=EFalse;
- TText *epocStartPtr=IsValidFilePath(iReader.Text(epocPathStart));
- TText *epocEndPtr=epocStartPtr;
- if (epocStartPtr==NULL)
- {
- Print(EError, "Invalid destination path on line %d\n",currentLine);
- return EFalse;
- }
- if(warnFlag) // Check for the std destination path(for executables) as per platsec.
- {
- if(strnicmp(aStdPath,(const char*)epocStartPtr,sysBinLength) != 0)
- {
- Print(EWarning,"Invalid destination path on line %d. \"%s\" \n",currentLine,epocStartPtr);
- }
- }
-
- TRomNode* dir=iRootDirectory;
- TRomNode* subDir=0;
- TRomBuilderEntry *file=0;
- while (!endOfName)
- {
- endOfName = GetNextBitOfFileName(&epocEndPtr);
- if (endOfName) // file
- {
- TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
- /*
- * The EKeywordHideV2 keyword is used to indicate that:
- * 1. if the file exists in the same image and then hidden, mark it hidden
- * 2. if the file exists in another image, but in this (ROFS) image, it is
- * required to hide that file, create a 0 length file entry setting the 'hide'
- * flag so that at runtime, file gets hidden in the composite filesystem.
- */
- if ((aKeyword != EKeywordHideV2) && alreadyExists) // duplicate file
- {
- Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
- return EFalse;
- }
-
- TBool aHidden = aKeyword==EKeywordHideV2;
- /* The file is only marked hidden and hence the source file name isn't known
- * here as hide statement says :
- * hide <filename as in ROM>
- * Therefore, create TRomBuilderEntry with iFileName as 0 for hidden file when
- * the file doesn't exist in the same ROM image. Otherwise, the src file name
- * is known because of alreadyExists (which comes from the 'file'/'data' statement).
- */
- if(aHidden)
- file = new TRomBuilderEntry(0, epocStartPtr);
- else
- file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);
- file->iExecutable=isPeFile;
- file->iHidden= aHidden;
- if( aFileCompressOption )
- {
- file->iCompressEnabled = ECompressionCompress;
- }
- else if(aFileUncompressOption )
- {
- file->iCompressEnabled = ECompressionUncompress;
- }
- TRomNode* node=new TRomNode(epocStartPtr, file);
- if (node==0)
- return EFalse;
- TInt r=ParseFileAttributes(node, file, aKeyword);
- if (r!=KErrNone)
- return EFalse;
-
- dir->AddFile(node); // to ROFS directory structure
- AddFile(file); // to our list of files
- }
- else // directory
- {
- subDir = dir->FindInDirectory(epocStartPtr);
- if (!subDir) // sub directory does not exist
- {
- subDir = dir->NewSubDir(epocStartPtr);
- if (!subDir)
- return EFalse;
- }
- dir=subDir;
- epocStartPtr = epocEndPtr;
- }
- }
- return ETrue;
- }
-
-
-TBool CObeyFile::ProcessRenaming(enum EKeyword aKeyword)
- {
-
- // find existing file
- TBool endOfName=EFalse;
- TText *epocStartPtr=IsValidFilePath(iReader.Text(1));
-
- // Store the current name and new name to maintain renamed file map
- String currentName=iReader.Word(1);
- String newName=iReader.Word(2);
-
- TText *epocEndPtr=epocStartPtr;
- if (epocStartPtr==NULL)
- {
- Print(EError, "Invalid source path on line %d\n",iReader.CurrentLine());
- return EFalse;
- }
-
- char saved_srcname[257];
- strcpy(saved_srcname, iReader.Word(1));
-
- TRomNode* dir=iRootDirectory;
- TRomNode* existingFile=0;
- while (!endOfName)
- {
- endOfName = GetNextBitOfFileName(&epocEndPtr);
- if (endOfName) // file
- {
- existingFile=dir->FindInDirectory(epocStartPtr);
- if (existingFile)
- {
- TInt fileCount=0;
- TInt dirCount=0;
- existingFile->CountDirectory(fileCount, dirCount);
- if (dirCount != 0 || fileCount != 0)
- {
- Print(EError, "Keyword %s not applicable to directories - line %d\n",iReader.Word(0),iReader.CurrentLine());
- return EFalse;
- }
- }
- }
- else // directory
- {
- TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
- if (!subDir) // sub directory does not exist
- break;
- dir=subDir;
- epocStartPtr = epocEndPtr;
- }
- }
- if (aKeyword == EKeywordHide)
- {
- /*
- * The EKeywordHide keyword is used to indicate that if the file exists in
- * the primary ROFS image and then hidden in extension ROFS, mark it hidden.
- */
- if (!existingFile)
- {
- Print(EWarning, "Hiding non-existent file %s on line %d\n",
- saved_srcname, iReader.CurrentLine());
- // Just a warning, as we've achieved the right overall effect.
- }
- else if (existingFile->iFileStartOffset==(TUint)KFileHidden)
- {
- Print(EWarning, "Hiding already hidden file %s on line %d\n",
- saved_srcname, iReader.CurrentLine());
- // We will igrore this request, otherwise it will "undelete" it.
- }
- else
- {
- //hidden files will not be placed to the image
- existingFile->iHidden = ETrue;
- }
- return ETrue;
- }
-
- if (!existingFile)
- {
- Print(EError, "Can't %s non-existent source file %s on line %d\n",
- iReader.Word(0), saved_srcname, iReader.CurrentLine());
- return EFalse;
- }
-
- epocStartPtr=IsValidFilePath(iReader.Text(2));
- epocEndPtr=epocStartPtr;
- endOfName=EFalse;
- if (epocStartPtr==NULL)
- {
- Print(EError, "Invalid destination path on line %d\n",iReader.CurrentLine());
- return EFalse;
- }
-
- TRomNode* newdir=iRootDirectory;
- while (!endOfName)
- {
- endOfName = GetNextBitOfFileName(&epocEndPtr);
- if (endOfName) // file
- {
- TRomNode* alreadyExists=newdir->FindInDirectory(epocStartPtr);
- if (alreadyExists && !(alreadyExists->iHidden)) // duplicate file
- {
- Print(EError, "Duplicate file for %s on line %d\n",saved_srcname,iReader.CurrentLine());
- return EFalse;
- }
- }
- else // directory
- {
- TRomNode* subDir = newdir->FindInDirectory(epocStartPtr);
- if (!subDir) // sub directory does not exist
- {
- subDir = newdir->NewSubDir(epocStartPtr);
- if (!subDir)
- return EFalse;
- }
- newdir=subDir;
- epocStartPtr = epocEndPtr;
- }
- }
-
- if (aKeyword == EKeywordRename)
- {
- // rename => remove existingFile and insert into tree at new place
- // has no effect on the iNextExecutable or iNextNodeForSameFile links
-
- TInt r=ParseFileAttributes(existingFile, existingFile->iEntry, aKeyword);
- if (r!=KErrNone)
- return EFalse;
- existingFile->Rename(dir, newdir, epocStartPtr);
- // Store the current and new name of file in the renamed file map.
- iPatchData->AddToRenamedFileMap(currentName, newName);
- return ETrue;
- }
-
- // alias => create new TRomNode entry and insert into tree
-
- TRomNode* node = new TRomNode(epocStartPtr, 0);
- if (node == 0)
- {
- Print(EError, "Out of memory\n");
- return EFalse;
- }
- node->Alias(existingFile);
- TInt r=ParseFileAttributes(node, 0, aKeyword);
- if (r!=KErrNone)
- return EFalse;
-
- newdir->AddFile(node); // to ROFS directory structure, though possibly hidden
-
- return ETrue;
- }
-
-TInt ParsePagingPolicy(const char* policy)
- {
- if(stricmp(policy,"NOPAGING")==0)
- return EKernelConfigPagingPolicyNoPaging;
- else if (stricmp(policy,"ALWAYSPAGE")==0)
- return EKernelConfigPagingPolicyAlwaysPage;
- else if(stricmp(policy,"DEFAULTUNPAGED")==0)
- return EKernelConfigPagingPolicyDefaultUnpaged;
- else if(stricmp(policy,"DEFAULTPAGED")==0)
- return EKernelConfigPagingPolicyDefaultPaged;
- return KErrArgument;
- }
-
-TBool CObeyFile::ProcessKeyword(enum EKeyword aKeyword)
- {
- #ifdef __TOOLS2__
- istringstream val(iReader.Word(1));
- #else
- istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
- #endif
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
- val >> setbase(0);
-#endif //__MSVCDOTNET__
-
- TBool success = ETrue;
-
- switch (aKeyword)
- {
- case EKeywordRofsName:
- iReader.CopyWord(1, iRomFileName);
- break;
- case EKeywordRofsSize:
- val >> iRomSize;
- break;
- case EKeywordVersion:
- val >> iVersion;
- break;
- case EKeywordRofsChecksum:
- val >> iCheckSum;
- break;
- case EKeywordTime:
- iReader.ProcessTime(iTime);
- break;
- case EKeywordPagingOverride:
- {
- if(iPagingOverrideParsed)
- Print(EWarning, "PagingOverride redefined - previous PagingOverride values lost\n");
- if(iCodePagingOverrideParsed)
- Print(EWarning, "PagingOverride defined - previous CodePagingOverride values lost\n");
- if(iDataPagingOverrideParsed)
- Print(EWarning, "PagingOverride defined - previous DataPagingOverride values lost\n");
- iPagingOverrideParsed = true;
- TInt policy = ParsePagingPolicy(iReader.Word(1));
- if(policy<0)
- {
- Print(EError,"Unrecognised option for PAGINGOVERRIDE keyword\n");
- success = false;
- }
- else
- {
- gCodePagingOverride = policy;
- gDataPagingOverride = policy;
- }
- }
- break;
- case EKeywordCodePagingOverride:
- {
- if(iCodePagingOverrideParsed)
- Print(EWarning, "CodePagingOverride redefined - previous CodePagingOverride values lost\n");
- if(iPagingOverrideParsed)
- Print(EWarning, "CodePagingOverride defined - previous PagingOverride values lost\n");
- iCodePagingOverrideParsed = true;
- TInt policy = ParsePagingPolicy(iReader.Word(1));
- if(policy<0)
- {
- Print(EError,"Unrecognised option for CODEPAGINGOVERRIDE keyword\n");
- success = false;
- }
- else
- gCodePagingOverride = policy;
- }
- break;
- case EKeywordDataPagingOverride:
- {
- if(iDataPagingOverrideParsed)
- Print(EWarning, "DataPagingOverride redefined - previous DataPagingOverride values lost\n");
- if(iPagingOverrideParsed)
- {
- Print(EError, "DataPagingOverride defined - previous PagingOverride values lost\n");
- success = false;
- break;
- }
- iDataPagingOverrideParsed = true;
- TInt policy = ParsePagingPolicy(iReader.Word(1));
- if(policy<0)
- {
- Print(EError,"Unrecognised option for DATAPAGINGOVERRIDE keyword\n");
- success = false;
- }
- else
- gDataPagingOverride = policy;
- }
- break;
- case EKeywordRofsAutoSize:
- iAutoSize = ETrue;
- val >> iAutoPageSize;
- break;
- default:
- // unexpected keyword iReader.Word(0)
- break;
- }
-
- return success;
- }
-
-TBool CObeyFile::GotKeyVariables()
-//
-// Checks that the obeyfile has supplied enough variables to continue
-//
- {
-
- TBool retVal=ETrue;
-
- // Mandatory keywords
-
- if (iRomFileName==0)
- {
- Print(EAlways,"The name of the image file has not been supplied.\n");
- Print(EAlways,"Use the keyword \"rofsname\".\n");
- retVal = EFalse;
- }
- if (iRomSize==0)
- {
- Print(EAlways,"The size of the image has not been supplied.\n");
- Print(EAlways,"Use the keyword \"rofssize\".\n");
- retVal = EFalse;
- }
-
- // Apply defaults as necessary
- if (iTime==0)
- {
- Print(ELog, "No timestamp specified. Using current time...\n");
- ObeyFileReader::TimeNow(iTime);
- }
-
- Print(ELog, "\nCreating Rofs image %s\n", iRomFileName);
- return retVal;
- }
-
-
-TText *CObeyFile::IsValidFilePath(TText *aPath)
-//
-// Check the path is valid
-//
- {
- // skip leading "\"
- if (*aPath=='\\')
- aPath++;
- if (*aPath==0)
- return NULL; // file ends in a backslash
-
- TText *p=aPath;
- TInt len=0;
- FOREVER
- {
- if (*p==0)
- return (len ? aPath : NULL);
- if (*p=='\\')
- {
- if (len==0)
- return NULL;
- len=0;
- }
- len++;
- p++;
- }
- }
-
-TBool CObeyFile::GetNextBitOfFileName(TText **epocEndPtr)
-//
-// Move the end pointer past the next directory separator, replacing it with 0
-//
- {
- while (**epocEndPtr != '\\') // until reach the directory separator
- {
- if (**epocEndPtr==0) // if reach end of string, return TRUE, it's the filename
- return ETrue;
- (*epocEndPtr)++;
- }
- **epocEndPtr=0; // overwrite the directory separator with a 0
- (*epocEndPtr)++; // point past the 0 ready for the next one
- return EFalse;
- }
-
-
-void CObeyFile::AddFile(TRomBuilderEntry* aFile)
- {
- *iNextFilePtrPtr = aFile;
- iNextFilePtrPtr = &(aFile->iNext);
- }
-
-
-
-TInt CObeyFile::ProcessExtensionRofs(MRofsImage* aKernelRom)
- {
- //
- // First pass through the obey file to set up key variables
- //
-
-
- iReader.Rewind();
-
- enum EKeyword keyword;
-
- // Deal with the "extensionrofs" keyword, which should be first
-
- if (iReader.NextLine(1,keyword) != KErrNone)
- return KErrEof;
- if (keyword != EKeywordExtensionRofs)
- return Print(EError, "Unexpected keyword '%s' at start of extension rom - line %d\n",
- iReader.Word(0), iReader.CurrentLine());
-
- iReader.CopyWord(1, iRomFileName);
- Print(ELog, "\n========================================================\n");
- Print(ELog, "Extension ROFS %s starting at line %d\n\n", iRomFileName, iReader.CurrentLine());
-
-
- iReader.MarkNext(); // so that we rewind to the line after the extensionrom keyword
-
- while (iReader.NextLine(1,keyword) != KErrEof)
- {
- if (keyword == EKeywordExtensionRofs)
- break;
- ProcessExtensionKeyword(keyword);
- }
-
- if (!GotExtensionVariables(aKernelRom))
- return KErrGeneral;
-
- // second pass to process the file specifications in the obey file building
- // up the TRomNode directory structure and the TRomBuilderEntry list
- //
- iReader.Rewind();
-
- //
- if (aKernelRom==0)
- return Print(EError, "Option to extend a kernel ROFS image not yet implemented\n");
-
-
-
- iRootDirectory = new TRomNode((TText*)"");
-
- iLastExecutable = 0;
-
- (aKernelRom->RootDirectory())->deleteTheFirstNode();
-
-
- iRootDirectory = aKernelRom->CopyDirectory(iLastExecutable);
- aKernelRom->SetRootDirectory(iRootDirectory);
-
-
- TInt align=0;
- while (iReader.NextLine(2,keyword)!=KErrEof)
- {
- if (keyword == EKeywordExtensionRofs)
- break;
-
- switch (keyword)
- {
- case EKeywordHide:
- case EKeywordAlias:
- case EKeywordRename:
- if (!ProcessRenaming(keyword))
- return KErrGeneral;
- break;
-
- case EKeywordPatchDllData:
- {
- // Collect patchdata statements to process at the end
- StringVector patchDataTokens;
- SplitPatchDataStatement(patchDataTokens);
- iPatchData->AddPatchDataStatement(patchDataTokens);
- break;
- }
- default:
- if (!ProcessFile(align, keyword))
- return KErrGeneral;
- align=0;
- break;
- }
- }
-
- if(!ParsePatchDllData() )
- return KErrGeneral;
-
- iReader.Mark(); // ready for processing the next extension rom(s)
-
- if (iMissingFiles!=0)
- return KErrGeneral;
- if (iNumberOfFiles==0)
- {
- Print(EError, "No files specified.\n");
- return KErrGeneral;
- }
- return KErrNone;
- }
-
-
-
-
-void CObeyFile::ProcessExtensionKeyword(enum EKeyword aKeyword)
- {
- #ifdef __TOOLS2__
- istringstream val(iReader.Word(1));
- #else
- istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
- #endif
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
- val >> setbase(0);
-#endif //__MSVCDOTNET__
-
- switch (aKeyword)
- {
- case EKeywordCoreRofsName:
- iReader.CopyWord(1, iKernelRofsName);
- return;
- case EKeywordRofsSize:
- val >> iRomSize;
- return;
- case EKeywordVersion:
- val >> iVersion;
- return;
- case EKeywordRomChecksum:
- val >> iCheckSum;
- return;
- case EKeywordTime:
- iReader.ProcessTime(iTime);
- return;
- case EKeywordRofsAutoSize:
- iAutoSize = ETrue;
- val >> iAutoPageSize;
- return;
- default:
- Print(EError,"Keyword '%s' not valid in extension ROFS - line %d\n", iReader.Word(0), iReader.CurrentLine());
- break;
- }
- return;
- }
-
-TBool CObeyFile::GotExtensionVariables(MRofsImage* aRom)
-//
-// Checks that the obeyfile has supplied enough variables to continue
-//
- {
-
- TBool retVal=ETrue;
- TText* kernelRofsName = iKernelRofsName;
-
- // Mandatory keywords
-
- if (iRomSize==0)
- {
- Print(EAlways,"The size of the extension ROFS has not been supplied.\n");
- Print(EAlways,"Use the keyword \"rofssize\".\n");
- retVal = EFalse;
- }
-
- // keywords we need if we don't already have a ROFS image to work from
-
- if (aRom==0)
- {
- if (iKernelRofsName==0)
- {
- Print(EAlways,"The name of the core ROFS has not been supplied.\n");
- Print(EAlways,"Use the keyword \"rofsname\".\n");
- retVal = EFalse;
- }
- }
- else
- {
- if (iKernelRofsName != 0)
- {
- Print(EWarning,"Keyword \"rofsname\" ignored.\n");
- }
- kernelRofsName = aRom->RomFileName();
- }
-
- // validation
-
- // Apply defaults as necessary
- if (iTime==0)
- {
- Print(ELog, "No timestamp specified. Using current time...\n");
- ObeyFileReader::TimeNow(iTime);
- }
-
- // fix up "*" in rofsname
- TText newname[256];
- TText* p=newname;
- TText* q=iRomFileName;
- TText c;
-
- while ((c=*q++)!='\0')
- {
- if (c!='*')
- {
- *p++=c;
- continue;
- }
- TText *r=kernelRofsName;
- while ((c=*r++)!='\0')
- *p++=c;
- }
- *p = '\0';
- free(iRomFileName);
- iRomFileName = (TText*)strdup((char*)newname);
-
- Print(ELog, "\nCreating ROFS image %s\n", iRomFileName);
-
- return retVal;
- }
-
-// Fuction to split patchdata statement
-void CObeyFile::SplitPatchDataStatement(StringVector& aPatchDataTokens)
-{
- // Get the value of symbol size, address/ordinal and new value
- // to be patched from the patchdata statement.
- // Syntax of patchdata statements is as follows:
- // 1) patchdata dll_name ordinal OrdinalNumber size_in_bytes new_value
- // 2) patchdata dll_name addr Address size_in_bytes new_value
- for(TInt count=1; count<=5; count++)
- {
- aPatchDataTokens.push_back(iReader.Word(count));
- }
-
- // Store the the value of current line which will be used
- // when displaying error messages.
- OutputStringStream outStrStream;
- outStrStream<<iReader.CurrentLine();
- aPatchDataTokens.push_back(outStrStream.str());
-}
-
-TBool CObeyFile::ParsePatchDllData()
-{
- // Get the list of patchdata statements
- VectorOfStringVector patchDataStatements=iPatchData->GetPatchDataStatements();
- // Get the list of renamed file map
- MapOfString RenamedFileMap=iPatchData->GetRenamedFileMap();
-
- for(TUint count=0; count<patchDataStatements.size(); count++)
- {
- StringVector strVector = patchDataStatements.at(count);
- String filename=strVector.at(0);
- String lineNoStr = strVector.at(5);
- TUint lineNo=getNumber(((TText*)lineNoStr.c_str()));
- TRomNode* existingFile = NULL;
-
- do
- {
- TRomNode* dir=iRootDirectory;
- TBool endOfName=EFalse;
-
- TText *epocStartPtr=IsValidFilePath((TText*)filename.c_str());
- if (epocStartPtr==NULL)
- {
- Print(EError, "Invalid source path on line %d\n",lineNo);
- return EFalse;
- }
- epocStartPtr = (TText*)NormaliseFileName((const char*)epocStartPtr);
- TText *epocEndPtr=epocStartPtr;
-
- while (!endOfName)
- {
- endOfName = GetNextBitOfFileName(&epocEndPtr);
- if (endOfName) // file
- {
- existingFile=dir->FindInDirectory(epocStartPtr);
- if (existingFile)
- {
- TInt fileCount=0;
- TInt dirCount=0;
- existingFile->CountDirectory(fileCount, dirCount);
- if (dirCount != 0 || fileCount != 0)
- {
- Print(EError, "Keyword %s not applicable to directories - line %d\n","patchdata",lineNo);
- return EFalse;
- }
- }
- }
- else // directory
- {
- TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
- if (!subDir) // sub directory does not exist
- break;
- dir=subDir;
- epocStartPtr = epocEndPtr;
- }
- }
-
- if(!existingFile)
- {
- // If the E32Image file to be patched is not included then check if the
- // file was renamed.
- MapOfStringIterator RenamedFileMapIterator;
- if ((RenamedFileMapIterator=RenamedFileMap.find(filename)) != RenamedFileMap.end())
- filename = (*RenamedFileMapIterator).second;
- else
- {
- Print(EError, "File %s not found - line %d\n", filename.c_str(), lineNo);
- return EFalse;
- }
- }
- }while(!existingFile);
-
- TUint32 aSize, aOrdinal, aNewValue, aOffset;
- TLinAddr aDataAddr;
-
- aOrdinal = (TUint32)-1;
- aDataAddr = (TUint32)-1;
- aOffset = 0;
-
- String symbolSize=strVector.at(3);
- aSize = getNumber((TText*)symbolSize.c_str());
- String aValue=strVector.at(4);
- aNewValue = getNumber((TText*)aValue.c_str());
-
- DllDataEntry *dataEntry = new DllDataEntry(aSize, aNewValue);
-
- // Set the address of the data or the ordinal number specified in OBY statement.
- String keyword=strVector.at(1);
- String keywordValue=strVector.at(2);
-
- /* Check for +OFFSET at the end of the ordinal number or address */
- TUint plus = keywordValue.find("+",0);
- if (plus != std::string::npos)
- {
- /* Get the offset that we found after the + sign */
- String offset = keywordValue.substr(plus+1);
- aOffset = getNumber((TText*)offset.c_str());
-
- keywordValue.resize(plus);
- }
- if(stricmp (keyword.c_str(), "addr") == 0)
- aDataAddr = getNumber((TText*)keywordValue.c_str());
-
- else
- aOrdinal = getNumber((TText*)keywordValue.c_str());
-
- dataEntry->iDataAddress = aDataAddr;
- dataEntry->iOrdinal = aOrdinal;
- dataEntry->iOffset = aOffset;
-
- existingFile->SetDllData();
-
- DllDataEntry *aDllDataEntry= existingFile->iEntry->GetFirstDllDataEntry();
- if (aDllDataEntry==NULL)
- {
- // Set the first node of the patchdata linked list
- aDllDataEntry=dataEntry;
- existingFile->iEntry->SetFirstDllDataEntry(aDllDataEntry);
- }
- else
- {
- // Goto the last node
- while((aDllDataEntry->NextDllDataEntry()) != NULL)
- {
- aDllDataEntry = aDllDataEntry->NextDllDataEntry();
- }
-
- // Add the new node at the end of linked list
- aDllDataEntry->AddDllDataEntry(dataEntry);
- }
- }
- return ETrue;
-}
-
-
-
-
-
-
-
-
-
+/*
+* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* @internalComponent * @released
+* Rofsbuild Obey file class and its reader class.
+*
+*/
+
+#include <strstream>
+#include <iomanip>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <e32rom.h>
+#include <u32std.h>
+#include <f32file.h>
+
+#include "h_utl.h"
+#include "r_obey.h"
+#include "r_coreimage.h"
+#include "patchdataprocessor.h"
+#include "fatimagegenerator.h"
+#include "r_driveimage.h"
+
+extern TInt gCodePagingOverride;
+extern TInt gDataPagingOverride;
+extern ECompression gCompress;
+extern TBool gEnableStdPathWarning; // Default to not warn if destination path provided for a file is not in standard path.
+extern TBool gKeepGoing;
+
+
+#define _P(word) word, sizeof(word)-1 // match prefix, optionally followed by [HWVD]
+#define _K(word) word, 0 // match whole word
+static char* const NullString = "" ;
+const ObeyFileKeyword ObeyFileReader::iKeywords[] =
+{
+ {_K("file"), 2,-2, EKeywordFile, "File to be copied into ROFS"},
+ {_K("data"), 2,-2, EKeywordData, "same as file"},
+ {_K("dir"), 2,1, EKeywordDir, "Directory to be created into FAT image"},
+
+ {_K("rofsname"), 1, 1, EKeywordRofsName, "output file for ROFS image"},
+ {_K("romsize"), 1, 1, EKeywordRomSize, "size of ROM image"},
+ {_P("hide"), 2, -1, EKeywordHide, "Exclude named file from ROM directory structure"},
+ {_P("alias"), 2, -2, EKeywordAlias, "Create alias for existing file in ROM directory structure"},
+ {_P("rename"), 2, -2, EKeywordRename, "Change the name of a file in the ROM directory structure"},
+ {_K("rofssize"), 1, 1, EKeywordRofsSize, "maximum size of ROFS image"},
+ {_K("romchecksum"), 1, 1, EKeywordRofsChecksum, "desired 32-bit checksum value for the whole image"},
+ {_K("version"), 1, 1, EKeywordVersion, "ROFS image version number"},
+ {_K("time"), 1,-1, EKeywordTime, "ROFS image timestamp"},
+ {_K("extensionrofs"),1+2, 1, EKeywordExtensionRofs, "Start of definition of optional Extension ROFS"},
+ {_K("extensionrofsname"),1, 1, EKeywordCoreRofsName, "ROFS image on which extension ROFS is based"},
+ {_K("rem"), 0, 0, EKeywordNone, "comment"},
+ {_K("stop"), 0, 0, EKeywordNone, "Terminates OBEY file prematurely"},
+ {_K("romchecksum"), 1, 1, EKeywordRomChecksum, "desired 32-bit checksum value for the whole ROFS image"},
+ {_K("coreimage"), 1, 1, EKeywordCoreImage, "Core image to be used for extension directory structure"},
+ {_K("autosize"), 1, 1, EKeywordRofsAutoSize, "Automatically adjust maximum image size to actual used"},
+ {_K("pagingoverride"), 1, 1, EKeywordPagingOverride, "Overide the demand paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
+ {_K("codepagingoverride"), 1, 1, EKeywordCodePagingOverride, "Overide the code paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
+ {_K("datapagingoverride"), 1, 1, EKeywordDataPagingOverride, "Overide the data paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
+ {_K("dataimagename"),1, 1,EKeywordDataImageName, "Data Drive image file name"},
+ {_K("dataimagefilesystem"),1, 1,EKeywordDataImageFileSystem, "Drive image file system format"},
+ {_K("dataimagesize"),1, 1,EKeywordDataImageSize, "Maximum size of Data Drive image"},
+ {_K("volume"),1, -1,EKeywordDataImageVolume, "Volume Label of Data Drive image"},
+ {_K("sectorsize"),1, 1,EKeywordDataImageSectorSize, "Sector size(in bytes) of Data Drive image"},
+ {_K("fattable"),1, 1,EKeywordDataImageNoOfFats, "Number of FATs in the Data Drive image"},
+ // things we don't normally report in the help information
+ {_K("trace"), 1, 1, EKeywordTrace, "(ROMBUILD activity trace flags)"},
+ {_K("filecompress"),2, -2,EKeywordFileCompress,"Non-XIP Executable to be loaded into the ROM compressed" },
+ {_K("fileuncompress"),2, -2,EKeywordFileUncompress,"Non-XIP Executable to be loaded into the ROM uncompressed" },
+ {_K("patchdata"),2, 5,EKeywordPatchDllData, "Patch exported data"},
+ {_K("imagename"), 1, 1, EKeywordSmrImageName, "output file for SMR image"},
+ {_K("hcrdata"), 1, 1, EKeywordSmrFileData, "file data for HCR SMR image"},
+ {_K("formatversion"), 1, 1, EKeywordSmrFormatVersion, "format version for HCR SMR image"},
+ {_K("payloadflags"), 1, 1, EKeywordSmrFlags, "payload flags for the HCR SMR image"},
+ {_K("payloaduid"), 1, 1, EKeywordSmrUID, "payload UID for the HCR SMR image"},
+ {0,0,0,0,EKeywordNone,""}
+};
+
+void ObeyFileReader::KeywordHelp() { // static
+
+ cout << "Obey file keywords:\n";
+
+ const ObeyFileKeyword* k=0;
+ for (k=iKeywords; k->iKeyword!=0; k++)
+ {
+ if (k->iHelpText == 0)
+ continue;
+ if (k->iHelpText[0]=='(' && !H.iVerbose)
+ continue; // don't normally report things in (parentheses)
+
+ char buf[32];
+ sprintf(buf, "%-20s", k->iKeyword);
+ if (k->iKeywordLength)
+ memcpy(buf+k->iKeywordLength,"[HWVD]",6);
+ if (H.iVerbose)
+ sprintf(buf+20,"%2d",k->iNumArgs);
+ cout << " " << buf << " " << k->iHelpText << endl;
+ }
+ cout << endl;
+
+ cout << "File attributes:\n";
+
+ const FileAttributeKeyword* f=0;
+ for (f=iAttributeKeywords; f->iKeyword!=0; f++)
+ {
+ if (f->iHelpText == 0)
+ continue;
+ if (f->iHelpText[0]=='(' && !H.iVerbose)
+ continue; // don't normally report things in (parentheses)
+
+ char buf[32];
+ sprintf(buf, "%-20s", f->iKeyword);
+ if (H.iVerbose)
+ sprintf(buf+20,"%2d",k->iNumArgs);
+ cout << " " << buf << " " << f->iHelpText << endl;
+ }
+ cout << endl;
+}
+
+ObeyFileReader::ObeyFileReader(const char* aFileName):iCurrentLine(0),
+iFileName(aFileName),iNumWords(0),iLine(0),iMarkLine(0),iCurrentObeyStatement(0) {
+ for(TUint i = 0 ; i < KNumWords ; i++)
+ iWord[i] = NullString;
+ *iSuffix = 0 ;
+}
+
+ObeyFileReader::~ObeyFileReader() {
+ if(iCurrentObeyStatement) {
+ delete []iCurrentObeyStatement;
+ iCurrentObeyStatement = 0 ;
+ }
+ if(iLine) {
+ delete []iLine;
+ iLine = 0 ;
+ }
+}
+
+//
+// Open the file & return a status
+//
+TBool ObeyFileReader::Open() {
+ ifstream ifs(iFileName.c_str(),ios_base::in + ios_base::binary);
+ if (!ifs.is_open()) {
+ Print(EError,"Cannot open obey file %s\n",iFileName.c_str());
+ return EFalse;
+ }
+ iLines.clear();
+ if(iLine){
+ delete []iLine;
+ iLine = 0 ;
+ }
+ ifs.seekg(0,ios_base::end);
+ size_t length = ifs.tellg();
+ char* buffer = new char[length + 2];
+ if (0 == buffer) {
+ Print(EError,"Insufficent Memory to Continue.");
+ ifs.close();
+ return EFalse;
+ }
+ ifs.seekg(0,ios_base::beg);
+ ifs.read(buffer,length);
+ size_t readcout = ifs.gcount() ;
+ if(readcout != length){
+ Print(EError,"Cannot Read All of File.");
+ delete []buffer ;
+ ifs.close();
+ return EFalse;
+ }
+ buffer[length] = '\n';
+ buffer[length + 1] = 0 ;
+ ifs.close();
+ char* lineStart = buffer ;
+ char* end = buffer + length ;
+ string line ;
+ size_t maxLengthOfLine = 0 ;
+ while(lineStart < end){
+ while(*lineStart == ' ' || *lineStart == '\t') //trimleft
+ lineStart ++ ;
+ char* lineEnd = lineStart ;
+ while(*lineEnd != '\r' && *lineEnd != '\n')
+ lineEnd ++ ;
+ if(strnicmp(lineStart,"REM",3) == 0){
+ line = "" ; // REMOVE "REM ... "
+ }
+ else {
+ TInt lastIndex = lineEnd - lineStart - 1;
+ while(lastIndex >= 0 && // trimright
+ (lineStart[lastIndex] == ' ' || lineStart[lastIndex] == '\t'))
+ lastIndex -- ;
+ if(lastIndex >= 0)
+ line.assign(lineStart,lastIndex + 1);
+ else
+ line = "";
+ }
+ if(line.length() > maxLengthOfLine)
+ maxLengthOfLine = line.length();
+ iLines.push_back(line);
+ if(*lineEnd == '\r') {
+ if(lineEnd[1] == '\n')
+ lineStart = lineEnd + 2 ;
+ else
+ lineStart = lineEnd + 1 ;
+ }
+ else // '\n'
+ lineStart = lineEnd + 1 ;
+ }
+ delete []buffer ;
+ iLine = new char[maxLengthOfLine + 1];
+ iCurrentObeyStatement = new char[maxLengthOfLine + 1];
+ *iCurrentObeyStatement = 0 ;
+ *iLine = 0 ;
+ iCurrentLine = 0 ;
+ iMarkLine = 0 ;
+ return ETrue;
+}
+
+void ObeyFileReader::Mark() {
+ iMarkLine = iCurrentLine - 1;
+}
+
+void ObeyFileReader::MarkNext() {
+ iMarkLine = iCurrentLine;
+}
+
+void ObeyFileReader::Rewind() {
+ iCurrentLine = iMarkLine;
+}
+
+char* ObeyFileReader::DupWord(TInt aIndex) const {
+ char* retVal = 0 ;
+ if(aIndex >= 0 && aIndex < (TInt)KNumWords){
+ size_t len = strlen(iWord[aIndex]) + 1;
+ retVal = new char[len];
+ if(retVal)
+ memcpy(retVal,iWord[aIndex],len);
+ }
+ return retVal ;
+}
+
+TInt ObeyFileReader::ReadAndParseLine() {
+ if (iCurrentLine >= (TInt)iLines.size())
+ return KErrEof;
+ iCurrentLine++;
+ iNumWords = Parse();
+ return KErrNone;
+}
+
+TInt ObeyFileReader::NextLine(TInt aPass, enum EKeyword& aKeyword) {
+
+NextLine:
+ TInt err = ReadAndParseLine();
+ if (err == KErrEof)
+ return KErrEof;
+ if(iNumWords == 0)
+ goto NextLine;
+ if (stricmp(iWord[0], "stop")==0)
+ return KErrEof;
+
+ const ObeyFileKeyword* k=0;
+ for (k=iKeywords; k->iKeyword!=0; k++) {
+ if (k->iKeywordLength == 0) {
+ // Exact case-insensitive match on keyword
+ if (stricmp(iWord[0], k->iKeyword) != 0)
+ continue;
+ *iSuffix = 0;
+ }
+ else {
+ // Prefix match
+ if (strnicmp(iWord[0], k->iKeyword, k->iKeywordLength) != 0)
+ continue;
+ // Suffix must be empty, or a variant number in []
+ strncpy(iSuffix,iWord[0] + k->iKeywordLength,80);
+ if (*iSuffix != '\0' && *iSuffix != '[')
+ continue;
+ }
+ // found a match
+ if ((k->iPass & aPass) == 0)
+ goto NextLine;
+ if (k->iNumArgs>=0 && (1+k->iNumArgs != iNumWords)) {
+ Print(EError, "Incorrect number of arguments for keyword %s on line %d.\n",
+ iWord[0], iCurrentLine);
+ goto NextLine;
+ }
+ if (k->iNumArgs<0 && (1-k->iNumArgs > iNumWords)) {
+ Print(EError, "Too few arguments for keyword %s on line %d.\n",
+ iWord[0], iCurrentLine);
+ goto NextLine;
+ }
+
+ aKeyword = k->iKeywordEnum;
+ return KErrNone;
+ }
+ if (aPass == 1)
+ Print(EWarning, "Unknown keyword '%s'. Line %d ignored\n", iWord[0], iCurrentLine);
+ goto NextLine;
+}
+
+//
+// splits a line into words, and returns the number of words found
+//
+TInt ObeyFileReader::Parse() {
+
+ for (TUint i = 0; i < KNumWords; i++)
+ iWord[i] = NullString;
+
+ enum TState {EInWord, EInQuotedWord, EInGap};
+ TState state = EInGap;
+ const string& line = iLines[iCurrentLine - 1];
+ size_t len = line.length();
+ memcpy(iLine,line.c_str(),len);
+ memcpy(iCurrentObeyStatement,iLine,len);
+ iLine[len] = 0 ;
+ iCurrentObeyStatement[len] = 0 ;
+ TUint i = 0;
+ char* linestr = iLine;
+ while (i < KNumWords && *linestr != 0) {
+ switch (state)
+ {
+ case EInGap:
+ if (*linestr =='\"') {
+ if (linestr[1] != 0 && linestr[1]!='\"')
+ iWord[i++] = linestr + 1;
+ state = EInQuotedWord;
+ }
+ else if (!IsGap(*linestr)) {
+ iWord[i++] = linestr;
+ state=EInWord;
+ }
+ else
+ *linestr=0;
+ break;
+ case EInWord:
+ if (*linestr == '\"') {
+ *linestr = 0;
+ if (linestr[1] != 0 && linestr[1] != '\"')
+ iWord[i++] = linestr+1;
+ state=EInQuotedWord;
+ }
+ else if (IsGap(*linestr)) {
+ *linestr=0;
+ state=EInGap;
+ }
+ break;
+ case EInQuotedWord:
+ if (*linestr == '\"'){
+ *linestr = 0;
+ state = EInGap;
+ }
+ break;
+ }
+ linestr++;
+ }
+ return i;
+}
+
+//
+// Process the timestamp
+//
+void ObeyFileReader::ProcessTime(TInt64& aTime) {
+ char timebuf[256];
+ if (iNumWords>2)
+ sprintf(timebuf, "%s_%s", iWord[1], iWord[2]);
+ else
+ strncpy(timebuf, iWord[1],256);
+
+ TInt r = StringToTime(aTime, timebuf);
+ if (r==KErrGeneral) {
+ Print(EError, "incorrect format for time keyword on line %d\n", iCurrentLine);
+ exit(0x670);
+ }
+ if (r==KErrArgument){
+ Print(EError, "Time out of range on line %d\n", iCurrentLine);
+ exit(0x670);
+ }
+}
+
+TInt64 ObeyFileReader::iTimeNow = 0;
+void ObeyFileReader::TimeNow(TInt64& aTime) {
+ if (iTimeNow==0) {
+ TInt sysTime = time(0); // seconds since midnight Jan 1st, 1970
+ sysTime -= (30*365*24*60*60+7*24*60*60); // seconds since midnight Jan 1st, 2000
+ TInt64 daysTo2000AD=730497;
+ TInt64 t=daysTo2000AD*24*3600+sysTime; // seconds since 0000
+ t = t+3600; // BST (?)
+ iTimeNow=t*1000000; // milliseconds
+ }
+ aTime=iTimeNow;
+}
+
+
+
+// File attributes.
+
+
+const FileAttributeKeyword ObeyFileReader::iAttributeKeywords[] =
+{
+ {"attrib",3 ,0,1,EAttributeAtt, "File attributes in ROM file system"},
+ {"exattrib",3 ,0,1,EAttributeAttExtra, "File extra attributes in ROM file system"},
+ {"stack",3 ,1,1,EAttributeStack, "?"},
+ {"fixed",3 ,1,0,EAttributeFixed, "Relocate to a fixed address space"},
+ {"priority",3 ,1,1,EAttributePriority, "Override process priority"},
+ {_K("uid1") ,1,1,EAttributeUid1, "Override first UID"},
+ {_K("uid2") ,1,1,EAttributeUid2, "Override second UID"},
+ {_K("uid3") ,1,1,EAttributeUid3, "Override third UID"},
+ {_K("heapmin") ,1,1,EAttributeHeapMin, "Override initial heap size"},
+ {_K("heapmax") ,1,1,EAttributeHeapMax, "Override maximum heap size"},
+ {_K("capability") ,1,1,EAttributeCapability, "Override capabilities"},
+ {_K("unpaged") ,1,0,EAttributeUnpaged, "Don't page code or data for this file"},
+ {_K("paged") ,1,0,EAttributePaged, "Page code and data for this file"},
+ {_K("unpagedcode") ,1,0,EAttributeUnpagedCode, "Don't page code for this file"},
+ {_K("pagedcode") ,1,0,EAttributePagedCode, "Page code for this file"},
+ {_K("unpageddata") ,1,0,EAttributeUnpagedData, "Don't page data for this file"},
+ {_K("pageddata") ,1,0,EAttributePagedData, "Page data for this file"},
+ {0,0,0,0,EAttributeAtt,0}
+};
+
+TInt ObeyFileReader::NextAttribute(TInt& aIndex, TInt aHasFile, enum EFileAttribute& aKeyword, char*& aArg)
+{
+NextAttribute:
+ if (aIndex >= iNumWords)
+ return KErrEof;
+ char* word=iWord[aIndex++];
+ const FileAttributeKeyword* k;
+ for (k=iAttributeKeywords; k->iKeyword!=0; k++)
+ {
+ if (k->iKeywordLength == 0)
+ {
+ // Exact match on keyword
+ if (stricmp(word, k->iKeyword) != 0)
+ continue;
+ }
+ else
+ {
+ // Prefix match
+ if (strnicmp(word, k->iKeyword, k->iKeywordLength) != 0)
+ continue;
+ }
+ // found a match
+ if (k->iNumArgs>0)
+ {
+ TInt argIndex = aIndex;
+ aIndex += k->iNumArgs; // interface only really supports 1 argument
+ if (aIndex>iNumWords)
+ {
+ Print(EError, "Missing argument for attribute %s on line %d\n", word, iCurrentLine);
+ return KErrArgument;
+ }
+ aArg=iWord[argIndex];
+ }
+ if (k->iIsFileAttribute && !aHasFile)
+ {
+ Print(EError, "File attribute %s applied to non-file on line %d\n", word, iCurrentLine);
+ return KErrNotSupported;
+ }
+ aKeyword=k->iAttributeEnum;
+ return KErrNone;
+ }
+ Print(EWarning, "Unknown attribute '%s' skipped on line %d\n", word, iCurrentLine);
+ goto NextAttribute;
+}
+
+
+
+/**
+Constructor:
+1.Obey file instance.
+2.used by both rofs and datadrive image.
+
+@param aReader - obey file reader object.
+*/
+CObeyFile::CObeyFile(ObeyFileReader& aReader):
+iRomFileName(NULL),
+iExtensionRofsName(0),
+iKernelRofsName(0),
+iRomSize(0),
+iVersion(0,0,0),
+iCheckSum(0),
+iNumberOfFiles(0),
+iTime(0),
+iRootDirectory(0),
+iNumberOfDataFiles(0),
+iDriveFileName(0),
+iDriveFileFormat(0),
+iReader(aReader),
+iMissingFiles(0),
+iLastExecutable(0),
+iFirstFile(0),
+iCurrentFile(0),
+iAutoSize(EFalse),
+iAutoPageSize(4096),
+iPagingOverrideParsed(0),
+iCodePagingOverrideParsed(0),
+iDataPagingOverrideParsed(0),
+iPatchData(new CPatchDataProcessor)
+{
+ iNextFilePtrPtr = &iFirstFile ;
+}
+
+/**
+Obey file Destructor.
+1.Release the tree memory.
+2.Release all allocated memory if any.
+*/
+CObeyFile::~CObeyFile() {
+ if(iDriveFileName){
+ delete[] iDriveFileName;
+ iDriveFileName = 0 ;
+ }
+ if(iDriveFileFormat) {
+ delete[] iDriveFileFormat;
+ iDriveFileFormat = 0 ;
+ }
+ iRootDirectory->deleteTheFirstNode();
+ iRootDirectory->InitializeCount();
+
+ Release();
+ if(iRomFileName){
+ delete [] iRomFileName;
+ iRomFileName = 0 ;
+ }
+ if (iRootDirectory)
+ iRootDirectory->Destroy();
+ if(iPatchData)
+ delete iPatchData;
+}
+
+//
+// Free resources not needed after building a ROM
+//
+void CObeyFile::Release() {
+ iFirstFile = 0;
+ iNextFilePtrPtr = &iFirstFile;
+}
+
+TRomBuilderEntry *CObeyFile::FirstFile() {
+ iCurrentFile = iFirstFile;
+ return iCurrentFile;
+}
+
+TRomBuilderEntry *CObeyFile::NextFile() {
+ iCurrentFile = iCurrentFile ? iCurrentFile->iNext : 0;
+ return iCurrentFile;
+}
+
+char* CObeyFile::ProcessCoreImage() const {
+ // check for coreimage keyword and return filename
+ enum EKeyword keyword;
+ char* coreImageFileName = 0;
+ iReader.Rewind();
+ while (iReader.NextLine(1,keyword) != KErrEof) {
+ if (keyword == EKeywordCoreImage) {
+ coreImageFileName = iReader.DupWord(1);
+ iReader.MarkNext();
+ break;
+ }
+ }
+ return coreImageFileName;
+}
+
+void CObeyFile::SkipToExtension() {
+ iReader.Rewind();
+ enum EKeyword keyword;
+ while (iReader.NextLine(1,keyword) != KErrEof) {
+ if (keyword == EKeywordExtensionRofs) {
+ iReader.Mark(); // ready for processing extension
+ break;
+ }
+ }
+}
+
+TInt CObeyFile::ProcessRofs() {
+
+ //
+ // First pass through the obey file to set up key variables
+ //
+
+ iReader.Rewind();
+
+ TInt count=0;
+ enum EKeyword keyword;
+ while (iReader.NextLine(1,keyword) != KErrEof) {
+ if (keyword == EKeywordExtensionRofs){
+ if (count==0)
+ return KErrNotFound; // no core ROFS, just extension ROFSs.
+ break;
+ }
+
+ count++;
+ if (! ProcessKeyword(keyword))
+ return KErrGeneral;
+ }
+
+ if (!GotKeyVariables())
+ return KErrGeneral;
+
+ //
+ // second pass to process the file specifications in the obey file building
+ // up the TRomNode directory structure and the TRomBuilderEntry list
+ //
+ iReader.Rewind();
+
+ iRootDirectory = new TRomNode("");
+ iLastExecutable = iRootDirectory;
+
+ TInt align=0;
+ while (iReader.NextLine(2,keyword)!=KErrEof) {
+ if (keyword == EKeywordExtensionRofs)
+ break;
+
+ if (keyword == EKeywordHide)
+ keyword = EKeywordHideV2;
+
+ switch (keyword)
+ {
+ case EKeywordHide:
+ case EKeywordAlias:
+ case EKeywordRename:
+ if (!ProcessRenaming(keyword))
+ return KErrGeneral;
+ break;
+ case EKeywordPatchDllData:
+ {
+ // Collect patchdata statements to process at the end
+ StringVector patchDataTokens;
+ SplitPatchDataStatement(patchDataTokens);
+ iPatchData->AddPatchDataStatement(patchDataTokens);
+ break;
+ }
+ default:
+ if (!ProcessFile(align, keyword))
+ return KErrGeneral;
+ align=0;
+ break;
+ }
+ }
+
+ if(!ParsePatchDllData())
+ return KErrGeneral;
+ iReader.Mark(); // ready for processing the extension rom(s)
+
+ if (iMissingFiles!=0) {
+ return KErrGeneral;
+ }
+ if ( 0 == iNumberOfFiles ){
+ Print(EError, "No files specified.\n");
+ return KErrGeneral;
+ }
+
+ return KErrNone;
+}
+
+TBool CObeyFile::Process() {
+ TBool result = ETrue;
+ iReader.Rewind();
+ enum EKeyword keyword;
+ while(iReader.NextLine(1, keyword) != KErrEof){
+ string key = iReader.Word(0);
+ string value = iReader.Word(1);
+ if(iKeyValues.find(key) != iKeyValues.end()){
+ iKeyValues[key].push_back(value);
+ }
+ else {
+ StringVector values;
+ values.push_back(value);
+ iKeyValues[key]=values;
+ }
+
+
+ }
+ return result;
+}
+StringVector CObeyFile::getValues(const string& aKey) {
+ StringVector values;
+ if(iKeyValues.find(aKey) != iKeyValues.end()){
+ values = iKeyValues[aKey];
+ }
+ return values;
+}
+
+/**
+Process drive obey file and construct the tree.
+
+@return - Return the status,
+'KErrnone' for Success,
+'KErrGeneral' for failure (required keywords not there in obey file or failed
+to construct the tree).
+*/
+TInt CObeyFile::ProcessDataDrive() {
+ iReader.Rewind();
+ enum EKeyword keyword;
+
+ // First pass through the obey file to set up key variables
+ while (iReader.NextLine(1,keyword) != KErrEof) {
+ if (!ProcessDriveKeyword(keyword))
+ return KErrGeneral;
+ }
+
+ if (!GotKeyDriveVariables())
+ return KErrGeneral;
+
+ // Second pass to process the file specifications in the obey file.
+ // Build the TRomNode directory structure and the TRomBuilderEntry list
+ iReader.Rewind();
+ iRootDirectory = new TRomNode("//");
+ iLastExecutable = iRootDirectory;
+
+ while(iReader.NextLine(2,keyword)!=KErrEof) {
+ switch (keyword)
+ {
+ case EKeywordPatchDllData:
+ { // Collect patchdata statements to process at the end
+ StringVector patchDataTokens;
+ SplitPatchDataStatement(patchDataTokens);
+ iPatchData->AddPatchDataStatement(patchDataTokens);
+ break;
+ }
+
+ case EKeywordHide:
+ case EKeywordFile:
+ case EKeywordDir:
+ case EKeywordData:
+ case EKeywordFileCompress:
+ case EKeywordFileUncompress:
+ if (!ProcessDriveFile(keyword))
+ return KErrGeneral;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if(!ParsePatchDllData())
+ return KErrGeneral;
+ if (iMissingFiles) {
+ Print(EError, "Source Files Missing.\n");
+ return KErrGeneral;
+ }
+ if (!iNumberOfFiles)
+ Print(EWarning,"No files specified.\n");
+
+ return KErrNone;
+}
+
+
+/**
+Process and stores the keyword information.
+
+@param aKeyword - keyword to update its value to variables.
+@return - Return the status i.e Success,
+*/
+TBool CObeyFile::ProcessDriveKeyword(enum EKeyword aKeyword) {
+
+ TBool success = ETrue;
+ switch (aKeyword)
+ {
+ case EKeywordDataImageName:
+ iDriveFileName = iReader.DupWord(1);
+ break;
+ case EKeywordDataImageFileSystem:
+ iDriveFileFormat = iReader.DupWord(1);
+ break;
+ case EKeywordDataImageSize:
+ {
+ const char* bigString = iReader.Word(1);
+ if(*bigString == '\0')
+ {
+ Print(EWarning,"Not a valid Image Size. Default size is considered\n");
+ break;
+ }
+
+ Val(iConfigurableFatAttributes.iImageSize,bigString);
+ }
+ break;
+ case EKeywordDataImageVolume:
+ {
+ // Get the volume label provided by using "volume" keyword.
+ // e.g. vlolume = NO NAME
+ string volumeLabel = iReader.GetCurrentObeyStatement();
+ string volumeLabelKeyword = "volume";
+
+ TUint position = volumeLabel.find(volumeLabelKeyword.c_str(),0,volumeLabelKeyword.size());
+ position += volumeLabelKeyword.size();
+ if (volumeLabel.find('=',position) != string::npos) {
+ position=volumeLabel.find('=',position);
+ ++position;
+ }
+
+ position = volumeLabel.find_first_not_of(' ',position);
+ if (position != string::npos) {
+ volumeLabel = volumeLabel.substr(position);
+
+ // Remove the new line character from the end
+ position = volumeLabel.find_first_of("\r\n");
+ if (position != string::npos)
+ volumeLabel = volumeLabel.substr(0,position);
+ size_t length = volumeLabel.length() ;
+ if(length > 11)
+ length = 11 ;
+ memcpy(iConfigurableFatAttributes.iDriveVolumeLabel,volumeLabel.c_str(),length) ;
+ while(length != 11)
+ iConfigurableFatAttributes.iDriveVolumeLabel[length++] = ' ';
+ iConfigurableFatAttributes.iDriveVolumeLabel[length] = 0;
+ }
+ else {
+ Print(EWarning,"Value for Volume Label is not provided. Default value is considered.\n");
+ }
+ break;
+ }
+ case EKeywordDataImageSectorSize:
+ {
+ const char* bigString = iReader.Word(1);
+ TInt sectorSize = atoi(bigString);
+ if(sectorSize <= 0) {
+ Print(EWarning,"Invalid Sector Size value. Default value is considered.\n");
+ }
+ else {
+ iConfigurableFatAttributes.iDriveSectorSize = atoi(bigString);
+ }
+ }
+ break;
+ case EKeywordDataImageNoOfFats:
+ {
+ const char* bigString = iReader.Word(1);
+ TInt noOfFats = atoi(bigString);
+ if (noOfFats <=0)
+ Print(EWarning,"Invalid No of FATs specified. Default value is considered.\n");
+ else
+ iConfigurableFatAttributes.iDriveNoOfFATs = atoi(bigString);
+ }
+ break;
+ default:
+ // unexpected keyword iReader.Word(0), keep going.
+ break;
+ }
+ return success;
+}
+
+
+/**
+Checks whether obeyfile has supplied enough variables to continue.
+
+@return - Return the status
+ETrue - Supplied valid values,
+EFalse- Not valied values.
+*/
+TBool CObeyFile::GotKeyDriveVariables() {
+
+ TBool retVal=ETrue;
+
+ // Mandatory keywords
+ if (iDriveFileName==0) {
+ Print(EError,"The name of the image file has not been supplied.\n");
+ Print(EError,"Use the keyword \"dataimagename\".\n");
+ retVal = EFalse;
+ }
+ // Check for '-'ve entered value.
+ if(iConfigurableFatAttributes.iImageSize <= 0){
+ Print(EWarning,"Image Size should be positive. Default size is Considered.\n");
+ }
+
+ // File system format.
+ if(iDriveFileFormat==0) {
+ Print(EError,"The name of the file system not been supplied.\n");
+ Print(EError,"Use the keyword \"dataimagefilesystem\".\n");
+ retVal = EFalse;
+ }
+
+ // Checking the validity of file system format.
+ if(iDriveFileFormat){
+ if(stricmp(iDriveFileFormat,"FAT16") && stricmp(iDriveFileFormat,"FAT32")) {
+ Print(EError,"The name of the file system not supported : %s\n",iDriveFileFormat);
+ retVal = EFalse;
+ }
+ }
+ if(retVal)
+ Print(ELog,"\nCreating Data Drive image : %s\n", iDriveFileName);
+
+ return retVal;
+}
+
+/**
+Process a parsed line to set up one or more new TRomBuilder entry objects.
+
+@param - obey file keyword.
+// iWord[0] = the keyword (file,)
+// iWord[1] = the PC pathname
+// iWord[2] = the EPOC pathname
+// iWord[3] = start of the file attributes
+
+@return - Return the status
+ETrue - Successful generation of tree.
+EFalse- Fail to generate the tree.
+*/
+TBool CObeyFile::ProcessDriveFile(enum EKeyword aKeyword) {
+
+ TBool isPeFile = ETrue;
+ TBool aFileCompressOption, aFileUncompressOption;
+
+ TInt epocPathStart=2;
+ aFileCompressOption = aFileUncompressOption = EFalse;
+ // do some validation of the keyword
+ TInt currentLine = iReader.CurrentLine();
+
+ switch (aKeyword)
+ {
+ case EKeywordData:
+ case EKeywordDir:
+ case EKeywordHide:
+ isPeFile = EFalse;
+ break;
+
+ case EKeywordFile:
+ break;
+
+ case EKeywordFileCompress:
+ aFileCompressOption = ETrue;
+ break;
+
+ case EKeywordFileUncompress:
+ aFileUncompressOption = ETrue;
+ break;
+
+ default:
+ return EFalse;
+ }
+
+ if (aKeyword!=EKeywordHide && aKeyword!=EKeywordDir) {
+ // check the PC file exists
+ char* nname = NormaliseFileName(iReader.Word(1));
+ ifstream test(nname);
+ if(!test.is_open()){
+ Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
+ iMissingFiles++;
+ }
+ test.close();
+ delete []nname ;
+
+ }
+ else
+ epocPathStart=1;
+
+ if(aKeyword != EKeywordDir)
+ iNumberOfFiles++;
+
+ TBool endOfName=EFalse;
+ const char *epocStartPtr;
+ if(aKeyword != EKeywordDir)
+ epocStartPtr = IsValidFilePath(iReader.Word(epocPathStart));
+ else
+ epocStartPtr = IsValidDirPath(iReader.Word(epocPathStart));
+ char *epocEndPtr = const_cast<char*>(epocStartPtr);
+
+ if (epocStartPtr == NULL) {
+ Print(EError, "Invalid destination path on line %d\n",currentLine);
+ return EFalse;
+ }
+
+ TRomNode* dir=iRootDirectory;
+ TRomNode* subDir=0;
+ TRomBuilderEntry *file=0;
+
+ while (!endOfName) {
+ endOfName = GetNextBitOfFileName(epocEndPtr);
+ if (endOfName && (aKeyword!=EKeywordDir)) { // file
+ TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
+ if ((aKeyword != EKeywordHide) && alreadyExists) { // duplicate file
+ if (gKeepGoing) {
+ Print(EWarning, "Duplicate file for %s on line %d, will be ignored\n",iReader.Word(1),iReader.CurrentLine());
+ iNumberOfFiles--;
+ return ETrue;
+ }
+ else {
+ Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
+ return EFalse;
+ }
+ }
+ else if((aKeyword == EKeywordHide) && (alreadyExists)) {
+ alreadyExists->iEntry->iHidden = ETrue;
+ alreadyExists->iHidden = ETrue;
+ return ETrue;
+ }
+ else if((aKeyword == EKeywordHide) && (!alreadyExists)) {
+ Print(EWarning, "Hiding non-existent file %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
+ return ETrue;
+ }
+
+ file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);
+ file->iExecutable=isPeFile;
+ if( aFileCompressOption ) {
+ file->iCompressEnabled = ECompressionCompress;
+ }
+ else if(aFileUncompressOption ) {
+ file->iCompressEnabled = ECompressionUncompress;
+ }
+
+ TRomNode* node=new TRomNode(epocStartPtr, file);
+ if (node==0)
+ return EFalse;
+
+ TInt r=ParseFileAttributes(node, file, aKeyword);
+ if (r!=KErrNone)
+ return EFalse;
+
+ if(gCompress != ECompressionUnknown) {
+ node->iFileUpdate = ETrue;
+ }
+
+ if((node->iOverride) || (aFileCompressOption) || (aFileUncompressOption)) {
+ node->iFileUpdate = ETrue;
+ }
+
+ dir->AddFile(node); // to drive directory structure.
+ }
+ else {
+ // directory
+ //for directory creation, given /sys/bin/, it's possible to reach 0 at the end, just ignore that...
+ if(!*epocStartPtr)
+ break;
+
+ subDir = dir->FindInDirectory(epocStartPtr);
+ if (!subDir){ // sub directory does not exist
+ if(aKeyword==EKeywordHide) {
+ Print(EWarning, "Hiding non-existent file %s on line %d\n",
+ iReader.Word(1),iReader.CurrentLine());
+ return ETrue;
+ }
+ subDir = dir->NewSubDir(epocStartPtr);
+ if (!subDir)
+ return EFalse;
+ }
+ dir=subDir;
+ epocStartPtr = epocEndPtr;
+ } // end of else.
+ }
+ return ETrue;
+}
+
+
+TInt CObeyFile::SetStackSize(TRomNode *aNode, const char* aStr) {
+ if (EFalse == IsValidNumber(aStr))
+ return Print(EError, "Number required as argument for keyword 'stack'.\n");
+ TInt size ;
+ TInt err = Val(size,aStr);
+ if(KErrNone == err){
+ aNode->SetStackSize(size );
+ }
+ return err;
+}
+
+TInt CObeyFile::SetHeapSizeMin(TRomNode *aNode, const char* aStr) {
+ if (EFalse == IsValidNumber(aStr))
+ return Print(EError, "Number required as argument for keyword 'heapmin'.\n");
+ TInt size ;
+ TInt err = Val(size,aStr);
+ if(KErrNone == err){
+ aNode->SetHeapSizeMin(size );
+ }
+ return err;
+}
+
+TInt CObeyFile::SetHeapSizeMax(TRomNode *aNode, const char* aStr) {
+ if (EFalse == IsValidNumber(aStr))
+ return Print(EError, "Number required as argument for keyword 'heapmax'.\n");
+ TInt size ;
+ TInt err = Val(size,aStr);
+ if(KErrNone == err){
+ aNode->SetHeapSizeMax(size );
+ }
+ return err;
+
+}
+
+TInt CObeyFile::SetCapability(TRomNode *aNode, const char* aStr) {
+ if ( IsValidNumber(aStr)){
+ Print(EDiagnostic,"Old style numeric CAPABILTY specification ignored.\n");
+ return KErrNone;
+ }
+ SCapabilitySet cap;
+ TInt r = ParseCapabilitiesArg(cap, (char*)aStr);
+ if( KErrNone == r ) {
+ aNode->SetCapability( cap );
+ }
+ return r;
+}
+
+TInt CObeyFile::SetPriority(TRomNode *aNode, const char* aStr) {
+ TProcessPriority priority;
+
+ if ( IsValidNumber(aStr)) {
+ TUint32 temp = 0;
+ Val(temp,aStr) ;
+ priority = (TProcessPriority)temp ;
+ }
+ else {
+ if (stricmp(aStr, "low")==0)
+ priority=EPriorityLow;
+ else if (strnicmp(aStr, "background", 4)==0)
+ priority=EPriorityBackground;
+ else if (strnicmp(aStr, "foreground", 4)==0)
+ priority=EPriorityForeground;
+ else if (stricmp(aStr, "high")==0)
+ priority=EPriorityHigh;
+ else if (strnicmp(aStr, "windowserver",3)==0)
+ priority=EPriorityWindowServer;
+ else if (strnicmp(aStr, "fileserver",4)==0)
+ priority=EPriorityFileServer;
+ else if (strnicmp(aStr, "realtimeserver",4)==0)
+ priority=EPriorityRealTimeServer;
+ else if (strnicmp(aStr, "supervisor",3)==0)
+ priority=EPrioritySupervisor;
+ else
+ return Print(EError, "Unrecognised priority keyword.\n");
+ }
+ if (priority<EPriorityLow || priority>EPrioritySupervisor)
+ return Print(EError, "Priority out of range.\n");
+
+ aNode->SetPriority( priority );
+ return KErrNone;
+}
+
+TInt CObeyFile::SetUid1(TRomNode *aNode, const char* aStr){
+ if (EFalse == IsValidNumber(aStr))
+ return Print(EError, "Number required as argument for keyword 'uid1'.\n");
+ TInt size ;
+ TInt err = Val(size,aStr);
+ if(KErrNone == err){
+ aNode->SetUid1(size );
+ }
+ return err;
+}
+TInt CObeyFile::SetUid2(TRomNode *aNode, const char* aStr) {
+ if (EFalse == IsValidNumber(aStr))
+ return Print(EError, "Number required as argument for keyword 'uid2'.\n");
+ TInt size ;
+ TInt err = Val(size,aStr);
+ if(KErrNone == err){
+ aNode->SetUid2(size );
+ }
+ return err;
+}
+TInt CObeyFile::SetUid3(TRomNode *aNode, const char* aStr) {
+ if (EFalse == IsValidNumber(aStr))
+ return Print(EError, "Number required as argument for keyword 'uid3'.\n");
+ TInt size ;
+ TInt err = Val(size,aStr);
+ if(KErrNone == err){
+ aNode->SetUid3(size );
+ }
+ return err;
+}
+
+//
+// Process any inline keywords
+//
+TInt CObeyFile::ParseFileAttributes(TRomNode *aNode, TRomBuilderEntry* aFile, enum EKeyword aKeyword) {
+ TInt currentLine = iReader.CurrentLine();
+ enum EFileAttribute attribute;
+ TInt r=KErrNone;
+ TInt index=3;
+ char* arg=0;
+
+ while(r==KErrNone) {
+ r=iReader.NextAttribute(index,(aFile!=0),attribute,arg);
+ if (r!=KErrNone)
+ break;
+ switch(attribute)
+ {
+ case EAttributeAtt:
+ r=aNode->SetAtt(arg);
+ break;
+ case EAttributeAttExtra:
+ r=aNode->SetAttExtra(arg, aFile, aKeyword);
+ break;
+ case EAttributeStack:
+ r=SetStackSize(aNode, arg);
+ break;
+ case EAttributeFixed:
+ aNode->SetFixed();
+ r = KErrNone;
+ break;
+ case EAttributeUid1:
+ r=SetUid1(aNode, arg);
+ break;
+ case EAttributeUid2:
+ r=SetUid2(aNode, arg);
+ break;
+ case EAttributeUid3:
+ r=SetUid3(aNode, arg);
+ break;
+ case EAttributeHeapMin:
+ r=SetHeapSizeMin(aNode, arg);
+ break;
+ case EAttributeHeapMax:
+ r=SetHeapSizeMax(aNode, arg);
+ break;
+ case EAttributePriority:
+ r=SetPriority(aNode, arg);
+ break;
+ case EAttributeCapability:
+ r=SetCapability(aNode, arg);
+ break;
+ case EAttributeUnpaged:
+ aNode->iOverride |= KOverrideCodeUnpaged|KOverrideDataUnpaged;
+ aNode->iOverride &= ~(KOverrideCodePaged|KOverrideDataPaged);
+ break;
+ case EAttributePaged:
+ aNode->iOverride |= KOverrideCodePaged;
+ aNode->iOverride &= ~(KOverrideCodeUnpaged);
+ break;
+ case EAttributeUnpagedCode:
+ aNode->iOverride |= KOverrideCodeUnpaged;
+ aNode->iOverride &= ~KOverrideCodePaged;
+ break;
+ case EAttributePagedCode:
+ aNode->iOverride |= KOverrideCodePaged;
+ aNode->iOverride &= ~KOverrideCodeUnpaged;
+ break;
+ case EAttributeUnpagedData:
+ aNode->iOverride |= KOverrideDataUnpaged;
+ aNode->iOverride &= ~KOverrideDataPaged;
+ break;
+ case EAttributePagedData:
+ aNode->iOverride |= KOverrideDataPaged;
+ aNode->iOverride &= ~KOverrideDataUnpaged;
+ break;
+ default:
+ return Print(EError, "Unrecognised keyword in file attributes on line %d.\n",currentLine);
+ }
+ }
+
+ if (r==KErrEof)
+ return KErrNone;
+ return r;
+}
+
+//
+// Process a parsed line to set up one or more new TRomBuilder entry objects.
+// iWord[0] = the keyword (file, primary or secondary)
+// iWord[1] = the PC pathname
+// iWord[2] = the EPOC pathname
+// iWord[3] = start of the file attributes
+//
+TBool CObeyFile::ProcessFile(TInt /*aAlign*/, enum EKeyword aKeyword){
+
+ TBool isPeFile = ETrue;
+ TBool aFileCompressOption, aFileUncompressOption;
+ TInt epocPathStart=2;
+ aFileCompressOption = aFileUncompressOption = EFalse;
+ TBool warnFlag = EFalse;
+ static const char aStdPath[] = "SYS\\BIN\\";
+ static const int sysBinLength = sizeof(aStdPath)-1;
+
+ // do some validation of the keyword
+ TInt currentLine = iReader.CurrentLine();
+ switch (aKeyword)
+ {
+ case EKeywordData:
+ case EKeywordHideV2:
+ iNumberOfDataFiles++;
+ isPeFile = EFalse;
+ break;
+
+ case EKeywordFile:
+ warnFlag = gEnableStdPathWarning;
+ break;
+ case EKeywordFileCompress:
+ aFileCompressOption = ETrue;
+ warnFlag = gEnableStdPathWarning;
+ break;
+ case EKeywordFileUncompress:
+ aFileUncompressOption = ETrue;
+ warnFlag = gEnableStdPathWarning;
+ break;
+
+ default:
+ Print(EError,"Unexpected keyword '%s' on line %d.\n",iReader.Word(0),currentLine);
+ return EFalse;
+ }
+
+ if (aKeyword!=EKeywordHideV2) {
+
+ // check the PC file exists
+ char* nname = NormaliseFileName(iReader.Word(1));
+ ifstream test(nname);
+ if (!test) {
+ Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
+ iMissingFiles++;
+ }
+ test.close();
+ delete []nname;
+ }
+ else
+ epocPathStart=1;
+
+ iNumberOfFiles++;
+
+
+ TBool endOfName=EFalse;
+ const char *epocStartPtr=IsValidFilePath(iReader.Word(epocPathStart));
+ char *epocEndPtr=const_cast<char*>(epocStartPtr);
+ if (epocStartPtr==NULL) {
+ Print(EError, "Invalid destination path on line %d\n",currentLine);
+ return EFalse;
+ }
+ if(warnFlag){ // Check for the std destination path(for executables) as per platsec.
+ if(strnicmp(aStdPath,epocStartPtr,sysBinLength) != 0) {
+ Print(EWarning,"Invalid destination path on line %d. \"%s\" \n",currentLine,epocStartPtr);
+ }
+ }
+
+ TRomNode* dir=iRootDirectory;
+ TRomNode* subDir=0;
+ TRomBuilderEntry *file=0;
+ while (!endOfName) {
+ endOfName = GetNextBitOfFileName(epocEndPtr);
+ if (endOfName) {// file
+ TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
+ /*
+ * The EKeywordHideV2 keyword is used to indicate that:
+ * 1. if the file exists in the same image and then hidden, mark it hidden
+ * 2. if the file exists in another image, but in this (ROFS) image, it is
+ * required to hide that file, create a 0 length file entry setting the 'hide'
+ * flag so that at runtime, file gets hidden in the composite filesystem.
+ */
+ if ((aKeyword != EKeywordHideV2) && alreadyExists){ // duplicate file
+ if(gKeepGoing){
+ Print(EWarning, "Duplicate file for %s on line %d, will be ignored\n",iReader.Word(1),iReader.CurrentLine());
+ switch (aKeyword)
+ {
+ case EKeywordData:
+ case EKeywordHideV2:
+ iNumberOfDataFiles--;
+ default:
+ break;
+ }
+ iNumberOfFiles--;
+ return ETrue;
+ }
+ else {
+ Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
+ return EFalse;
+ }
+ }
+
+ TBool aHidden = aKeyword==EKeywordHideV2;
+ /* The file is only marked hidden and hence the source file name isn't known
+ * here as hide statement says :
+ * hide <filename as in ROM>
+ * Therefore, create TRomBuilderEntry with iFileName as 0 for hidden file when
+ * the file doesn't exist in the same ROM image. Otherwise, the src file name
+ * is known because of alreadyExists (which comes from the 'file'/'data' statement).
+ */
+ if(aHidden)
+ file = new TRomBuilderEntry(0, epocStartPtr);
+ else
+ file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);
+ file->iExecutable=isPeFile;
+ file->iHidden= aHidden;
+ if( aFileCompressOption ){
+ file->iCompressEnabled = ECompressionCompress;
+ }
+ else if(aFileUncompressOption ) {
+ file->iCompressEnabled = ECompressionUncompress;
+ }
+ TRomNode* node=new TRomNode(epocStartPtr, file);
+ if (node==0)
+ return EFalse;
+ TInt r=ParseFileAttributes(node, file, aKeyword);
+ if (r!=KErrNone)
+ return EFalse;
+
+ dir->AddFile(node); // to ROFS directory structure
+ AddFile(file); // to our list of files
+ }
+ else { // directory
+ subDir = dir->FindInDirectory(epocStartPtr);
+ if (!subDir) { // sub directory does not exist
+ subDir = dir->NewSubDir(epocStartPtr);
+ if (!subDir)
+ return EFalse;
+ }
+ dir=subDir;
+ epocStartPtr = epocEndPtr;
+ }
+ }
+ return ETrue;
+}
+
+
+TBool CObeyFile::ProcessRenaming(enum EKeyword aKeyword) {
+
+ // find existing file
+ TBool endOfName=EFalse;
+ const char *epocStartPtr=IsValidFilePath(iReader.Word(1));
+
+ // Store the current name and new name to maintain renamed file map
+ string currentName=iReader.Word(1);
+ string newName=iReader.Word(2);
+
+ char *epocEndPtr= const_cast<char*>(epocStartPtr);
+ if (epocStartPtr == NULL) {
+ Print(EError, "Invalid source path on line %d\n",iReader.CurrentLine());
+ return EFalse;
+ }
+
+ char saved_srcname[257];
+ strncpy(saved_srcname, iReader.Word(1),257);
+
+ TRomNode* dir=iRootDirectory;
+ TRomNode* existingFile=0;
+ while (!endOfName){
+ endOfName = GetNextBitOfFileName(epocEndPtr);
+ if (endOfName) { // file
+ existingFile=dir->FindInDirectory(epocStartPtr);
+ if (existingFile) {
+ TInt fileCount=0;
+ TInt dirCount=0;
+ existingFile->CountDirectory(fileCount, dirCount);
+ if (dirCount != 0 || fileCount != 0) {
+ Print(EError, "Keyword %s not applicable to directories - line %d\n",
+ iReader.Word(0),iReader.CurrentLine());
+ return EFalse;
+ }
+ }
+ }
+ else { // directory
+ TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
+ if (!subDir) // sub directory does not exist
+ break;
+ dir=subDir;
+ epocStartPtr = epocEndPtr;
+ }
+ }
+ if (aKeyword == EKeywordHide) {
+ /*
+ * The EKeywordHide keyword is used to indicate that if the file exists in
+ * the primary ROFS image and then hidden in extension ROFS, mark it hidden.
+ */
+ if (!existingFile) {
+ Print(EWarning, "Hiding non-existent file %s on line %d\n",
+ saved_srcname, iReader.CurrentLine());
+ // Just a warning, as we've achieved the right overall effect.
+ }
+ else if (existingFile->iFileStartOffset==(TUint)KFileHidden){
+ Print(EWarning, "Hiding already hidden file %s on line %d\n",
+ saved_srcname, iReader.CurrentLine());
+ // We will igrore this request, otherwise it will "undelete" it.
+ }
+ else {
+ //hidden files will not be placed to the image
+ existingFile->iHidden = ETrue;
+ }
+ return ETrue;
+ }
+
+ if (!existingFile) {
+ Print(EError, "Can't %s non-existent source file %s on line %d\n",
+ iReader.Word(0), saved_srcname, iReader.CurrentLine());
+ return EFalse;
+ }
+
+ epocStartPtr = IsValidFilePath(iReader.Word(2));
+ epocEndPtr = const_cast<char*>(epocStartPtr);
+ endOfName = EFalse;
+ if (epocStartPtr == NULL) {
+ Print(EError, "Invalid destination path on line %d\n",iReader.CurrentLine());
+ return EFalse;
+ }
+
+ TRomNode* newdir=iRootDirectory;
+ while (!endOfName) {
+ endOfName = GetNextBitOfFileName(epocEndPtr);
+ if (endOfName) {// file
+ TRomNode* alreadyExists=newdir->FindInDirectory(epocStartPtr);
+ if (alreadyExists && !(alreadyExists->iHidden)) {// duplicate file
+ if(gKeepGoing){
+ Print(EWarning, "Duplicate file for %s on line %d, renaming will be skipped\n",saved_srcname,iReader.CurrentLine());
+ return ETrue;
+ }
+ else {
+ Print(EError, "Duplicate file for %s on line %d\n",saved_srcname,iReader.CurrentLine());
+ return EFalse;
+ }
+ }
+ }
+ else { // directory
+ TRomNode* subDir = newdir->FindInDirectory(epocStartPtr);
+ if (!subDir) {// sub directory does not exist
+ subDir = newdir->NewSubDir(epocStartPtr);
+ if (!subDir)
+ return EFalse;
+ }
+ newdir=subDir;
+ epocStartPtr = epocEndPtr;
+ }
+ }
+
+ if (aKeyword == EKeywordRename) {
+ // rename => remove existingFile and insert into tree at new place
+ // has no effect on the iNextExecutable or iNextNodeForSameFile links
+ TInt r=ParseFileAttributes(existingFile, existingFile->iEntry, aKeyword);
+ if (r!=KErrNone)
+ return EFalse;
+ existingFile->Rename(dir, newdir, epocStartPtr);
+ // Store the current and new name of file in the renamed file map.
+ iPatchData->AddToRenamedFileMap(currentName, newName);
+ return ETrue;
+ }
+
+ // alias => create new TRomNode entry and insert into tree
+ TRomNode* node = new TRomNode(epocStartPtr, 0);
+ if (node == 0) {
+ Print(EError, "Out of memory\n");
+ return EFalse;
+ }
+ node->Alias(existingFile);
+ TInt r=ParseFileAttributes(node, 0, aKeyword);
+ if (r!=KErrNone)
+ return EFalse;
+ newdir->AddFile(node); // to ROFS directory structure, though possibly hidden
+ return ETrue;
+}
+
+TInt ParsePagingPolicy(const char* policy){
+ if(stricmp(policy,"NOPAGING") == 0)
+ return EKernelConfigPagingPolicyNoPaging;
+ else if (stricmp(policy,"ALWAYSPAGE") == 0)
+ return EKernelConfigPagingPolicyAlwaysPage;
+ else if(stricmp(policy,"DEFAULTUNPAGED") == 0)
+ return EKernelConfigPagingPolicyDefaultUnpaged;
+ else if(stricmp(policy,"DEFAULTPAGED") == 0)
+ return EKernelConfigPagingPolicyDefaultPaged;
+ return KErrArgument;
+}
+
+TBool CObeyFile::ProcessKeyword(enum EKeyword aKeyword) {
+
+ TBool success = ETrue;
+ switch (aKeyword)
+ {
+ case EKeywordRofsName:
+ iRomFileName = iReader.DupWord(1);
+ break;
+ case EKeywordRofsSize:
+ Val(iRomSize,iReader.Word(1));
+ break;
+ case EKeywordVersion:
+ {
+ istringstream val(iReader.Word(1));
+ val >> iVersion;
+ }
+ break;
+ case EKeywordRofsChecksum:
+ Val(iCheckSum,iReader.Word(1));
+ break;
+ case EKeywordTime:
+ iReader.ProcessTime(iTime);
+ break;
+ case EKeywordPagingOverride:
+ {
+ if(iPagingOverrideParsed)
+ Print(EWarning, "PagingOverride redefined - previous PagingOverride values lost\n");
+ if(iCodePagingOverrideParsed)
+ Print(EWarning, "PagingOverride defined - previous CodePagingOverride values lost\n");
+ iPagingOverrideParsed = true;
+ TInt policy = ParsePagingPolicy(iReader.Word(1));
+ if(policy < 0) {
+ Print(EError,"Unrecognized option for PAGINGOVERRIDE keyword\n");
+ success = false;
+ }
+ else {
+ gCodePagingOverride = policy;
+ if((policy == EKernelConfigPagingPolicyNoPaging) || (policy == EKernelConfigPagingPolicyDefaultUnpaged))
+ gDataPagingOverride = policy;
+ }
+ }
+ break;
+ case EKeywordCodePagingOverride:
+ {
+ if(iCodePagingOverrideParsed)
+ Print(EWarning, "CodePagingOverride redefined - previous CodePagingOverride values lost\n");
+ if(iPagingOverrideParsed)
+ Print(EWarning, "CodePagingOverride defined - previous PagingOverride values lost\n");
+ iCodePagingOverrideParsed = true;
+ TInt policy = ParsePagingPolicy(iReader.Word(1));
+ if(policy<0)
+ {
+ Print(EError,"Unrecognized option for CODEPAGINGOVERRIDE keyword\n");
+ success = false;
+ }
+ else
+ gCodePagingOverride = policy;
+ }
+ break;
+ case EKeywordDataPagingOverride:
+ {
+ if(iDataPagingOverrideParsed)
+ Print(EWarning, "DataPagingOverride redefined - previous DataPagingOverride values lost\n");
+/* if(iPagingOverrideParsed){
+ Print(EError, "DataPagingOverride defined - previous PagingOverride values lost\n");
+ success = false;
+ break;
+ }
+*/
+ iDataPagingOverrideParsed = true;
+ TInt policy = ParsePagingPolicy(iReader.Word(1));
+ if(policy < 0) {
+ Print(EError,"Unrecognized option for DATAPAGINGOVERRIDE keyword\n");
+ success = false;
+ }
+ else
+ gDataPagingOverride = policy;
+ }
+ break;
+ case EKeywordRofsAutoSize:
+ iAutoSize = ETrue;
+ Val(iAutoPageSize,iReader.Word(1));
+ break;
+ default:
+ // unexpected keyword iReader.Word(0)
+ break;
+ }
+
+ return success;
+}
+//
+// Checks that the obeyfile has supplied enough variables to continue
+//
+TBool CObeyFile::GotKeyVariables() {
+
+ TBool retVal=ETrue;
+ // Mandatory keywords
+ if (iRomFileName == 0) {
+ Print(EAlways,"The name of the image file has not been supplied.\n");
+ Print(EAlways,"Use the keyword \"rofsname\".\n");
+ retVal = EFalse;
+ }
+ if (iRomSize == 0) {
+ Print(EAlways,"The size of the image has not been supplied.\n");
+ Print(EAlways,"Use the keyword \"rofssize\".\n");
+ retVal = EFalse;
+ }
+ // Apply defaults as necessary
+ if (iTime == 0) {
+ Print(ELog, "No timestamp specified. Using current time...\n");
+ ObeyFileReader::TimeNow(iTime);
+ }
+ Print(ELog, "\nCreating Rofs image %s\n", iRomFileName);
+ return retVal;
+}
+
+//
+// Check the path is valid
+//
+const char* CObeyFile::IsValidFilePath(const char* aPath) {
+ // skip leading "\"
+ if (*aPath == '/' || *aPath == '\\')
+ aPath++;
+ if (*aPath == 0)
+ return NULL; // file ends in a backslash
+
+ const char *p = aPath;
+ TInt len=0;
+ while(*p) {
+ if (*p == '/' || *p == '\\') {
+ if (len == 0)
+ return NULL;
+ len=0;
+ p++;
+ continue;
+
+ }
+ len++;
+ p++;
+ }
+ return (len ? aPath : NULL);
+}
+
+const char* CObeyFile::IsValidDirPath(const char* aPath)
+{
+ const char* walker = aPath;
+
+ //validate path...
+ while(*walker)
+ {
+ if(((*walker=='/') || (*walker=='\\')) && ((*(walker+1)=='/') || (*(walker+1)=='\\')))
+ return (const char*)0;
+ walker++;
+ }
+
+ if((*aPath=='/') || (*aPath=='\\'))
+ aPath++;
+
+ return aPath;
+}
+
+//
+// Move the end pointer past the next directory separator, replacing it with 0
+//
+TBool CObeyFile::GetNextBitOfFileName(char*& epocEndPtr) {
+ while (*epocEndPtr != '/' && *epocEndPtr != '\\'){ // until reach the directory separator
+ if (*epocEndPtr == 0) // if reach end of string, return TRUE, it's the filename
+ return ETrue;
+ epocEndPtr++;
+ }
+ *epocEndPtr = 0; // overwrite the directory separator with a 0
+ epocEndPtr++; // point past the 0 ready for the next one
+ return EFalse;
+}
+
+void CObeyFile::AddFile(TRomBuilderEntry* aFile) {
+ *iNextFilePtrPtr = aFile;
+ iNextFilePtrPtr = &(aFile->iNext);
+}
+
+//
+// First pass through the obey file to set up key variables
+//
+TInt CObeyFile::ProcessExtensionRofs(MRofsImage* aKernelRom) {
+
+ iReader.Rewind();
+ enum EKeyword keyword;
+
+ // Deal with the "extensionrofs" keyword, which should be first
+ // however, you may've found "time" before it.
+ while(iReader.NextLine(1,keyword) != KErrEof) {
+ if(EKeywordExtensionRofs == keyword)
+ break ;
+ }
+ if(EKeywordExtensionRofs != keyword) return KErrEof;
+ iRomFileName = iReader.DupWord(1);
+ Print(ELog, "\n========================================================\n");
+ Print(ELog, "Extension ROFS %s starting at line %d\n\n", iRomFileName, iReader.CurrentLine());
+
+ iReader.MarkNext(); // so that we rewind to the line after the extensionrom keyword
+
+ while (iReader.NextLine(1,keyword) != KErrEof) {
+ if (keyword == EKeywordExtensionRofs)
+ break;
+ ProcessExtensionKeyword(keyword);
+ }
+
+ if (!GotExtensionVariables(aKernelRom))
+ return KErrGeneral;
+
+ // second pass to process the file specifications in the obey file building
+ // up the TRomNode directory structure and the TRomBuilderEntry list
+ //
+ iReader.Rewind();
+
+ //
+ if (aKernelRom == 0)
+ return Print(EError, "Option to extend a kernel ROFS image not yet implemented\n");
+
+ iRootDirectory = new TRomNode("");
+
+ iLastExecutable = 0;
+
+ (aKernelRom->RootDirectory())->deleteTheFirstNode();
+
+
+ iRootDirectory = aKernelRom->CopyDirectory(iLastExecutable);
+ aKernelRom->SetRootDirectory(iRootDirectory);
+
+
+ TInt align=0;
+ while (iReader.NextLine(2,keyword)!=KErrEof) {
+ if (keyword == EKeywordExtensionRofs)
+ break;
+
+ switch (keyword)
+ {
+ case EKeywordHide:
+ case EKeywordAlias:
+ case EKeywordRename:
+ if (!ProcessRenaming(keyword))
+ return KErrGeneral;
+ break;
+
+ case EKeywordPatchDllData:
+ {
+ // Collect patchdata statements to process at the end
+ StringVector patchDataTokens;
+ SplitPatchDataStatement(patchDataTokens);
+ iPatchData->AddPatchDataStatement(patchDataTokens);
+ break;
+ }
+ default:
+ if (!ProcessFile(align, keyword))
+ return KErrGeneral;
+ align=0;
+ break;
+ }
+ }
+
+ if(!ParsePatchDllData() )
+ return KErrGeneral;
+
+ iReader.MarkNext(); // ready for processing the next extension rom(s)
+
+ if (iMissingFiles!=0)
+ return KErrGeneral;
+ if (iNumberOfFiles == 0) {
+ Print(EError, "No files specified.\n");
+ return KErrGeneral;
+ }
+ return KErrNone;
+}
+void CObeyFile::ProcessExtensionKeyword(enum EKeyword aKeyword) {
+
+ switch (aKeyword)
+ {
+ case EKeywordCoreRofsName:
+ iKernelRofsName = iReader.DupWord(1);
+ return;
+ case EKeywordRofsSize:
+ Val(iRomSize,iReader.Word(1));
+ return;
+ case EKeywordVersion:
+ {
+ istringstream val(iReader.Word(1));
+ val >> iVersion;
+ }
+ return;
+ case EKeywordRomChecksum:
+ Val(iCheckSum,iReader.Word(1)); //--
+ return;
+ case EKeywordTime:
+ iReader.ProcessTime(iTime);
+ return;
+ case EKeywordRofsAutoSize:
+ iAutoSize = ETrue;
+ Val(iAutoPageSize , iReader.Word(1));
+ return;
+ default:
+ Print(EError,"Keyword '%s' not valid in extension ROFS - line %d\n", iReader.Word(0), iReader.CurrentLine());
+ break;
+ }
+ return;
+}
+//
+// Checks that the obeyfile has supplied enough variables to continue
+//
+TBool CObeyFile::GotExtensionVariables(MRofsImage* aRom) {
+
+ TBool retVal=ETrue;
+ const char* kernelRofsName = iKernelRofsName;
+
+ // Mandatory keywords
+
+ if (iRomSize == 0){
+ Print(EAlways,"The size of the extension ROFS has not been supplied.\n");
+ Print(EAlways,"Use the keyword \"rofssize\".\n");
+ retVal = EFalse;
+ }
+
+ // keywords we need if we don't already have a ROFS image to work from
+ if (aRom == 0) {
+ if (iKernelRofsName == 0) {
+ Print(EAlways,"The name of the core ROFS has not been supplied.\n");
+ Print(EAlways,"Use the keyword \"rofsname\".\n");
+ retVal = EFalse;
+ }
+ }
+ else {
+ if (iKernelRofsName != 0){
+ Print(EWarning,"Keyword \"rofsname\" ignored.\n");
+ }
+ kernelRofsName = aRom->RomFileName();
+ }
+
+ // validation
+ // Apply defaults as necessary
+ if (iTime == 0) {
+ Print(ELog, "No timestamp specified. Using current time...\n");
+ ObeyFileReader::TimeNow(iTime);
+ }
+
+ // fix up "*" in rofsname
+ char newname[256];
+ char* p=newname;
+ char* q=iRomFileName;
+ char c;
+
+ while ((c=*q++)!='\0'){
+ if (c!='*') {
+ *p++=c;
+ continue;
+ }
+ const char *r = kernelRofsName;
+ while ((c=*r++)!='\0')
+ *p++=c;
+ }
+ *p++ = '\0';
+ delete []iRomFileName;
+ size_t len = p - newname ;
+ iRomFileName = new char[len];
+ memcpy(iRomFileName,newname,len);
+ Print(ELog, "\nCreating ROFS image %s\n", iRomFileName);
+ return retVal;
+}
+
+// Fuction to split patchdata statement
+void CObeyFile::SplitPatchDataStatement(StringVector& aPatchDataTokens) {
+ // Get the value of symbol size, address/ordinal and new value
+ // to be patched from the patchdata statement.
+ // Syntax of patchdata statements is as follows:
+ // 1) patchdata dll_name ordinal OrdinalNumber size_in_bytes new_value
+ // 2) patchdata dll_name addr Address size_in_bytes new_value
+ for(TInt count=1; count<=5; count++) {
+ aPatchDataTokens.push_back(iReader.Word(count));
+ }
+
+ // Store the the value of current line which will be used
+ // when displaying error messages.
+ ostringstream outStrStream;
+ outStrStream<<iReader.CurrentLine();
+ aPatchDataTokens.push_back(outStrStream.str());
+}
+
+TBool CObeyFile::ParsePatchDllData() {
+ // Get the list of patchdata statements
+ VectorOfStringVector patchDataStatements=iPatchData->GetPatchDataStatements();
+ // Get the list of renamed file map
+ MapOfString RenamedFileMap=iPatchData->GetRenamedFileMap();
+
+ for(TUint count=0; count < patchDataStatements.size(); count++) {
+
+ StringVector strVector = patchDataStatements.at(count);
+ string filename=strVector.at(0);
+ string lineNoStr = strVector.at(5);
+ TUint lineNo = 0 ;
+ Val(lineNo,lineNoStr.c_str());
+ TRomNode* existingFile = NULL;
+
+ do {
+ TRomNode* dir=iRootDirectory;
+ TBool endOfName=EFalse;
+
+ if (!IsValidFilePath(filename.c_str())) {
+ Print(EError, "Invalid source path on line %d\n",lineNo);
+ return EFalse;
+ }
+ char* epocStartPtr =NormaliseFileName(filename.c_str());
+ char* savedPtr = epocStartPtr;
+ if(*epocStartPtr == '/' ||*epocStartPtr == '\\')
+ epocStartPtr++ ;
+ char* epocEndPtr = epocStartPtr;
+
+ while (!endOfName) {
+ endOfName = GetNextBitOfFileName(epocEndPtr);
+ if (endOfName) {// file
+ existingFile=dir->FindInDirectory(epocStartPtr);
+ if (existingFile) {
+ TInt fileCount=0;
+ TInt dirCount=0;
+ existingFile->CountDirectory(fileCount, dirCount);
+ if (dirCount != 0 || fileCount != 0) {
+ Print(EError, "Keyword %s not applicable to directories - line %d\n","patchdata",lineNo);
+ return EFalse;
+ }
+ }
+ }
+ else {// directory
+ TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
+ if (!subDir) // sub directory does not exist
+ break;
+ dir=subDir;
+ epocStartPtr = epocEndPtr;
+ }
+ }
+ delete []savedPtr;
+
+ if(!existingFile) {
+ // If the E32Image file to be patched is not included then check if the
+ // file was renamed.
+ MapOfStringIterator RenamedFileMapIterator;
+ if ((RenamedFileMapIterator=RenamedFileMap.find(filename)) != RenamedFileMap.end())
+ filename = (*RenamedFileMapIterator).second;
+ else {
+ Print(EError, "File %s not found - line %d\n", filename.c_str(), lineNo);
+ return EFalse;
+ }
+ }
+ }while(!existingFile);
+
+ TUint32 aSize, aOrdinal, aNewValue, aOffset;
+ TLinAddr aDataAddr;
+
+ aOrdinal = (TUint32)-1;
+ aDataAddr = (TUint32)-1;
+ aOffset = 0;
+
+ string symbolSize=strVector.at(3);
+ Val(aSize,symbolSize.c_str());
+ string aValue=strVector.at(4);
+ Val(aNewValue,aValue.c_str());
+
+ DllDataEntry *dataEntry = new DllDataEntry(aSize, aNewValue);
+
+ // Set the address of the data or the ordinal number specified in OBY statement.
+ string keyword=strVector.at(1);
+ string keywordValue=strVector.at(2);
+
+ /* Check for +OFFSET at the end of the ordinal number or address */
+ TUint plus = keywordValue.find("+",0);
+ if (plus != string::npos) {
+ /* Get the offset that we found after the + sign */
+ string offset = keywordValue.substr(plus+1);
+ Val(aOffset,offset.c_str());
+
+ keywordValue.resize(plus);
+ }
+ if(stricmp (keyword.c_str(), "addr") == 0)
+ Val(aDataAddr,keywordValue.c_str());
+
+ else
+ Val(aOrdinal,keywordValue.c_str());
+
+ dataEntry->iDataAddress = aDataAddr;
+ dataEntry->iOrdinal = aOrdinal;
+ dataEntry->iOffset = aOffset;
+
+ existingFile->SetDllData();
+
+ DllDataEntry *aDllDataEntry= existingFile->iEntry->GetFirstDllDataEntry();
+ if (aDllDataEntry == NULL) {
+ // Set the first node of the patchdata linked list
+ aDllDataEntry=dataEntry;
+ existingFile->iEntry->SetFirstDllDataEntry(aDllDataEntry);
+ }
+ else {
+ // Goto the last node
+ while((aDllDataEntry->NextDllDataEntry()) != NULL) {
+ aDllDataEntry = aDllDataEntry->NextDllDataEntry();
+ }
+ // Add the new node at the end of linked list
+ aDllDataEntry->AddDllDataEntry(dataEntry);
+ }
+ }
+ return ETrue;
+}