--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/romtools/rombuild/rombuild.cpp Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,628 @@
+// Copyright (c) 2007-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:
+//
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "h_utl.h"
+#include "h_ver.h"
+
+#include "r_global.h"
+#include "r_rom.h"
+#include "r_obey.h"
+#include "parameterfileprocessor.h"
+
+#include "r_dir.h"
+#include "r_coreimage.h"
+
+const TInt KRomLoaderHeaderNone=0;
+const TInt KRomLoaderHeaderEPOC=1;
+const TInt KRomLoaderHeaderCOFF=2;
+
+static const TInt RombuildMajorVersion=2;
+static const TInt RombuildMinorVersion=14;
+static const TInt RombuildPatchVersion=0;
+static TBool SizeSummary=EFalse;
+static TPrintType SizeWhere=EAlways;
+static char *CompareRom=NULL;
+static TInt MAXIMUM_THREADS = 128;
+static TInt DEFAULT_THREADS = 8;
+
+string filename; // to store oby filename passed to Rombuild.
+TBool reallyHelp=EFalse;
+TInt gCPUNum = 0;
+TInt gThreadNum = 0;
+char* g_pCharCPUNum = NULL;
+TBool gGenDepGraph = EFalse;
+char* gDepInfoFile = NULL;
+
+void PrintVersion()
+ {
+ Print(EAlways,"\nROMBUILD - Rom builder");
+ Print(EAlways, " V%d.%d.%d\n", RombuildMajorVersion, RombuildMinorVersion, RombuildPatchVersion);
+ Print(EAlways,Copyright);
+ }
+
+char HelpText[] =
+ "Syntax: ROMBUILD [options] obeyfilename\n"
+ "Option: -v verbose, -? \n"
+ " -type-safe-link \n"
+ " -s[log|screen|both] size summary\n"
+ " -r<FileName> compare a sectioned Rom image\n"
+ " -no-header suppress the image loader header\n"
+ " -gendep generate the dependence graph for paged part\n"
+ " -coff-header use a PE-COFF header rather than an EPOC header\n"
+ " -d<bitmask> set trace mask (DEB build only)\n"
+ " -compress[[=]paged|unpaged] compress the ROM Image\n"
+ " without any argumentum compress both sections\n"
+ " paged compress paged section only\n"
+ " unpaged compress unpaged section only\n"
+ " -fastcompress compress files with faster bytepair and tradeoff of compress ratio\n"
+ " -j<digit> do the main job with <digit> threads\n"
+ " -compressionmethod <method> method one of none|inflate|bytepair to set the compression\n"
+ " -no-sorted-romfs do not add sorted entries arrays (6.1 compatible)\n"
+ " -geninc to generate include file for licensee tools to use\n" // DEF095619
+ " -loglevel<level> level of information to log (valid levels are 0,1,2,3,4).\n" //Tools like Visual ROM builder need the host/ROM filenames, size & if the file is hidden.
+ " -wstdpath warn if destination path provided for a file is not a standard path\n"
+ " -argfile=<fileName> specify argument-file name containing list of command-line arguments to rombuild\n"
+ " -lowmem use memory-mapped file for image build to reduce physical memory consumption\n"
+ " -coreimage=<core image file> to pass the core image as input for extension ROM image generation\n";
+
+
+char ReallyHelpText[] =
+ "Priorities:\n"
+ " low background foreground high windowserver\n"
+ " fileserver realtimeserver supervisor\n"
+ "Languages:\n"
+ " Test English French German Spanish Italian Swedish Danish\n"
+ " Norwegian Finnish American SwissFrench SwissGerman Portuguese\n"
+ " Turkish Icelandic Russian Hungarian Dutch BelgianFlemish\n"
+ " Australian BelgianFrench\n"
+ "Compression methods:\n"
+ " none no compression on the individual executable image.\n"
+ " inflate compress the individual executable image.\n"
+ " bytepair compress the individual executable image.\n"
+ "Log Level:\n"
+ " 0 produce the default logs\n"
+ " 1 produce file detail logs in addition to the default logs\n"
+ " 2 logs e32 header attributes(same as default log) in addition to the level 1 details\n";
+
+void processParamfile(string aFileName);
+
+void processCommandLine(int argc, char *argv[], TBool paramFileFlag=EFalse)
+//
+// Process the command line arguments, printing a helpful message if none are supplied
+//
+ {
+
+ // If "-argfile" option is passed to Rombuild, then process the parameters
+ // specified in parameter-file first and then the options passed from the
+ // command-line.
+ string ParamFileArg("-ARGFILE=");
+ if(paramFileFlag == EFalse)
+ {
+ for (int count=1; count<argc; count++)
+ {
+ string paramFile;
+ strupr(argv[count]);
+ if(strncmp(argv[count],ParamFileArg.c_str(),ParamFileArg.length())==0)
+ {
+ paramFile.assign(&argv[count][ParamFileArg.length()]);
+ processParamfile(paramFile);
+ }
+ }
+ }
+
+ for (int i=1; i<argc; i++)
+ {
+ strupr(argv[i]);
+ if ((argv[i][0] == '-') || (argv[i][0] == '/'))
+ { // switch
+ if (argv[i][1] == 'V')
+ H.iVerbose = ETrue;
+ else if (argv[i][1] == 'S')
+ {
+ SizeSummary=ETrue;
+ if (argv[i][2] == 'L')
+ SizeWhere=ELog;
+ if (argv[i][2] == 'S')
+ SizeWhere=EScreen;
+ }
+ else if (strcmp(argv[i], "-FASTCOMPRESS")==0)
+ gFastCompress = ETrue;
+ else if (strcmp(argv[i], "-GENDEP")==0)
+ gGenDepGraph = ETrue;
+ else if (strncmp(argv[i], "-J", 2)==0)
+ {
+ if(argv[i][2])
+ gThreadNum = atoi(&argv[i][2]);
+ else
+ {
+ Print(EWarning, "The option should be like '-j4'.\n");
+ gThreadNum = 0;
+ }
+ if(gThreadNum <= 0 || gThreadNum > MAXIMUM_THREADS)
+ {
+ if(gCPUNum > 0 && gCPUNum <= MAXIMUM_THREADS)
+ {
+ Print(EWarning, "The number of concurrent jobs set by -j should be between 1 and 128. And the number of processors %d will be used as the number of concurrent jobs.\n", gCPUNum);
+ gThreadNum = gCPUNum;
+ }
+ else if(g_pCharCPUNum)
+ {
+ Print(EWarning, "The number of concurrent jobs set by -j should be between 1 and 128. And the NUMBER_OF_PROCESSORS is invalid, so the default value %d will be used.\n", DEFAULT_THREADS);
+ gThreadNum = DEFAULT_THREADS;
+ }
+ else
+ {
+ Print(EWarning, "The number of concurrent jobs set by -j should be between 1 and 128. And the NUMBER_OF_PROCESSORS is not available, so the default value %d will be used.\n", DEFAULT_THREADS);
+ gThreadNum = DEFAULT_THREADS;
+ }
+ }
+ }
+ else if (strncmp(argv[i],ParamFileArg.c_str(),ParamFileArg.length())==0)
+ {
+ // If "-argfile" option is specified within parameter-file then process it
+ // otherwise ignore the option.
+ if (paramFileFlag)
+ {
+ String paramFile;
+ paramFile.assign(&argv[i][ParamFileArg.length()]);
+ processParamfile(paramFile);
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else if (argv[i][1] == 'T')
+ TypeSafeLink=ETrue;
+ else if (argv[i][1] == '?')
+ reallyHelp=ETrue;
+ else if (argv[i][1] == 'R')
+ CompareRom=strdup(&argv[i][2]);
+ else if (strcmp(argv[i], "-NO-HEADER")==0)
+ gHeaderType=KRomLoaderHeaderNone;
+ else if (strcmp(argv[i], "-EPOC-HEADER")==0)
+ gHeaderType=KRomLoaderHeaderEPOC;
+ else if (strcmp(argv[i], "-COFF-HEADER")==0)
+ gHeaderType=KRomLoaderHeaderCOFF;
+ else if (strcmp(argv[i], "-COMPRESS")==0)
+ {
+ if( (i+1) >= argc || argv[i+1][0] == '-')
+ {
+ // No argument, compress both parts with default compression method
+ // un-paged part compressed by Deflate
+ gCompressUnpaged = ETrue;
+ gCompressUnpagedMethod = KUidCompressionDeflate;
+ // paged part compressed by the Bytepiar
+ gEnableCompress=ETrue;
+ gCompressionMethod = KUidCompressionBytePair;
+ }
+ else
+ {
+ // An argument exists
+ i++;
+ strupr(argv[i]);
+ if( strcmp(argv[i], "PAGED") == 0)
+ {
+ gEnableCompress=ETrue;
+ gCompressionMethod = KUidCompressionBytePair;
+ }
+ else if( strcmp(argv[i], "UNPAGED") == 0)
+ {
+ gCompressUnpaged=ETrue;
+ gCompressUnpagedMethod = KUidCompressionDeflate;
+ }
+ else
+ {
+ Print (EError, "Unknown -compression argument! Set it to default (no compression)!");
+ gEnableCompress=EFalse;
+ gCompressionMethod = 0;
+ gCompressUnpaged = EFalse;
+ gCompressUnpagedMethod = 0;
+ }
+ }
+ }
+ else if( strcmp(argv[i], "-COMPRESSIONMETHOD") == 0 )
+ {
+ // next argument should be a method
+ if( (i+1) >= argc || argv[i+1][0] == '-')
+ {
+ Print (EError, "Missing compression method! Set it to default (no compression)!");
+ gEnableCompress=EFalse;
+ gCompressionMethod = 0;
+ }
+ else
+ {
+ i++;
+ strupr(argv[i]);
+ if( strcmp(argv[i], "INFLATE") == 0)
+ {
+ gEnableCompress=ETrue;
+ gCompressionMethod = KUidCompressionDeflate;
+ }
+ else if( strcmp(argv[i], "BYTEPAIR") == 0)
+ {
+ gEnableCompress=ETrue;
+ gCompressionMethod = KUidCompressionBytePair;
+ }
+ else
+ {
+ if( strcmp(argv[i], "NONE") != 0)
+ {
+ Print (EError, "Unknown compression method! Set it to default (no compression)!");
+ }
+ gEnableCompress=EFalse;
+ gCompressionMethod = 0;
+ }
+ }
+
+ }
+ else if (strcmp(argv[i], "-NO-SORTED-ROMFS")==0)
+ gSortedRomFs=EFalse;
+ else if (strcmp(argv[i], "-GENINC")==0) // DEF095619
+ gGenInc=ETrue;
+ else if (strcmp(argv[i], "-WSTDPATH")==0) // Warn if destination path provided for a file
+ gEnableStdPathWarning=ETrue; // is not a standard path as per platsec
+ else if( strcmp(argv[i], "-LOGLEVEL") == 0)
+ {
+ // next argument should a be loglevel
+ if( (i+1) >= argc || argv[i+1][0] == '-')
+ {
+ Print (EError, "Missing loglevel!");
+ gLogLevel = DEFAULT_LOG_LEVEL;
+ }
+ else
+ {
+ i++;
+ if (strcmp(argv[i], "4") == 0)
+ gLogLevel = (LOG_LEVEL_FILE_DETAILS | LOG_LEVEL_FILE_ATTRIBUTES | LOG_LEVEL_COMPRESSION_INFO | LOG_LEVEL_SMP_INFO);
+ else if (strcmp(argv[i], "3") == 0)
+ gLogLevel = (LOG_LEVEL_FILE_DETAILS | LOG_LEVEL_FILE_ATTRIBUTES | LOG_LEVEL_COMPRESSION_INFO);
+ else if (strcmp(argv[i], "2") == 0)
+ gLogLevel = (LOG_LEVEL_FILE_DETAILS | LOG_LEVEL_FILE_ATTRIBUTES);
+ else if (strcmp(argv[i], "1") == 0)
+ gLogLevel = LOG_LEVEL_FILE_DETAILS;
+ else if (strcmp(argv[i], "0") == 0)
+ gLogLevel = DEFAULT_LOG_LEVEL;
+ else
+ Print(EError, "Only loglevel 0, 1, 2, 3 or 4 is allowed!");
+ }
+ }
+ else if( strcmp(argv[i], "-LOGLEVEL4") == 0)
+ gLogLevel = (LOG_LEVEL_FILE_DETAILS | LOG_LEVEL_FILE_ATTRIBUTES | LOG_LEVEL_COMPRESSION_INFO | LOG_LEVEL_SMP_INFO);
+ else if( strcmp(argv[i], "-LOGLEVEL3") == 0)
+ gLogLevel = (LOG_LEVEL_FILE_DETAILS | LOG_LEVEL_FILE_ATTRIBUTES | LOG_LEVEL_COMPRESSION_INFO);
+ else if( strcmp(argv[i], "-LOGLEVEL2") == 0)
+ gLogLevel = (LOG_LEVEL_FILE_DETAILS | LOG_LEVEL_FILE_ATTRIBUTES);
+ else if( strcmp(argv[i], "-LOGLEVEL1") == 0)
+ gLogLevel = LOG_LEVEL_FILE_DETAILS;
+ else if( strcmp(argv[i], "-LOGLEVEL0") == 0)
+ gLogLevel = DEFAULT_LOG_LEVEL;
+ else if (argv[i][1] == 'D')
+ {
+ TraceMask=strtoul(argv[i]+2, 0, 0);
+ }
+ else if (strcmp(argv[i], "-LOWMEM") == 0)
+ gLowMem = ETrue;
+ else if (strncmp(argv[i], "-COREIMAGE=",11) ==0)
+ {
+ if(argv[i][11])
+ {
+ gUseCoreImage = ETrue;
+ gImageFilename = (TText*)strdup(&argv[i][11]);
+ }
+ else
+ {
+ Print (EError, "Core ROM image file is missing\n");
+ }
+ }
+ else
+ cout << "Unrecognised option " << argv[i] << "\n";
+ }
+ else // Must be the obey filename
+ filename=argv[i];
+ }
+ if (paramFileFlag)
+ return;
+ if (filename.empty())
+ {
+ PrintVersion();
+ cout << HelpText;
+ if (reallyHelp)
+ {
+ ObeyFileReader::KeywordHelp();
+ cout << ReallyHelpText;
+ }
+ else
+ Print(EError, "Obey filename is missing\n");
+ }
+ }
+
+/**
+Function to process parameter-file.
+
+@param aFileName parameter-file name.
+*/
+void processParamfile(string aFileName)
+{
+ CParameterFileProcessor parameterFile(aFileName);
+
+ // Invoke fuction "ParameterFileProcessor" to process parameter-file.
+ if(parameterFile.ParameterFileProcessor())
+ {
+ TUint noOfParameters = parameterFile.GetNoOfArguments();
+ char** parameters = parameterFile.GetParameters();
+ TBool paramFileFlag=ETrue;
+
+ // Invoke function "processCommandLine" to process parameters read from parameter-file.
+ processCommandLine(noOfParameters, parameters, paramFileFlag);
+ }
+}
+
+void GenerateIncludeFile(char* aRomName, TInt aUnpagedSize, TInt aPagedSize )
+ {
+
+ const char * incFileNameExt = ".inc";
+
+ TText* incFileName;
+ incFileName=new TText[strlen(aRomName) + strlen(incFileNameExt) + 1]; // Place for include file name and ".inc" extension and '\0'
+ strcpy((char *)incFileName, aRomName);
+
+ char *p = (char*)strrchr((const char *)incFileName, '.');
+ if( NULL != p)
+ {
+ strncpy(p, incFileNameExt, strlen(incFileNameExt) + 1); // copy extension and the '\0'
+ }
+ else
+ {
+ strcat((char *)incFileName, incFileNameExt); //Doesn't cotains extension, add to it.
+ }
+
+ Print(EAlways," (%s)\n", (const char *)incFileName);
+
+ ofstream incFile((const char*)incFileName, ios::out);
+ if(!incFile)
+ {
+ Print(EError,"Cannot open include file %s for output\n",(const char *)incFileName);
+ }
+ else
+ {
+ const char * incContent =
+ "/** Size of the unpaged part of ROM.\n"
+ "This part is at the start of the ROM image. */\n"
+ "#define SYMBIAN_ROM_UNPAGED_SIZE 0x%08x\n"
+ "\n"
+ "/** Size of the demand paged part of ROM.\n"
+ "This part is stored immediately after the unpaged part in the ROM image. */\n"
+ "#define SYMBIAN_ROM_PAGED_SIZE 0x%08x\n";
+
+ TText* temp = new TText[strlen(incContent)+ 2 * 8 + 1]; // for place of two hex representated values and '\0'
+
+ sprintf((char *)temp,incContent, aUnpagedSize, aPagedSize);
+ incFile.write((const char *)temp, strlen((const char *)temp));
+
+ incFile.close();
+ delete[] temp;
+ }
+ delete[] incFileName;
+
+ }
+
+int main(int argc, char *argv[])
+{
+ H.SetLogFile((unsigned char *)"ROMBUILD.LOG");
+ TInt r = 0;
+ g_pCharCPUNum = getenv("NUMBER_OF_PROCESSORS");
+ if(g_pCharCPUNum != NULL)
+ gCPUNum = atoi(g_pCharCPUNum);
+
+ // initialise set of all capabilities
+ ParseCapabilitiesArg(gPlatSecAllCaps, "all");
+
+ processCommandLine(argc, argv);
+ if(filename.empty())
+ return KErrGeneral;
+
+ if(gThreadNum == 0)
+ {
+ if(gCPUNum > 0 && gCPUNum <= MAXIMUM_THREADS)
+ {
+ Print(EAlways, "The number of processors (%d) is used as the number of concurrent jobs.\n", gCPUNum);
+ gThreadNum = gCPUNum;
+ }
+ else if(g_pCharCPUNum)
+ {
+ Print(EWarning, "The NUMBER_OF_PROCESSORS is invalid, and the default value %d will be used.\n", DEFAULT_THREADS);
+ gThreadNum = DEFAULT_THREADS;
+ }
+ else
+ {
+ Print(EWarning, "The NUMBER_OF_PROCESSORS is not available, and the default value %d will be used.\n", DEFAULT_THREADS);
+ gThreadNum = DEFAULT_THREADS;
+ }
+ }
+ TText *obeyFileName= (TText*)filename.c_str();
+
+ PrintVersion();
+
+ ObeyFileReader *reader=new ObeyFileReader(obeyFileName);
+ if (!reader->Open())
+ {
+ delete reader;
+ return KErrGeneral;
+ }
+
+ E32Rom* kernelRom=0; // for image from obey file
+ CoreRomImage *core= 0; // for image from core image file
+ MRomImage* imageInfo=0;
+ CObeyFile *mainObeyFile=new CObeyFile(*reader);
+
+ // need check if obey file has coreimage keyword
+ TText *file = mainObeyFile->ProcessCoreImage();
+ if (file)
+ {
+ // hase coreimage keyword but only use if command line option
+ // for coreimage not already selected
+ if (!gUseCoreImage)
+ {
+ gUseCoreImage = ETrue;
+ gImageFilename = file;
+ }
+ }
+
+ if (!gUseCoreImage)
+ {
+ r=mainObeyFile->ProcessKernelRom();
+ if (r==KErrNone)
+ {
+ // Build a kernel ROM using the description compiled into the
+ // CObeyFile object
+
+ kernelRom = new E32Rom(mainObeyFile);
+ if (kernelRom == 0 || kernelRom->iData == 0)
+ return KErrNoMemory;
+
+ r=kernelRom->Create();
+ if (r!=KErrNone)
+ {
+ delete kernelRom;
+ delete mainObeyFile;
+ return r;
+ }
+ if (SizeSummary)
+ kernelRom->DisplaySizes(SizeWhere);
+
+ r=kernelRom->WriteImages(gHeaderType);
+ if (r!=KErrNone)
+ {
+ delete kernelRom;
+ delete mainObeyFile;
+ return r;
+ }
+
+ if (CompareRom)
+ {
+ r=kernelRom->Compare(CompareRom, gHeaderType);
+ if (r!=KErrNone)
+ {
+ delete kernelRom;
+ delete mainObeyFile;
+ return r;
+ }
+ }
+ imageInfo = kernelRom;
+ mainObeyFile->Release();
+ }
+ else if (r!=KErrNotFound)
+ return r;
+ }
+ else
+ {
+ // need to use core image
+ core = new CoreRomImage((char*)gImageFilename);
+ if (!core)
+ {
+ return KErrNoMemory;
+ }
+ if (!core->ProcessImage(gLowMem))
+ {
+ delete core;
+ delete mainObeyFile;
+ return KErrGeneral;
+ }
+
+ NumberOfVariants = core->VariantCount();
+ TVariantList::SetNumVariants(NumberOfVariants);
+ TVariantList::SetVariants(core->VariantList());
+
+ core->SetRomAlign(mainObeyFile->iRomAlign);
+ core->SetDataRunAddress(mainObeyFile->iDataRunAddress);
+
+ gCompressionMethod = core->CompressionType();
+ if(gCompressionMethod)
+ {
+ gEnableCompress = ETrue;
+ }
+
+ imageInfo = core;
+ if(!mainObeyFile->SkipToExtension())
+ {
+ delete core;
+ delete mainObeyFile;
+ return KErrGeneral;
+ }
+ }
+
+ if(gGenInc)
+ {
+ Print(EAlways,"Generating include file for ROM image post-processors ");
+ if( gPagedRom )
+ {
+ Print(EAlways,"Paged ROM");
+ GenerateIncludeFile((char*)mainObeyFile->iRomFileName, kernelRom->iHeader->iPageableRomStart, kernelRom->iHeader->iPageableRomSize);
+ }
+ else
+ {
+ Print(EAlways,"Unpaged ROM");
+ int headersize=(kernelRom->iExtensionRomHeader ? sizeof(TExtensionRomHeader) : sizeof(TRomHeader)) - sizeof(TRomLoaderHeader);
+ GenerateIncludeFile((char*)mainObeyFile->iRomFileName, kernelRom->iHeader->iCompressedSize + headersize, kernelRom->iHeader->iPageableRomSize);
+ }
+ }
+
+ do
+ {
+ CObeyFile* extensionObeyFile = 0;
+ E32Rom* extensionRom = 0;
+
+ extensionObeyFile = new CObeyFile(*reader);
+ r = extensionObeyFile->ProcessExtensionRom(imageInfo);
+ if (r==KErrEof)
+ {
+ delete imageInfo;
+ delete mainObeyFile;
+ delete extensionObeyFile;
+ return KErrNone;
+ }
+ if (r!=KErrNone)
+ {
+ delete extensionObeyFile;
+ break;
+ }
+
+ extensionRom = new E32Rom(extensionObeyFile);
+ r=extensionRom->CreateExtension(imageInfo);
+ if (r!=KErrNone)
+ {
+ delete extensionRom;
+ delete extensionObeyFile;
+ break;
+ }
+ if (SizeSummary)
+ extensionRom->DisplaySizes(SizeWhere);
+
+ r=extensionRom->WriteImages(0); // always a raw image
+
+ delete extensionRom;
+ delete extensionObeyFile;
+ }
+ while (r==KErrNone);
+
+ delete imageInfo;
+ delete mainObeyFile;
+ free(gDepInfoFile);
+ return r;
+}