ROM Tools 13.1.0.4
authorZheng Shen <zheng.shen@nokia.com>
Wed, 13 Oct 2010 16:27:55 +0800
changeset 647 53d1ab72f5bc
parent 641 8dd670a9f34f
child 648 d5a8d436d33b
ROM Tools 13.1.0.4
bintools/petools/group/release.txt
cpptoolsplat/stlport/group/release.txt
imgtools/buildrom/group/release.txt
imgtools/buildrom/tools/buildrom.pl
imgtools/buildrom/tools/buildrom.pm
imgtools/buildrom/tools/datadriveimage.pm
imgtools/romtools/group/release.txt
imgtools/romtools/rofsbuild/fsnode.cpp
imgtools/romtools/rofsbuild/fsnode.h
imgtools/romtools/rofsbuild/r_driveutl.cpp
imgtools/romtools/rofsbuild/r_driveutl.h
imgtools/romtools/rofsbuild/r_obey.cpp
imgtools/romtools/rofsbuild/r_obey.h
imgtools/romtools/rofsbuild/rofsbuild.cpp
imgtools/romtools/rombuild/r_obey.cpp
imgtools/romtools/rombuild/rombuild.cpp
--- a/imgtools/buildrom/group/release.txt	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/buildrom/group/release.txt	Wed Oct 13 16:27:55 2010 +0800
@@ -1,3 +1,24 @@
+Version 3.30.0 (BUILDROM)
+===============
+Released by Lorence Wang, 12/10/2010
+	1) ROM tools performance improvement: ignore configuration check.
+
+Version 3.29.1 (BUILDROM)
+===============
+Released by Zheng Shen, 30/09/2010
+	1) ou1cimx1#577011 [MCL]Fallback failed in case of {} exists in filename, and file doesn't exists in default ABI folder
+
+Version 3.29.0 (BUILDROM)
+===============
+Released by Lorence Wang, 17/09/2010
+	1) Whole directory support in FAT.
+
+Version 3.28.1 (BUILDROM)
+===============
+Released by Lorence Wang, 13/09/2010
+	1) ou1cimx1#560005 Buildrom failed with -workdir="folder of different drive"
+	2) ou1cimx1#563537 Rofsbuild generates the log file for smr image and datadrive image in wrong location
+
 Version 3.28.0 (BUILDROM)
 ===============
 Released by Marvin Shi, 7/09/2010
--- a/imgtools/buildrom/tools/buildrom.pl	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/buildrom/tools/buildrom.pl	Wed Oct 13 16:27:55 2010 +0800
@@ -53,13 +53,15 @@
 	# Processes the buildrom command line parameters.
 	&process_cmdline_arguments;
 	
-	&image_content_processing_phase;
+	my $ignoreconfig = &isIgnoreConfig;
+	
+	&image_content_processing_phase if(!$ignoreconfig);
 
 	#Processes intermediate oby files.  Also processes any new option added to the buildrom in future.
-	&processobyfiles;
+	&processobyfiles if(!$ignoreconfig);
 
 	# Suppress ROM/ROFS/DataDrive Image creation if "-noimage" option is provided.
-	&suppress_image_generation;
+	&suppress_image_generation if(!$ignoreconfig);
 	
 	#Invokes ROMBUILD and ROFSBUILD
 	&invoke_rombuild;
--- a/imgtools/buildrom/tools/buildrom.pm	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/buildrom/tools/buildrom.pm	Wed Oct 13 16:27:55 2010 +0800
@@ -57,6 +57,7 @@
 	processData
 	create_smrimage
 	getWorkdir
+	isIgnoreConfig
 );
 
 my $useinterpretsis = 1;
@@ -66,7 +67,7 @@
 my $enforceFeatureManager = 0; # Flag to make Feature Manager mandatory if SYMBIAN_FEATURE_MANAGER macro is defined. 
 
 my $BuildromMajorVersion = 3 ;
-my $BuildromMinorVersion = 28;
+my $BuildromMinorVersion = 30;
 my $BuildromPatchVersion = 0;
 
 
@@ -159,6 +160,9 @@
    -stdcpp                          -- ignore symbian customized cpp and try to find another cpp in the PATH.(for Windows only)
    -cpp=xxx                         -- specify a CPP preprocessor used by Buildrom.
    -xiponly                      -- just create the XIP ROM image without creating the ROFS image.
+   -inputoby=<finalOBYfile>         -- Ignore BUILDROM config phase, invoke Rombuild/Rofsbuild using <finalOBYfile>.
+                                    <finalOBYfile> must contain one and ONLY one of romsize/rofssize/dataimagename/imagename keywords,
+                                    The keywords will be used to identify the OBY type.
    
 Popular -D defines to use include
 
@@ -354,6 +358,8 @@
 my $cppoption = 0;
 my $preprocessor = "cpp";
 my $opt_xiponly = 0;
+my $ignoreconfig = 0;
+my $romcount = 0;
 
 sub match_obyfile
 {
@@ -424,7 +430,8 @@
 					$compress =~m/\s-(compression)(method)\s(none|inflate|bytepair)/;
 					print "* ".$1." ".$2.": ".$3;
 				}
-				my $command = "rofsbuild -slog".$compress." -datadrive=$obeyfile.oby";
+				my $command = "rofsbuild -slog".$compress." -datadrive=$obeyfile.oby -logfile=$thisdir";
+				$command .= " -k" if($opt_k);      
 				print "* Executing $command\n" if ($opt_v);
 				system($command);
 				if ($? != 0)
@@ -505,129 +512,132 @@
 {
 	if($dataImageCount)
 	{
-		# set the default path for Z drive and Data drive directory,
-		# if and only if, path is not specified by the user. 
-		$ZDirloc = $thisdir."zdrive" unless ($ZDirloc);
-		$DataDriveDirloc = $thisdir."datadrive" unless ($DataDriveDirloc);
-		#delete any existing Z drive directory.
-		my $retVal = &datadriveimage::deleteDirectory($ZDirloc,$opt_v)if(!$opt_r);
-		if($retVal)
-		{
-			exit(1) if(!$opt_k);
-		}
-		# delete pre-existence of data drive folder, if and only if -r option is not enabled.
-		$retVal = &datadriveimage::deleteDirectory($DataDriveDirloc,$opt_v) if(!$opt_r);
-		if($retVal)
+		if(!$ignoreconfig)
 		{
-			exit(1) if(!$opt_k);
-		}
-		if($opt_logFile)
-		{
-			# clean any pre-existance of log file.
-			unlink($ZDirloc."\/".$imageEntryLogFile);
-		}
-		
-		for (my $datadriveidx=0; $datadriveidx < $dataImageCount; $datadriveidx++)
-		{
-			my $driveIndex = $dataIndexHash{$datadriveidx};
-			# get the data drive name.
-			if( defined( $driveIndex ) )
+			# set the default path for Z drive and Data drive directory,
+			# if and only if, path is not specified by the user. 
+			$ZDirloc = $thisdir."zdrive" unless ($ZDirloc);
+			$DataDriveDirloc = $thisdir."datadrive" unless ($DataDriveDirloc);
+			#delete any existing Z drive directory.
+			my $retVal = &datadriveimage::deleteDirectory($ZDirloc,$opt_v)if(!$opt_r);
+			if($retVal)
+			{
+				exit(1) if(!$opt_k);
+			}
+			# delete pre-existence of data drive folder, if and only if -r option is not enabled.
+			$retVal = &datadriveimage::deleteDirectory($DataDriveDirloc,$opt_v) if(!$opt_r);
+			if($retVal)
 			{
-				my $datadrivename=$datadriveimage[$driveIndex]{obeyfile};
-				# get the size of the data drive.
-				my $size = $datadriveimage[$driveIndex]{size};
-				if( $datadrivename )
+				exit(1) if(!$opt_k);
+			}
+			if($opt_logFile)
+			{
+				# clean any pre-existance of log file.
+				unlink($ZDirloc."\/".$imageEntryLogFile);
+			}
+			
+			for (my $datadriveidx=0; $datadriveidx < $dataImageCount; $datadriveidx++)
+			{
+				my $driveIndex = $dataIndexHash{$datadriveidx};
+				# get the data drive name.
+				if( defined( $driveIndex ) )
 				{
-					# set data drive oby file.
-					my $datadriveobyfile = $datadrivename.".oby";
-					# final location of prototype data drive.
-					my $proDataDriveDirloc;
-					# Location of stub-sis file(s) inside Z Drive folder.
-					my $zDriveSisFileLoc;
-					# check if more than one data drive image needs to be generated. 
-					if ($datadrivename =~ /.*[\\\/]([^\\\/]+)$/)
-					{
-						$datadrivename = $1;
-					}
-					if( $dataImageCount > 1 )
-					{
-						# if yes, then set the location of prototype data drive folder as 
-						# DataDriveDirloc + datadrivename
-						$proDataDriveDirloc = $DataDriveDirloc."\/".$datadrivename;
-					}
-					else
+					my $datadrivename=$datadriveimage[$driveIndex]{obeyfile};
+					# get the size of the data drive.
+					my $size = $datadriveimage[$driveIndex]{size};
+					if( $datadrivename )
 					{
-						# else, then set the location of prototype data drive folder as DataDriveDirloc 
-						$proDataDriveDirloc = $DataDriveDirloc;
-					}
-
-					# create prototype data drive folder.
-					print "creating data drive folder\n" if ($opt_v);
-					&datadriveimage::createDirectory($proDataDriveDirloc);
-
-					# check for sis file keyword in ROM description file.
-					# if found,then locate for stub-sisfile.
-					# create Z drive( if and only if stub-sis files are present in ROM description file )
-					# and dump all the non-sis files on to the Z drive folder. 
-					if(&datadriveimage::checkForSisFile($datadriveobyfile,\@sisfilelist,\$sisfilepresent))
-					{
-						my $zDriveImagePresent = 0; # flag to check whether z drive image is Present;
-						if(&datadriveimage::checkForZDriveImageKeyword($datadriveobyfile,\@zDriveImageList,\$zDriveImagePresent) )
+						# set data drive oby file.
+						my $datadriveobyfile = $datadrivename.".oby";
+						# final location of prototype data drive.
+						my $proDataDriveDirloc;
+						# Location of stub-sis file(s) inside Z Drive folder.
+						my $zDriveSisFileLoc;
+						# check if more than one data drive image needs to be generated. 
+						if ($datadrivename =~ /.*[\\\/]([^\\\/]+)$/)
 						{
-							# find out size of the array
-							my $arraysize = scalar(@zDriveImageList);
-							for( my $i=0; $i < $arraysize; $i++ )
-							{
-								$zDriveSisFileLoc =  $ZDirloc."\/".$datadrivename;
-								&datadriveimage::invokeReadImage(pop(@zDriveImageList),$zDriveSisFileLoc,$opt_v,$imageEntryLogFile,$opt_k);
-							}
+							$datadrivename = $1;
+						}
+						if( $dataImageCount > 1 )
+						{
+							# if yes, then set the location of prototype data drive folder as 
+							# DataDriveDirloc + datadrivename
+							$proDataDriveDirloc = $DataDriveDirloc."\/".$datadrivename;
 						}
 						else
 						{
-							$zDriveSisFileLoc = $ZDirloc;
-							# locate and copy stub-sis file(s),for the first time.
-							if( !$zDrivePresent )
+							# else, then set the location of prototype data drive folder as DataDriveDirloc 
+							$proDataDriveDirloc = $DataDriveDirloc;
+						}
+	
+						# create prototype data drive folder.
+						print "creating data drive folder\n" if ($opt_v);
+						&datadriveimage::createDirectory($proDataDriveDirloc);
+	
+						# check for sis file keyword in ROM description file.
+						# if found,then locate for stub-sisfile.
+						# create Z drive( if and only if stub-sis files are present in ROM description file )
+						# and dump all the non-sis files on to the Z drive folder. 
+						if(&datadriveimage::checkForSisFile($datadriveobyfile,\@sisfilelist,\$sisfilepresent))
+						{
+							my $zDriveImagePresent = 0; # flag to check whether z drive image is Present;
+							if(&datadriveimage::checkForZDriveImageKeyword($datadriveobyfile,\@zDriveImageList,\$zDriveImagePresent) )
 							{
-								# check for image file.
-								if( $opt_zimage )
+								# find out size of the array
+								my $arraysize = scalar(@zDriveImageList);
+								for( my $i=0; $i < $arraysize; $i++ )
 								{
-									# image(s)supplied to BUILDROM(like rom,rofs,extrofs or core) using "-zdriveimage" option, 
-									# are maintained in a seperate array and the element from the array is fetched one by one and is 
-									# fed to READIMAGE as an input.
-									foreach my $element (@zdriveImageName)
+									$zDriveSisFileLoc =  $ZDirloc."\/".$datadrivename;
+									&datadriveimage::invokeReadImage(pop(@zDriveImageList),$zDriveSisFileLoc,$opt_v,$imageEntryLogFile,$opt_k);
+								}
+							}
+							else
+							{
+								$zDriveSisFileLoc = $ZDirloc;
+								# locate and copy stub-sis file(s),for the first time.
+								if( !$zDrivePresent )
+								{
+									# check for image file.
+									if( $opt_zimage )
 									{
-										# invoke READIMAGE to extract all /swi stub sis file(s) from the given image.
-										$zDrivePresent = &datadriveimage::invokeReadImage($element,$zDriveSisFileLoc,$opt_v,$imageEntryLogFile,$opt_k);
+										# image(s)supplied to BUILDROM(like rom,rofs,extrofs or core) using "-zdriveimage" option, 
+										# are maintained in a seperate array and the element from the array is fetched one by one and is 
+										# fed to READIMAGE as an input.
+										foreach my $element (@zdriveImageName)
+										{
+											# invoke READIMAGE to extract all /swi stub sis file(s) from the given image.
+											$zDrivePresent = &datadriveimage::invokeReadImage($element,$zDriveSisFileLoc,$opt_v,$imageEntryLogFile,$opt_k);
+										}
 									}
-								}
-								else
-								{
-									# if zdrive image(s) such as (rom,core,rofs or extrofs) are generated ealier to the data drive image processing
-									# then these images are maintained in an array and the element from the array is fetched one by one and is 
-									# fed to READIMAGE as an input.
-									foreach my $element (@romImages)
+									else
 									{
-										# invoke READIMAGE to extract all /swi stub sis file(s) from the given image.
-										$zDrivePresent = &datadriveimage::invokeReadImage($element,$zDriveSisFileLoc,$opt_v,$imageEntryLogFile,$opt_k);
+										# if zdrive image(s) such as (rom,core,rofs or extrofs) are generated ealier to the data drive image processing
+										# then these images are maintained in an array and the element from the array is fetched one by one and is 
+										# fed to READIMAGE as an input.
+										foreach my $element (@romImages)
+										{
+											# invoke READIMAGE to extract all /swi stub sis file(s) from the given image.
+											$zDrivePresent = &datadriveimage::invokeReadImage($element,$zDriveSisFileLoc,$opt_v,$imageEntryLogFile,$opt_k);
+										}
 									}
 								}
 							}
+							# invoke INTERPRETSIS tool with z drive folder location.
+							if ($useinterpretsis)
+							{
+								&datadriveimage::invokeInterpretsis( \@sisfilelist,$proDataDriveDirloc,$opt_v,$zDriveSisFileLoc,$paraFile,$opt_k,\@interpretsisOptList,$thisdir)if($sisfilepresent);
+							}else
+							{
+								print "Warning: interpretsis is not ready on linux.\n";
+							}	
 						}
-						# invoke INTERPRETSIS tool with z drive folder location.
-						if ($useinterpretsis)
-						{
-							&datadriveimage::invokeInterpretsis( \@sisfilelist,$proDataDriveDirloc,$opt_v,$zDriveSisFileLoc,$paraFile,$opt_k,\@interpretsisOptList,$thisdir)if($sisfilepresent);
-						}else
-						{
-							print "Warning: interpretsis is not ready on linux.\n";
-						}	
+	
+						# create an oby file by traversing through upated prototype data drive directory.
+						&datadriveimage::dumpDatadriveObydata( $proDataDriveDirloc,$datadriveobyfile,$size,\@nonsisFilelist,
+											\@renameList,\@aliaslist,\@hideList,\@sisobydata,\@datadrivedata,$opt_k,$opt_v );
+						#reset sisfilepresent flag to zero;
+						$sisfilepresent =0;
 					}
-
-					# create an oby file by traversing through upated prototype data drive directory.
-					&datadriveimage::dumpDatadriveObydata( $proDataDriveDirloc,$datadriveobyfile,$size,\@nonsisFilelist,
-										\@renameList,\@aliaslist,\@hideList,\@sisobydata,\@datadrivedata,$opt_k,$opt_v );
-					#reset sisfilepresent flag to zero;
-					$sisfilepresent =0;
 				}
 			}
 		}
@@ -902,7 +912,7 @@
 		next;
 	    }
    		#Process imagecontent file 
-	    if( $arg =~ /^-i(.*)/)
+	    if( $arg =~ /^-i(.*)/ && $arg !~ /^-input(.*)/)
 	    {
 # Disabling -i option
 		print "Warning: Ignoring invalid Option $arg \n";
@@ -1106,6 +1116,61 @@
           }
           next;
         }
+		if ($arg =~ /^-inputoby=(.*)/)
+		{
+			$ignoreconfig =1;
+			my $ignoreoby = $1;
+			$ignoreoby .= ".oby" unless $ignoreoby =~ /\.oby$/i;
+			die "$ignoreoby file does not exist!!\n" if (!-e $ignoreoby);
+			open IGNORE, "$ignoreoby" or die("* Can't open $ignoreoby\n");
+			my @lines = <IGNORE>;
+			close IGNORE;
+			my $keywordcount = 0;
+			my $romimgcount = 0;
+			my $rofsimgcount = 0;
+			my $fatcount = 0;
+			my $smrcount = 0;
+			foreach my $line (@lines)
+			{
+				if ($line =~ /^\s*romsize\s*=/)
+				{
+					next if ($romimgcount);
+					$romimgcount = 1;
+					$keywordcount ++;
+					$ignoreoby =~ s/\.oby$//i;
+					$romimage[$romcount] = {xip=>1, obeyfile=>$ignoreoby, compress=>0, extension=>0, composite=>"none",uncompress=>0 };
+					$romcount ++;
+				}elsif ($line =~ /^\s*rofssize\s*=/)
+				{
+					next if ($rofsimgcount);
+					$rofsimgcount = 1;
+					$keywordcount ++;
+					$ignoreoby =~ s/\.oby$//i;
+					$romimage[$romcount] = {xip=>0, obeyfile=>$ignoreoby, compress=>0, extension=>0, composite=>"none",uncompress=>0 };
+					$romcount ++;
+				}elsif ($line =~ /^\s*dataimagename\s*=/)
+				{
+					next if ($fatcount);
+					$fatcount = 1;
+					$keywordcount ++;
+					$ignoreoby =~ s/\.oby$//i;
+					$datadriveimage[$dataImageCount] = {obeyfile=>$ignoreoby, compress=>0, uncompress=>0};
+					$dataImageCount ++;
+					$dataIndexHash{0} = 0;
+				}elsif ($line =~ /^\s*imagename\s*=/)
+				{
+					next if ($smrcount);
+					$smrcount = 1;
+					$keywordcount ++;
+					$ignoreoby =~ s/\.oby$//i;
+					$needSmrImage = 1;
+					push @obeyFileList, $ignoreoby;
+				}
+			}
+			die "$ignoreoby file does not contain keywords romsize/rofssize/dataimagename/imagename, cannot identify the oby type!\n" if ($keywordcount == 0);
+			die "$ignoreoby file contains $keywordcount keywords of romsize/rofssize/dataimagename/imagename, cannot identify the oby type! Maybe $ignoreoby is not a final oby file.\n" if ($keywordcount > 1);
+			next;
+		}
 		if( $arg =~ /^-loglevel\d+$/)
 		{
 			$logLevel= $arg;
@@ -1258,7 +1323,8 @@
 		return;
 	}
 	
-	if (@obyfiles<1)
+	$preserve = 1 if ($ignoreconfig);
+	if (@obyfiles<1 && !$ignoreconfig)
 	{
 	    print "Missing obyfile argument\n";
 	    $errors++ if(!$opt_k);
@@ -3250,6 +3316,7 @@
 				$from =~ s/\\/\\\\/g;	
 				$from =~ s/\//\\\//g;		# need to escape backslashes
 				$from =~ s/(\[|\])/\\$1/g;	# need to escape square brackets for file names like "featreg.cfg[x-y]",etc.
+				$from =~ s/(\{|\})/\\$1/g;	# need to escape brace for file names like "mydll{00010001}.dll",etc.
 				my $into = $fileExists;
 
  				$line =~ s/$from/$into/i;
@@ -3607,7 +3674,7 @@
 	{
 		return $line;
 	}
-	elsif($line =~ /^\s*dir\s*=.*/i)
+	elsif($line =~ /^\s*(dir|dircopy)\s*=.*/i)
 	{
 		return $line;
 	}
@@ -4868,7 +4935,8 @@
 		foreach my $oby (@obeyFileList)
 		{
 			is_existinpath("rofsbuild", romutl::ERROR_NOT_FOUND);
-			my $command = "rofsbuild -slog -smr=$oby.oby";
+			my $command = "rofsbuild -slog -smr=$oby.oby -logfile=$thisdir";
+			$command .= " -k" if($opt_k);      
 			print "* Executing $command\n" if($opt_v);
 			system($command);
 			if($? != 0)
@@ -4913,6 +4981,11 @@
 	return $thisdir;
 }
 
+sub isIgnoreConfig
+{
+	return $ignoreconfig;
+}
+
 sub find_stdcpp
 {
     return "cpp" if (!$stdcpp);
--- a/imgtools/buildrom/tools/datadriveimage.pm	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/buildrom/tools/datadriveimage.pm	Wed Oct 13 16:27:55 2010 +0800
@@ -288,20 +288,35 @@
 	open (OBEY ,$obyfile) or die($obyfile."\n");
 	while(my $line =<OBEY>) 
 	{
-		if( $line =~ /^(file|data)\s*=\s*(\"[^"]+\")\s+(\"[^"]+\")/i || 
-				$line =~ /^(file|data)\s*=\s*(\"[^"]+\")\s+(\S+)/i || 
-				$line =~ /^(file|data)\s*=\s*(\S+)\s+(\"[^"]+\")/i || 
-				$line =~ /^(file|data)\s*=\s*(\S+)\s+(\S+)/i )
+		if( $line =~ /^(file|data|dircopy)\s*=\s*(\"[^"]+\")\s+(\"[^"]+\")/i || 
+				$line =~ /^(file|data|dircopy)\s*=\s*(\"[^"]+\")\s+(\S+)/i || 
+				$line =~ /^(file|data|dircopy)\s*=\s*(\S+)\s+(\"[^"]+\")/i || 
+				$line =~ /^(file|data|dircopy)\s*=\s*(\S+)\s+(\S+)/i )
 		{
 			my $keyWord=$1;
 			my $source=$2;
 			my $dest=$3;
 
-			if( $source !~ /(\S+):([^"]+)/ )
-			{ 
-				$source = get_drive().$2;
+			my $currentdir=cwd;
+			$currentdir=~s-\\-\/-go;
+			$currentdir.= "\/" unless $currentdir =~ /\/$/;
+			$currentdir =~ s-\/-\\-g if (&is_windows);
+			my $drive = "";
+			$drive = $1 if ($currentdir =~ /^(.:)/);
+			$source =~ s/\"//g;
+			if ($source =~ /^[\\\/]/)
+			{
+				$source = $drive.$source;
+			}elsif ($source !~ /^.:/)
+			{
+				$source = $currentdir.$source;
 			}
-			my $var = &copyFilesToFolders( $source,$dest,$dir,$verboseOpt);
+			$source = "\"".$source."\"";
+
+			my $var = $source;
+			if ($keyWord ne "dircopy"){
+				$var = &copyFilesToFolders( $source,$dest,$dir,$verboseOpt);
+			}
 			if($var)
 			{
 				$line = $keyWord."=".$var."\t".$dest."\n";
@@ -371,8 +386,6 @@
 	my $command = "interpretsis ";
 	my $vOption = "-w info" if ($verboseOpt);
 	
-	is_existinpath("interpretsis", romutl::DIE_NOT_FOUND);
-
 	# do a check if the path has a white space.
 	if( $dataDrivePath =~ m/ /)
 	{
@@ -457,6 +470,11 @@
 	print "* Changing to $outputdir\n" if ( $verboseOpt );
 	chdir "$outputdir";
 	
+	my $epocroot = &get_epocroot;
+	if ($epocroot !~ /^(.:)/)
+	{
+	  $ENV{EPOCROOT} = $drive.$epocroot;
+	}
 	print "* Executing $command\n" if ( $verboseOpt );
 	system ( $command );
 
@@ -467,6 +485,7 @@
 	
 	print "* Changing back to $currentdir\n" if ( $verboseOpt );
 	chdir "$currentdir";
+	$ENV{EPOCROOT} = $epocroot;
 }
 
 # invoke the READIMAGE tool with appropriate parameters.
@@ -654,7 +673,7 @@
 			my $linekeyword = "alias";
 			&compareArrays($aliasArray,$nonsisFileArray,$linesource,$linedest,$linekeyword);
 		}
-		elsif(	$line =~ /^(file|data)\s*=\s*/i || $line =~ /^\s*(zdriveimagename|sisfile)\s*=\s*/i )
+		elsif(	$line =~ /^(file|data|dircopy)\s*=\s*/i || $line =~ /^\s*(zdriveimagename|sisfile)\s*=\s*/i )
 		{
 			# skip to next line. 
 			next;
--- a/imgtools/romtools/group/release.txt	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/group/release.txt	Wed Oct 13 16:27:55 2010 +0800
@@ -1,4 +1,20 @@
-Version 2.13.0 (ROFSBUILD)
+Version 2.18.3 (ROMBUILD)
+Version 2.14.1 (ROFSBUILD)
+===============
+Released by Lorence Wang, 19/09/2010
+	1) ou1cimx1#498436 rombuild prompt 2 warnings when there's an unknown keyword in oby.
+
+Version 2.14.0 (ROFSBUILD)
+===============
+Released by Lorence Wang, 17/09/2010
+	1) Whole directory support in FAT.
+
+Version 2.13.3 (ROFSBUILD)
+===============
+Released by Lorence Wang, 13/09/2010
+	1) ou1cimx1#563537 Rofsbuild generates the log file for smr image and datadrive image in wrong location
+
+Version 2.13.2 (ROFSBUILD)
 ===============
 Released by Jason Cui, 25/08/2010
 	1) ROFSBUILD generates 0-length log file.
--- a/imgtools/romtools/rofsbuild/fsnode.cpp	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rofsbuild/fsnode.cpp	Wed Oct 13 16:27:55 2010 +0800
@@ -25,19 +25,6 @@
  
 #include <ctype.h> 
  
-
-#ifdef __LINUX__
-#include <dirent.h> 
-#include <sys/stat.h>
-#include <unistd.h>
-#define SPLIT_CHAR '/'
-#else
-#include <io.h> 
-#include <direct.h> //TODO: check under MinGW4 + stlport 5.2
-#include <conio.h> 
-#define SPLIT_CHAR '\\'
-#endif
- 
 using namespace std;
 
 const TUint KBytesPerEntry = 13 ;
@@ -105,85 +92,6 @@
 		free(iPCSideName);
 }
  
-TFSNode* TFSNode::CreateFromFolder(const char* aPath,TFSNode* aParent) { 
-	 
-	int len = strlen(aPath);  
-#ifdef __LINUX__
-	DIR* dir = opendir(aPath);
-	if(dir == NULL) {
-		cout << aPath << " does not contain any subfolder/file.\n";     
-			return aParent;
-	}
-	if(!aParent)
-		aParent = new TFSNode(NULL,"/",ATTR_DIRECTORY);
-	dirent*  entry; 
-	struct stat statbuf ;
-	char* fileName = new(nothrow) char[len + 200];
-	if(!fileName) return NULL ;
-	memcpy(fileName,aPath,len); 
-	fileName[len] = SPLIT_CHAR;
-	while ((entry = readdir(dir)) != NULL)  {
-		if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0)
-			continue ; 
-		strcpy(&fileName[len+1],entry->d_name);             
-		stat(fileName , &statbuf);         
-		TFSNode* pNewItem = new TFSNode(aParent,fileName,S_ISDIR(statbuf.st_mode) ? ATTR_DIRECTORY : 0);
-		pNewItem->Init(statbuf.st_ctime,statbuf.st_atime,statbuf.st_mtime,statbuf.st_size);         
-		if(S_ISDIR(statbuf.st_mode)){ 
-			CreateFromFolder(fileName,pNewItem);
-		} 
-	}	
-	delete []fileName ;
-	closedir(dir);
-#else
-	struct _finddata_t data ;
-	memset(&data, 0, sizeof(data)); 	
-	char* fileName = new(nothrow) char[len + 200];
-	if(!fileName) return NULL ;
-	memcpy(fileName,aPath,len); 
-    fileName[len] = SPLIT_CHAR;
-	fileName[len+1] = '*';
-	fileName[len+2] = 0;
-	intptr_t hFind =  _findfirst(fileName,&data); 
- 
-	if(hFind == (intptr_t)-1 ) {
-		cout << aPath << " does not contain any subfolder/file.\n";		
-		delete []fileName;
-		return aParent;
-	}	
-	if(!aParent)
-	    aParent = new TFSNode(NULL,"/",ATTR_DIRECTORY);	
-	
-	do {        
-        if(strcmp(data.name,".") == 0 || strcmp(data.name,"..") == 0)
-            continue ; 
-        
-        strcpy(&fileName[len+1],data.name); 
-        TUint8 attr = 0;
-        if(data.attrib & _A_SUBDIR)  
-            attr |= ATTR_DIRECTORY;
-        if(data.attrib & _A_RDONLY)
-            attr |= ATTR_READ_ONLY ;
-        if(data.attrib &  _A_HIDDEN)
-            attr |= ATTR_HIDDEN ;
-        if(data.attrib & _A_SYSTEM)
-            attr |= ATTR_SYSTEM ;
-        if(data.attrib & _A_ARCH)
-            attr |= ATTR_ARCHIVE;      
-        TFSNode* pNewItem = new TFSNode(aParent,data.name,attr,fileName);        
-        pNewItem->Init(data.time_create,data.time_access,data.time_write,data.size);            
-        if(data.attrib & _A_SUBDIR){ 
-            CreateFromFolder(fileName,pNewItem);
-        }  
- 
-    } while(-1 != _findnext(hFind, &data));
-	delete []fileName ;
-    _findclose(hFind);
-#endif
- 
-	return aParent;
-}
- 
 /** GenerateBasicName : Generate the short name according to long name 
 	* 
 	* algorithm :
--- a/imgtools/romtools/rofsbuild/fsnode.h	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rofsbuild/fsnode.h	Wed Oct 13 16:27:55 2010 +0800
@@ -55,9 +55,7 @@
 	// GetSize() 
 	void WriteDirEntries(TUint aStartIndex, TUint8* aClusterData ); 
 	
-	static TFSNode* CreateFromFolder(const char* aPath,TFSNode* aParent = NULL);
-	
-	
+
 	
 protected:
 	void GenerateBasicName();
--- a/imgtools/romtools/rofsbuild/r_driveutl.cpp	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rofsbuild/r_driveutl.cpp	Wed Oct 13 16:27:55 2010 +0800
@@ -32,33 +32,49 @@
 Checks the validity of driveobey file name before creating the log file name.
 
 @param adriveobeyFileName - Drive obey file.
-@param &apadlogfile       - Reference to log file name.
+@param &apadlogfile       - Log file name from command line. 
   
 @return - returns 'ErrorNone' if log file created, otherwise returns Error.
 */ 
-TInt Getlogfile(char *aDriveObeyFileName,char* &aPadLogFile)
+string Getlogfile(char *aDriveObeyFileName,const string &CmdLogFile)
 	{
-
+	string strLogfile(CmdLogFile);
+	if(strLogfile.size() > 0 && strLogfile[strLogfile.size()-1] != '\\' && strLogfile[strLogfile.size()-1] != '/')
+		return strLogfile;
+		
 	if(!(*aDriveObeyFileName))
-		return KErrGeneral;
+		return string("");
 
 	// Validate the user entered driveoby file name.
 	char* logFile = (char*)aDriveObeyFileName;
 
+#ifdef __LINUX__
+	logFile = strrchr(logFile,'/');
+#else
+	while(*logFile)
+		{
+		if(*logFile == '/')
+			*logFile = '\\';
+		logFile++;
+		}
+	logFile = (char*)aDriveObeyFileName;
+	logFile = strrchr(logFile,'\\');
+#endif
+	
+	if(logFile)
+		++logFile;
+	else
+		logFile = (char*)aDriveObeyFileName;
+
 	TInt len = strlen(logFile);
 	if(!len)
-		return KErrGeneral;
-
-	// Allocates the memory for log file name.
-	aPadLogFile = new char[(len)+5]; 
-	if(!aPadLogFile)
-		return KErrNoMemory;
+		return string("");
 
 	// Create the log file name.
-	strcpy((char*)aPadLogFile,logFile);
-	strcat((char*)aPadLogFile,".LOG");
+	strLogfile += logFile;
+	strLogfile += ".LOG";
 				
-	return  KErrNone;
+	return  strLogfile;
 	}
 
 /**
--- a/imgtools/romtools/rofsbuild/r_driveutl.h	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rofsbuild/r_driveutl.h	Wed Oct 13 16:27:55 2010 +0800
@@ -23,7 +23,7 @@
 
 #include <e32def.h>
 
-TInt Getlogfile(char *aDriveObeyFileName,char* &aPadLogFile);
+string Getlogfile(char *aDriveObeyFileName,const string &CmdLogFile);
 TAny GetLocalTime(TAny);
 
 #endif
--- a/imgtools/romtools/rofsbuild/r_obey.cpp	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rofsbuild/r_obey.cpp	Wed Oct 13 16:27:55 2010 +0800
@@ -40,6 +40,16 @@
 #include "fatimagegenerator.h" 
 #include "r_driveimage.h"
 
+#ifdef __LINUX__
+#include <dirent.h> 
+#include <sys/stat.h>
+#include <unistd.h>
+#else
+#include <io.h> 
+#include <direct.h> //TODO: check under MinGW4 + stlport 5.2
+#include <conio.h> 
+#endif
+
 #include "uniconv.hpp"
 extern TInt gCodePagingOverride;
 extern TInt gDataPagingOverride;
@@ -57,6 +67,7 @@
 	{_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("dircopy"),      2,-2, EKeywordDirCpy, "Directory to be copied into FAT image"},
 
 	{_K("rofsname"),	1, 1, EKeywordRofsName, "output file for ROFS image"},
 	{_K("romsize"),		1, 1, EKeywordRomSize, "size of ROM image"}, 
@@ -268,7 +279,7 @@
 }
 
 TInt ObeyFileReader::NextLine(TInt aPass, enum EKeyword& aKeyword) {
-
+	static int warnline = -1;
 NextLine:
 	TInt err = ReadAndParseLine();
 	if (err == KErrEof)
@@ -312,8 +323,10 @@
 		aKeyword = k->iKeywordEnum;
 		return KErrNone;
 	}
-	if (aPass == 1)
+	if (aPass == 1 && iCurrentLine > warnline){
+		warnline = iCurrentLine;
 		Print(EWarning, "Unknown keyword '%s'.  Line %d ignored\n", iWord[0], iCurrentLine);
+	}
 	goto NextLine;
 }
 
@@ -740,6 +753,7 @@
 		case EKeywordHide:						
 		case EKeywordFile:
 		case EKeywordDir:
+		case EKeywordDirCpy:
 		case EKeywordData:
 		case EKeywordFileCompress:
 		case EKeywordFileUncompress:
@@ -933,7 +947,6 @@
 */
 TBool CObeyFile::ProcessDriveFile(enum EKeyword aKeyword) {
 
-	TBool isPeFile = ETrue;
 	TBool aFileCompressOption, aFileUncompressOption;
 
 	TInt epocPathStart=2;
@@ -945,8 +958,8 @@
 	{
 	case EKeywordData:
 	case EKeywordDir:
+	case EKeywordDirCpy:
 	case EKeywordHide:
-		isPeFile = EFalse;
 		break;
 
 	case EKeywordFile:
@@ -964,7 +977,7 @@
 		return EFalse;
 	}
 
-	if (aKeyword!=EKeywordHide && aKeyword!=EKeywordDir) {
+	if (aKeyword!=EKeywordHide && aKeyword!=EKeywordDir && aKeyword!=EKeywordDirCpy) {
 		// check the PC file exists
 		char* nname = NormaliseFileName(iReader.Word(1));		  
 		if(gIsOBYUTF8 && !UniConv::IsPureASCIITextStream(nname))
@@ -990,15 +1003,12 @@
 		delete []nname ;												
 		 
 	}
-	else
+	else if (aKeyword != EKeywordDirCpy)
 		epocPathStart=1;   
 
-	if(aKeyword != EKeywordDir)
-		iNumberOfFiles++;
-
 	TBool endOfName=EFalse;
 	const char *epocStartPtr;
-	if(aKeyword != EKeywordDir)
+	if(aKeyword != EKeywordDir && aKeyword != EKeywordDirCpy)
 		epocStartPtr = IsValidFilePath(iReader.Word(epocPathStart));
 	else
 		epocStartPtr = IsValidDirPath(iReader.Word(epocPathStart));
@@ -1011,59 +1021,12 @@
 
 	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)
+		if (endOfName && (aKeyword!=EKeywordDir) && (aKeyword!=EKeywordDirCpy)) { // file
+			if (!AddFileToNodeTree(aKeyword, dir, epocStartPtr, iReader.Word(1), ETrue, aFileCompressOption, aFileUncompressOption))
 				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
@@ -1071,24 +1034,195 @@
 			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;
+			subDir = AddDirToNodeTree(aKeyword, dir, epocStartPtr);				
+			if (!subDir) {
+				if (aKeyword != EKeywordHide)
+					return EFalse;//this is for memory alloc failed
+				else
+					return ETrue;//this is for hide a non-exist dir
 			}
 			dir=subDir;
 			epocStartPtr = epocEndPtr;
 		}  // end of else.
 	}
+
+	if (aKeyword == EKeywordDirCpy)	{
+		if(!CreateFromFolder(iReader.Word(1), dir))
+			return EFalse;
+	}
+		
 	return ETrue;
 }
 
+TRomNode* CObeyFile::AddFileToNodeTree(enum EKeyword aKeyword, TRomNode* dir, const char* filename, const char* aPCSidename, const TBool aParseAttr, TBool aFileCompressOption, TBool aFileUncompressOption)	{
+	TRomNode* alreadyExists=dir->FindInDirectory(filename);
+	if ((aKeyword != EKeywordHide) && alreadyExists) { // duplicate file		
+		if (gKeepGoing) {
+			Print(EWarning, "Duplicate file for %s on line %d, will be ignored\n",aPCSidename,iReader.CurrentLine());
+			return alreadyExists;
+		}
+		else {	
+			Print(EError, "Duplicate file for %s on line %d\n",aPCSidename,iReader.CurrentLine());
+			return 0;
+		}
+	}
+	else if((aKeyword == EKeywordHide) && (alreadyExists)) { 
+		alreadyExists->iEntry->iHidden = ETrue;
+		alreadyExists->iHidden = ETrue;
+		return alreadyExists;
+	}
+	else if((aKeyword == EKeywordHide) && (!alreadyExists)) {
+		Print(EWarning, "Hiding non-existent file %s on line %d\n",aPCSidename,iReader.CurrentLine());
+		return (TRomNode*)1;
+	}
+
+	iNumberOfFiles++;
+	TRomBuilderEntry* file = new TRomBuilderEntry(aPCSidename, filename);                   
+	if( aFileCompressOption ) {
+		file->iCompressEnabled = ECompressionCompress;
+	}
+	else if(aFileUncompressOption )	{
+		file->iCompressEnabled = ECompressionUncompress;
+	}
+
+	TRomNode* node=new TRomNode(filename, file);
+	if (node==0)
+		return 0;
+
+	if (aParseAttr){
+		TInt r=ParseFileAttributes(node, file, aKeyword);         
+		if (r!=KErrNone)
+			return 0;
+	}
+	if(gCompress != ECompressionUnknown) {
+		node->iFileUpdate = ETrue;
+	}
+
+	if((node->iOverride) || (aFileCompressOption) || (aFileUncompressOption)) {
+		node->iFileUpdate = ETrue;
+	}
+
+	dir->AddFile(node);	// to drive directory structure.
+	return node;
+}
+
+TRomNode* CObeyFile::AddDirToNodeTree(enum EKeyword aKeyword, TRomNode* dir, const char* dirname) {
+	TRomNode* subDir = dir->FindInDirectory(dirname);      
+	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 0;
+		}
+		subDir = dir->NewSubDir(dirname);
+		if (!subDir)
+			return 0;
+	}
+	return subDir;
+}
+
+TBool CObeyFile::CreateFromFolder(const char* aPath,TRomNode* aParent) { 
+	int len = strlen(aPath);  
+	if(!aParent)
+		aParent = new TRomNode("//");
+#ifdef __LINUX__
+	DIR* dir = opendir(aPath);
+	if(dir == NULL) {
+		Print(EError, "The directory %s does not exist.\n",aPath);
+		return EFalse;
+	}
+	dirent*  entry; 
+	struct stat statbuf ;
+	char* fileName = new(nothrow) char[len + 200];
+	if(!fileName) return EFalse ;
+	memcpy(fileName,aPath,len); 
+	fileName[len] = '/';
+	while ((entry = readdir(dir)) != NULL)  {
+		if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0)
+			continue ; 
+		strcpy(&fileName[len+1],entry->d_name);             
+		stat(fileName , &statbuf);   
+		if (S_ISDIR(statbuf.st_mode)){
+			TRomNode* subdir = AddDirToNodeTree(EKeywordDirCpy, aParent, entry->d_name);
+			if (!subdir){
+				delete []fileName;
+				return EFalse;
+			}
+			if (!CreateFromFolder(fileName, subdir)){
+				delete []fileName;
+				return EFalse;
+			}
+		}else{
+			if (!AddFileToNodeTree(EKeywordDirCpy, aParent, entry->d_name, fileName, EFalse)){
+				delete []fileName;
+				return EFalse;
+			}
+		}
+	}	
+	delete []fileName ;
+	closedir(dir);
+#else
+	struct _finddata_t data ;
+	memset(&data, 0, sizeof(data)); 	
+	char* fileName = new(nothrow) char[len + 200];
+	if(!fileName) return EFalse ;
+	memcpy(fileName,aPath,len); 
+  fileName[len] = '\\';
+	fileName[len+1] = '*';
+	fileName[len+2] = 0;
+	intptr_t hFind =  _findfirst(fileName,&data); 
+ 
+	if(hFind == (intptr_t)-1 ) {
+		Print(EError, "The directory %s does not exist.\n",aPath);
+		delete []fileName;
+		return EFalse;
+	}	
+	
+	do {        
+    if(strcmp(data.name,".") == 0 || strcmp(data.name,"..") == 0)
+        continue ; 
+        
+    strcpy(&fileName[len+1],data.name); 
+    if(data.attrib & _A_SUBDIR){ 
+			TRomNode* subDir = AddDirToNodeTree(EKeywordDirCpy, aParent, data.name);
+			if (!subDir){
+				delete []fileName;
+				return EFalse;
+			}
+      if(data.attrib & _A_RDONLY)
+				subDir->iAtt |= KEntryAttReadOnly;
+      if(data.attrib &  _A_HIDDEN){
+				subDir->iAtt |= KEntryAttHidden;
+			}
+      if(data.attrib & _A_SYSTEM)
+				subDir->iAtt |= KEntryAttSystem;
+			if (!CreateFromFolder(fileName, subDir)){
+				delete []fileName;
+				return EFalse;
+			}
+		}else{
+			TRomNode* node = AddFileToNodeTree(EKeywordDirCpy, aParent, data.name, fileName, EFalse);
+			if (!node){
+				delete []fileName;
+				return EFalse;
+			}
+      if(data.attrib & _A_RDONLY)
+				node->iAtt |= KEntryAttReadOnly;
+      if(data.attrib &  _A_HIDDEN){
+				node->iAtt |= KEntryAttHidden;
+     		node->iEntry->iHidden = ETrue;
+				node->iHidden = ETrue;
+			}
+      if(data.attrib & _A_SYSTEM)
+				node->iAtt |= KEntryAttSystem;
+		}
+  } while(-1 != _findnext(hFind, &data));
+	delete []fileName ;
+  _findclose(hFind);
+#endif
+ 
+	return ETrue;
+}
 
 TInt CObeyFile::SetStackSize(TRomNode *aNode, const char* aStr) {
 	if (EFalse == IsValidNumber(aStr))
--- a/imgtools/romtools/rofsbuild/r_obey.h	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rofsbuild/r_obey.h	Wed Oct 13 16:27:55 2010 +0800
@@ -48,6 +48,7 @@
 	EKeywordFile,
 	EKeywordData,
 	EKeywordDir,
+	EKeywordDirCpy,
 	EKeywordRofsName,
 	EKeywordExtensionRofs, 
 	EKeywordCoreRofsName,
@@ -252,6 +253,10 @@
 	TInt SetUid2(TRomNode* aNode, const char *aStr);
 	TInt SetUid3(TRomNode* aNode, const char *aStr);
 	TInt SetPriority(TRomNode* aNode, const char *aStr);
+
+	TRomNode* AddFileToNodeTree(enum EKeyword aKeyword, TRomNode* dir, const char* filename, const char* aPCSidename, const TBool aParseAttr, TBool aFileCompressOption = EFalse, TBool aFileUncompressOption = EFalse);
+	TRomNode* AddDirToNodeTree(enum EKeyword aKeyword, TRomNode* dir, const char* dirname);
+	TBool CreateFromFolder(const char* aPath,TRomNode* aParent);
 	
 	static TBool GetNextBitOfFileName(char*& epocEndPtr);
 	static const char *IsValidFilePath(const char *aPath);
--- a/imgtools/romtools/rofsbuild/rofsbuild.cpp	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rofsbuild/rofsbuild.cpp	Wed Oct 13 16:27:55 2010 +0800
@@ -46,8 +46,8 @@
 #endif
 
 static const TInt RofsbuildMajorVersion=2;
-static const TInt RofsbuildMinorVersion=13;
-static const TInt RofsbuildPatchVersion=2;
+static const TInt RofsbuildMinorVersion=14;
+static const TInt RofsbuildPatchVersion=1;
 static TBool SizeSummary=EFalse;
 static TPrintType SizeWhere=EAlways;
 
@@ -77,7 +77,7 @@
 TBool reallyHelp = EFalse;	
 TBool gSmrImage = EFalse;
 string gSmrFileName = "";
-static string rofslogfile = "ROFSBUILD.LOG";
+static string cmdlogfile = "";
 
 //Cache global variables
 bool gCache = false;
@@ -323,7 +323,7 @@
 			else if (stricmp(argv[i], "-LOWMEM") == 0)
 				gLowMem = ETrue;
 			else if (strnicmp(argv[i], "-logfile=",9) ==0) {
-				rofslogfile = argv[i] + 9;
+				cmdlogfile = argv[i] + 9;
 			}
 			else {
 #ifdef WIN32
@@ -386,7 +386,7 @@
 
 @return - returns the status, after processing the drive obey file.
 */ 
-TInt ProcessDataDriveMain(char* aobeyFileName,char* alogfile) {
+TInt ProcessDataDriveMain(char* aobeyFileName, const char* alogfile) {
 
 	ObeyFileReader *reader = new ObeyFileReader(aobeyFileName);
 
@@ -432,7 +432,7 @@
 	return retstatus;
 }
 
-TInt ProcessSmrImageMain(char* aObeyFileName, char* /* alogfile */) {
+TInt ProcessSmrImageMain(char* aObeyFileName, const char* /* alogfile */) {
 	ObeyFileReader *reader = new ObeyFileReader(aObeyFileName);
 	if(!reader)
 		return KErrNoMemory;
@@ -536,13 +536,12 @@
 			*(--ptr)++ = 0; 
 
 			if(*driveobeyFileName) {
-				char* logfile = 0;
-				if(Getlogfile(driveobeyFileName,logfile) == KErrNone) {
-					H.SetLogFile(logfile);
+				string logfile = Getlogfile(driveobeyFileName, cmdlogfile);
+				if(logfile.size() > 0) {
+					H.SetLogFile(logfile.c_str());
 					GetLocalTime();
-					r = ProcessDataDriveMain(driveobeyFileName,logfile);   
+					r = ProcessDataDriveMain(driveobeyFileName,logfile.c_str());   
 					H.CloseLogFile();
-					delete[] logfile;
 					if(r == KErrNoMemory)
 						return KErrNoMemory;
 				}
@@ -564,13 +563,12 @@
 			*(--ptr)++ = 0;
 
 			if(*smrImageObeyFileName){	
-				char * logfile = 0;
-				if(Getlogfile(smrImageObeyFileName,logfile) == KErrNone){
-					H.SetLogFile(logfile);
+				string logfile = Getlogfile(smrImageObeyFileName, cmdlogfile);
+				if(logfile.size() > 0) {
+					H.SetLogFile(logfile.c_str());
 					GetLocalTime();
-					r = ProcessSmrImageMain(smrImageObeyFileName, logfile);
+					r = ProcessSmrImageMain(smrImageObeyFileName, logfile.c_str());
 					H.CloseLogFile();
-					delete[] logfile;
 					if(r == KErrNoMemory)
 						return KErrNoMemory;
 				}
@@ -584,9 +582,9 @@
 	}
 	// Process Rofs Obey files.
 	if(obeyFileName) {
-		if (rofslogfile[rofslogfile.size()-1] == '\\' || rofslogfile[rofslogfile.size()-1] == '/')
-			rofslogfile += "ROFSBUILD.LOG";
-	 	H.SetLogFile(rofslogfile.c_str());
+		if (cmdlogfile[cmdlogfile.size()-1] == '\\' || cmdlogfile[cmdlogfile.size()-1] == '/')
+			cmdlogfile += "ROFSBUILD.LOG";
+	 	H.SetLogFile(cmdlogfile.c_str());
 		ObeyFileReader *reader = new ObeyFileReader(obeyFileName); 
 		if (!reader->Open())
 			return KErrGeneral;
--- a/imgtools/romtools/rombuild/r_obey.cpp	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rombuild/r_obey.cpp	Wed Oct 13 16:27:55 2010 +0800
@@ -296,7 +296,7 @@
 }
 TInt ObeyFileReader::NextLine(TInt aPass, enum EKeyword& aKeyword)
 	{
-
+	static int warnline = -1;
 NextLine:
 	TInt err = ReadAndParseLine();
 	if (err == KErrEof)
@@ -346,8 +346,10 @@
 		aKeyword = k->iKeywordEnum;
 		return KErrNone;
 	}
-	if (aPass == 1)
+	if (aPass == 1 && iCurrentLine > warnline){
+		warnline = iCurrentLine;
 		Print(EWarning, "Unknown keyword '%s'.  Line %d ignored\n", iWord[0], iCurrentLine);
+	}
 	goto NextLine;
 }
 
--- a/imgtools/romtools/rombuild/rombuild.cpp	Mon Sep 13 14:04:04 2010 +0100
+++ b/imgtools/romtools/rombuild/rombuild.cpp	Wed Oct 13 16:27:55 2010 +0800
@@ -33,7 +33,7 @@
 
 static const TInt RombuildMajorVersion=2;
 static const TInt RombuildMinorVersion=18;
-static const TInt RombuildPatchVersion=2;
+static const TInt RombuildPatchVersion=3;
 static TBool SizeSummary=EFalse;
 static TPrintType SizeWhere=EAlways;
 static string compareROMName = "";