diff -r 000000000000 -r 044383f39525 imgtools/romtools/rofsbuild/r_obey.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rofsbuild/r_obey.cpp Tue Oct 27 16:36:35 2009 +0000 @@ -0,0 +1,2274 @@ +/* +* 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 + +#ifdef __VC32__ + #ifdef __MSVCDOTNET__ + #include + #include + #else //__MSVCDOTNET__ + #include + #include + #endif //__MSVCDOTNET__ +#else // !__VC32__ +#ifdef __TOOLS2__ + #include + #include + #include + using namespace std; +#else + #include + #include +#endif + +#endif //__VC32__ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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)i2) + 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 (priorityEPrioritySupervisor) + 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 + * 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<GetPatchDataStatements(); + // Get the list of renamed file map + MapOfString RenamedFileMap=iPatchData->GetRenamedFileMap(); + + for(TUint count=0; countFindInDirectory(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; +} + + + + + + + + +