# HG changeset patch # User Mike Kinghan # Date 1279375764 -3600 # Node ID d10c1f04b2be4e5332d220c0cb534215634ed3de # Parent 223dcf462b7314b57772b330a707e1fca5ce0fa2 Linux support for ROM building under Raptor diff -r 223dcf462b73 -r d10c1f04b2be imgtools/romtools/group/BLD.INF --- a/imgtools/romtools/group/BLD.INF Tue Jul 13 15:22:53 2010 +0100 +++ b/imgtools/romtools/group/BLD.INF Sat Jul 17 15:09:24 2010 +0100 @@ -33,6 +33,12 @@ ../rombuild/checkstubs.pl /epoc32/rom/tools/checkstubs.pl ../rombuild/addextension.pl /epoc32/rom/tools/addextension.pl +../rombuild/romnibus.pl /epoc32/rom/tools/romnibus.pl +../rombuild/Armutl.pm /epoc32/tools/Armutl.pm +../rombuild/BPABIutl.pm /epoc32/tools/BPABIutl.pm +../rombuild/E32Plat.pm /epoc32/tools/E32Plat.pm +../rombuild/E32Variant.pm /epoc32/tools/E32Variant.pm +../rombuild/GCCEV5.bsf /epoc32/tools/GCCEV5.bsf PRJ_MMPFILES readimage diff -r 223dcf462b73 -r d10c1f04b2be imgtools/romtools/rombuild/Armutl.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rombuild/Armutl.pm Sat Jul 17 15:09:24 2010 +0100 @@ -0,0 +1,180 @@ +# Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "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: +# this package does various ancillary things for armedg modules +# +# + +package Armutl; + +require Exporter; +@ISA=qw(Exporter); +@EXPORT=qw( + Armutl_Help_Mmp + + Armutl_DoMmp + + Armutl_ArmIncDir + Armutl_ArmLibList + Armutl_ArmRT + Armutl_AsmFileList + Armutl_ArmVersion + Armutl_RVCTMajorVersion + Armutl_RVCTMinorVersion + Armutl_RVCTPatchLevel + Armutl_RVCTBuildNumber + Armutl_ArmLibDir +); + +use RVCT_plat2set; + +my $ArmInc=''; +my @ArmLibList=(); +my $ArmRT=0; +my @AsmFileList=(); + +# make sure that some of the tool subroutines still work in case of Plat() does not exists in namespace main +my $Plat = main::Plat() if defined &main::Plat; + +my ($RVCTMajorVersion, $RVCTMinorVersion, $RVCTBuildNumber) = RVCT_plat2set::get_version_list($Plat); + +my $RVCTVersion = "$RVCTMajorVersion.$RVCTMinorVersion"; +my $RVCTPatchLevel = 0; + + +sub Armutl_Help_Mmp { +# provide the help text for START END blocks + + print + "ARMINC // include value of RVCT*INC environment variable to search paths\n", + "ARMLIBS // list the ARM supplied libraries to be linked against\n", + "ARMRT // indicates this target froms part of the runtime and so\n", + " // shouldn't be linked against itself or other runtime libs\n", + "ARMNAKEDASM // list .cpp files subject to auto-translation from GCC inline asm to ARM embedded asm\n" + ; +} + +sub Armutl_DoMmp (@) { # takes platform text + my @PlatTxt=@_; + + my $BaseTrg=&main::BaseTrg; + my $BasicTrgType=&main::BasicTrgType; + my $MakeFilePath=&main::MakeFilePath; + my $MMPFILE=&main::MmpFile; + my @UidList=&main::UidList; + + # set up START ARMV5|THUMB2 ... END block module variables + my @MmpWarn=(); + my $Line; + + LINE: foreach $Line (@PlatTxt) { + my $LineInfo=shift @$Line; + $_=shift @$Line; + if (/^ARMINC$/o) { + $ArmInc = RVCT_plat2set::get_inc_path($Plat); + next LINE; + } + if (/^ARMRT$/o) { + $ArmRT = 1; + next LINE; + } + if (/^ARMLIBS$/o) { + my $LibVar = "RVCT${RVCTMajorVersion}${RVCTMinorVersion}LIB"; + my $ArmLibDir = RVCT_plat2set::get_lib_path($Plat); + + push @MmpWarn, "$LineInfo : No libraries specified for keyword ARMLIBS\n" unless @$Line; + + while (@$Line) { + my $lib = shift @$Line; + + my $lib_path = RVCT_plat2set::find_lib( $Plat, $lib ); + + if ($lib_path) + { + push @ArmLibList, $lib_path; + } + else + { + push @MmpWarn, "$LineInfo : arm library file $lib not found.\n" ; + } + } + next LINE; + } + if (/^ARMNAKEDASM$/o) { + push @MmpWarn, "$LineInfo : No files specified for keyword ARMNAKEDASM\n" unless @$Line; + push @AsmFileList, @$Line; + next LINE; + } + push @MmpWarn, "$LineInfo : Unrecognised Keyword \"$_\"\n"; + } + + undef $Line; + if (@MmpWarn) { + warn + "\nMMPFILE \"$MMPFILE\"\n", + "START .. END BLOCK WARNINGS(S)\n", + @MmpWarn, + "\n" + ; + } + undef @MmpWarn; + } + +sub Armutl_ArmIncDir() { + $ArmInc; +} + +sub Armutl_ArmLibList() { + @ArmLibList; +} + +sub Armutl_ArmRT() { + $ArmRT; +} + +sub Armutl_AsmFileList() { + @AsmFileList; +} + +sub Armutl_ArmVersion() { + return $RVCTVersion; +} + +sub Armutl_RVCTMajorVersion() { + return $RVCTMajorVersion; +} + +sub Armutl_RVCTMinorVersion() { + return $RVCTMinorVersion; +} + +sub Armutl_RVCTPatchLevel() { + return $RVCTPatchLevel; +} + +sub Armutl_RVCTBuildNumber() { + return $RVCTBuildNumber; +} + +sub Armutl_ArmLibDir() { + my $LibVar = "RVCT${RVCTMajorVersion}${RVCTMinorVersion}LIB"; + my $ArmLibDir = $ENV{$LibVar}; + return $ArmLibDir; +} + +1; + + + + + diff -r 223dcf462b73 -r d10c1f04b2be imgtools/romtools/rombuild/BPABIutl.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rombuild/BPABIutl.pm Sat Jul 17 15:09:24 2010 +0100 @@ -0,0 +1,141 @@ +# Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "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: +# This package does various ancillary things for BPABI (Base Platform ABI) platforms +# +# + +package BPABIutl; + +require Exporter; +@ISA=qw(Exporter); +@EXPORT=qw( + BPABIutl_Plat_List + BPABIutl_Config_Path + BPABIutl_Get_Config_Variables +); + +use E32Variant; +require E32Plat; + +my %ConfigPath; +my $variantABIV2Keyword = &Variant_GetMacro(); + +sub BPABIutl_Plat_List { + +# Identify the BPABI platforms to be supported based on the compiler configuration files +# present in the location specified by the environment variable "SYMBIAN_COMPILATION_CONFIG_DIR" +# and in the directory $EPOCROOT\epoc32\tools\compilation_config + + my @CompilerConfigPath; + + if (exists($ENV{'SYMBIAN_COMPILATION_CONFIG_DIR'})) + { + my $Path = $ENV{SYMBIAN_COMPILATION_CONFIG_DIR}; + @CompilerConfigPath = split(/;/, $Path); + } + + push @CompilerConfigPath, "$ENV{EPOCROOT}epoc32\\tools\\compilation_config"; + + my $ConfigDir; + my @BPABIPlats = (); + + foreach $ConfigDir (@CompilerConfigPath) + { + opendir DIR, "$ConfigDir"; + my @Plats=grep /\.mk$/i, readdir DIR; + my $Plat; + foreach $Plat (@Plats) + { +# The platform name will be same as the name of the configuration file +# with the suffix '.mk' removed + $Plat =~ s/\.mk//; + if ($variantABIV2Keyword) { + if ($Plat =~ /^armv5_abiv2$/i) { + $Plat = "ARMV5"; + } + } + else { + if ($Plat =~ /^armv5$/i) { + $Plat = "ARMV5_ABIV2"; + } + } + unless (grep /$Plat$/i, @BPABIPlats) { + $Plat = uc $Plat; + push @BPABIPlats, $Plat; + if (!$variantABIV2Keyword && $Plat =~ /^ARMV5_ABIV2$/i) { + $ConfigPath{$Plat} = "$ConfigDir\\ARMV5.mk"; + } + else { + $ConfigPath{$Plat} = "$ConfigDir\\$Plat.mk"; + } + } + } + } + closedir DIR; + return @BPABIPlats; +} + +sub BPABIutl_Config_Path($) { + my ($plat) = @_; +# Returns the Path of the compiler configuration file + if (!keys(%ConfigPath)) + { + # Running for first time so initialise ConfigPath + BPABIutl_Plat_List(); + } + if (!$ConfigPath{$plat}) + { + # Get the root platform name to support hierarchy of customizations + my $CustomizedPlat = &E32Plat::Plat_Root($plat); + +# In default ABIV1 mode, the platform name for v2 mode of ARMV5 is ARMV5_ABIV2 + if ( !$variantABIV2Keyword && $CustomizedPlat =~ /^ARMV5$/i ){ + $ConfigPath{$plat} = $ConfigPath{ARMV5_ABIV2}; + } + +# In default ABIV2 mode, the platform name for v2 mode of ARMV5 is ARMV5 + elsif ( $variantABIV2Keyword && $CustomizedPlat =~ /^ARMV5$/i) { + $ConfigPath{$plat} = $ConfigPath{ARMV5}; + } + else{ + $ConfigPath{$plat}=$ConfigPath{$CustomizedPlat}; + } + } + return "$ConfigPath{$plat}"; +} + +# routine to extract a set of variables from the compilation configuration +# file. The variables extracted are determined by the extractvars.make file. +# The variables are returned in a hash. +sub BPABIutl_Get_Config_Variables +{ + my ($plat) = @_; + my $configfile = BPABIutl_Config_Path($plat); + my $extractvars = "$ENV{EPOCROOT}epoc32\\tools\\compilation_config\\extractvars.make"; + my $command = "make CONFIG_FILE=$configfile -s -f $extractvars" ; + my $result = `$command`; + my %vars; + my @lines = split('\n', $result); + foreach my $line (@lines) + { + chomp $line; + if ($line =~ /(\w+)=(.*)/) + { + $vars{$1} = $2; + } + } + return %vars; +} + +1; diff -r 223dcf462b73 -r d10c1f04b2be imgtools/romtools/rombuild/E32Plat.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rombuild/E32Plat.pm Sat Jul 17 15:09:24 2010 +0100 @@ -0,0 +1,878 @@ +# Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "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: +# Module providing platform details for platforms supported +# by Symbian OS +# all data is uppercase +# +# + +package E32Plat; + +require Exporter; +@ISA=qw(Exporter); + +@EXPORT=qw( + Plat_SetVerbose + Plat_Init + Plat_GetL + Plat_List + Plat_AssocIDE + Plat_Customizations + Plat_Customizes + Plat_Root + Plat_SupportsFeatureVariants +); + +use BPABIutl; +use E32Variant; + +my $variantABIV2Keyword = &Variant_GetMacro(); + +my %Mode=( + Verbose=>0 +); +my $ModulePath; + +sub Plat_SetVerbose () { + $Mode{Verbose}=1; +} + +my %BldLists=( + EPOC32=>['UREL','UDEB'], + WINS=>['UDEB','UREL'], + TOOLS=>['DEB','REL'], + TOOLS2=>['DEB','REL'], +); + +my %BldMacros=( + DEB=>['_DEBUG'], + REL=>['NDEBUG'], + UDEB=>['_DEBUG','_UNICODE'], + UREL=>['NDEBUG','_UNICODE'] +); + + +my @EpocMacros=('__SYMBIAN32__'); + +my @BPABIPlats = &BPABIutl_Plat_List; + +my %Plat=( + ARM4=>{ + ABI=>'ARM4', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + }, + ARM4SMP=>{ + ABI=>'ARM4', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + SMP=>1, + StatLink=>'ARM4SMP', + }, + ARM4T=>{ + ABI=>'ARM4T', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + }, + ARMI=>{ + ASSP=>'MARM', + Generic=>1, + ASSPABI=>'', + }, + SARM4=>{ + ABI=>'ARM4', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + Single=>1, + }, + SARMI=>{ + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + Single=>1, + }, + STHUMB=>{ + ABI=>'THUMB', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + Single=>1, + }, + THUMB=>{ + ABI=>'THUMB', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + }, + TOOLS=>{ + ABI=>'TOOLS', + ASSPABI=>'', + Compiler=>'VC32', + CPU=>'TOOLS', + OS=>'TOOLS', + MakeMod=>'Cl_win', + MakeCmd=>'nmake', + }, + TOOLS2=>{ + ABI=>'TOOLS2', + ASSPABI=>'', + Compiler=>'GCC32', + CPU=>'TOOLS2', + OS=>'TOOLS2', + MakeMod=>'Cl_mingw', + MakeCmd=>'make', + }, + CWTOOLS=>{ + ABI=>'TOOLS', + ASSPABI=>'', + Compiler=>'CW32', + CPU=>'TOOLS', + OS=>'TOOLS', + MakeMod=>'Cl_tools', + MakeCmd=>'make', + }, + VC6TOOLS=>{ + ABI=>'TOOLS', + ASSPABI=>'', + Compiler=>'VC32', + CPU=>'TOOLS', + Ext=>'.DSP', + MakeMod=>'Ide_vc6', + MakeCmd=>'nmake', + OS=>'TOOLS', + Real=>'TOOLS', + UsrHdrsOnly=>1, + }, + WINS=>{ + ABI=>'WINS', + ASSPABI=>'', + Compiler=>'VC32', + CPU=>'WINS', + MakeMod=>'Cl_win', + MakeCmd=>'nmake', + OS=>'WINS', + }, + VC6=>{ + ABI=>'WINS', + ASSPABI=>'', + Compiler=>'VC32', + CPU=>'WINS', + Ext=>'.DSP', + MakeMod=>'Ide_vc6', + MakeCmd=>'nmake', + OS=>'WINS', + Real=>'WINS', + UsrHdrsOnly=>1, + }, + WINSCW=>{ + ABI=>'WINSCW', + ASSPABI=>'', + Compiler=>'CW32', + CPU=>'WINS', + MakeMod=>'Cl_codewarrior', + OS=>'WINS', + DefFile=>'WINS', # use the MSVC def files + }, + CW_IDE=>{ + ABI=>'WINSCW', + ASSPABI=>'', + Compiler=>'CW32', + CPU=>'WINS', + Ext=>'.xml', + MakeMod=>'Ide_cw', + MakeCmd=>'make', + OS=>'WINS', + Real=>'WINSCW', + DefFile=>'WINS', # use the MSVC def files + UsrHdrsOnly=>1, + SupportsMultiplePlatforms=>1, # supports more than one real platform + }, + X86=>{ + ABI=>'X86', + ASSPABI=>'', + Compiler=>'VC32', + CPU=>'X86', + MakeMod=>'Cl_x86', + MakeCmd=>'nmake', + OS=>'EPOC32', + DefFile=>'X86', + Generic=>1, + }, + X86SMP=>{ + ABI=>'X86', + ASSPABI=>'', + Compiler=>'VC32', + CPU=>'X86', + MakeMod=>'Cl_x86', + MakeCmd=>'nmake', + OS=>'EPOC32', + DefFile=>'X86', + Generic=>1, + SMP=>1, + StatLink=>'X86SMP', + }, + X86GCC=>{ + ABI=>'X86gcc', + ASSPABI=>'', + Compiler=>'X86GCC', + CPU=>'X86', + MakeMod=>'Cl_x86gcc', + OS=>'EPOC32', + DefFile=>'x86gcc', + Generic=>1, + }, + X86GMP=>{ + ABI=>'X86gcc', + ASSPABI=>'', + Compiler=>'X86GCC', + CPU=>'X86', + MakeMod=>'Cl_x86gcc', + OS=>'EPOC32', + DefFile=>'x86gcc', + Generic=>1, + SMP=>1, + StatLink=>'X86GMP', + }, + ARMV4=>{ + ABI=>'ARMV4', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + MakeMod=>'Cl_arm', + Compiler=>'ARMCC', + DefFile=>'EABI', + EABI=>1, + }, + ARMV4SMP=>{ + ABI=>'ARMV4', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + MakeMod=>'Cl_arm', + Compiler=>'ARMCC', + DefFile=>'EABI', + EABI=>1, + SMP=>1, + StatLink=>'ARMV4SMP', + }, + ARMV5_ABIV1=>{ + ABI=>'ARMV5', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + MakeMod=>'Cl_arm', + Compiler=>'ARMCC', + DefFile=>'EABI', + EABI=>1, + SupportsFeatureVariants=>1, + }, + ABIV2=>{ + ABI=>'ARMV5', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + MakeMod=>'Cl_bpabi', + DefFile=>'EABI', + EABI=>1, + SupportsFeatureVariants=>1, + }, + GCCXML=>{ + ABI=>'ARM4', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + MakeMod=>'cl_gccxml', + }, + VS6=>{ + ABI=>'WINSCW', + ASSPABI=>'', + Compiler=>'CW32', + CPU=>'WINS', + MakeMod=>'Cl_vscw', + OS=>'WINS', + Real=>'WINSCW', + DefFile=>'WINS', # use the MSVC def files + Ext=>'.mak' + }, + VS2003=>{ + ABI=>'WINSCW', + ASSPABI=>'', + Compiler=>'CW32', + CPU=>'WINS', + MakeMod=>'Cl_vscw', + OS=>'WINS', + Real=>'WINSCW', + DefFile=>'WINS', # use the MSVC def files + Ext=>'.mak' + }, + EDG=>{ + ABI=>'ARMV5', + ASSP=>'MARM', + ASSPABI=>'', + Generic=>1, + MakeMod=>'cl_edg', + }, + + # ASSP platforms should be described using .ASSP files + # Do not add additional ASSP platforms to this file. +); + +sub Set_Plat() +{ + @BPABIPlats = &BPABIutl_Plat_List; + foreach my $Candidate (@BPABIPlats) + { +# All BPABI platforms inherit from ABIV2 properties as listed in the platlist +# and Platlist is updated to include the BPABI platforms. + my ( $key, $value); + while (($key, $value) = each %{$Plat{ABIV2}}) { + $Plat{$Candidate}{$key}=$value; + } + } +} + +sub Plat_SupportsFeatureVariants($) + { + my ($plat) = @_; + + # In a non-ABIV2 world, ARMV5 means ARMV5_ABIV1 within e32plat content + if (!$variantABIV2Keyword && $plat =~ /^ARMV5$/i) + { + $plat .= "_ABIV1"; + } + + return ($plat && defined $Plat{$plat}{SupportsFeatureVariants}) ? $Plat{$plat}{SupportsFeatureVariants} : 0; + } + +sub Plat_Customizations($) { + my ($plat) = @_; + my @empty = (); + return @{$Plat{$plat}{'CUSTOMIZATIONS'}} if $Plat{$plat}{'CUSTOMIZATIONS'}; + return @empty; + } + +sub Plat_Customizes($) { + my ($plat) = @_; + return $Plat{$plat}{'CUSTOMIZES'} ? $Plat{$plat}{'CUSTOMIZES'} : ""; +} + +sub Plat_Root($) { + my ($plat) = @_; + + my $RootName = $Plat{$plat}{'ROOTPLATNAME'}; + + if ($RootName) { + return $RootName; + } + else { + # A non-BSF platform is its own root. + return $plat; + } +} + +sub Init_BSFs($) { + my ($Path)=@_; +# get a list of modules + opendir DIR, $Path; + my @BSFs=grep s/^([^\.].*)\.BSF$/$1/, map { uc $_ } sort readdir DIR; + closedir DIR; + + my $BSF; + foreach $BSF (@BSFs) { + my $File=$Path.$BSF.'.bsf'; +# check whether the assp is already defined + if (defined %{$Plat{$BSF}}) { + warn( + "$File : warning: Platform \"$BSF\" already defined\n", + " ... skipping this spec\n" + ); + delete $Plat{$BSF}; + next; + } +# open the module + unless (open FILE, $File) { + delete $Plat{$BSF}; + warn "warning: Can't open BSF specification \"$File\"\n"; + next; + } + my $line1 = ; + $line1 = uc($line1); + unless ($line1 =~ /^\#\\#/) { + warn "warning: \"$File\" Invalid BSF specification - missing ##\n"; + delete $Plat{$BSF}; + close FILE; + next; + } + my $custom; + while ($custom = ) { + #skip blank lines and comments + delete $Plat{$BSF}; + last unless ($custom =~ /^$|^\#/); + } + $custom = uc $custom; + unless ($custom =~ /^\s*CUSTOMIZES\s+(\S+)/) { + warn "warning: \"$File\" Invalid BSF specification - 'customizes' missing\n"; + delete $Plat{$BSF}; + close FILE; + next; + } + my $root = $1; + my $platname = ''; + my $CustomizedPlatName = ''; + + # In v1 mode, ARMV5 platform implies ARMV5_ABIV1 platform listed in the platlist + my $Armv5Flag = 0; + if (!$variantABIV2Keyword && $root =~ /^ARMV5$/i) { + $Armv5Flag = 1; + } + + # Support for Hierarchy of Customizations (BSF file customization of another BSF file) + # 1. Check whether the BSF file customizes another BSF file. + # 2. If so, check whether the root BSF file has already been read. + # 3. If not read, then defer the current BSF file reading until the root file is read. + my $rootPlatFound = 0; + if (defined %{$Plat{$root}} || $Armv5Flag) + { + # BSF platform customizes another valid BSF platform + if (defined $Plat{$root}{'CUSTOMIZES'}) + { + $rootPlatFound = 1; + $platname = $root; + $CustomizedPlatName = $root; + + # Set the root platform name which is same as of customizes platform + $Plat{$BSF}{'ROOTPLATNAME'} = $Plat{$root}{'ROOTPLATNAME'}; + } + # BSF platform customizes to one of the existing ABI platforms + else + { + # All BPABI platforms inherits from ABIV2 platform listed in the platlist + if (grep /^$root$/i, @BPABIPlats) { + $platname = "ABIV2"; + } + elsif ($Armv5Flag) { + # In v1 mode, ARMV5 platform implies ARMV5_ABIV1 platform listed in the platlist + $platname = "ARMV5_ABIV1"; + } + else { + $platname = $root; + } + + $CustomizedPlatName=$root; + + # BSF File check Begins + # The following check is included to handle the existing BSF files which has to behave in different manner + # in default v1 mode and v2 mode. The following code changes the BSF name and the custmoized platform name + # to the implied names. This is done to support switching between v1 and v2 modes by enabling the keyword in + # the variant configuration file. + # In v1 mode, the ARMV6_ABIV1 => ARMV6 platform and ARMV6 => ARMV6_ABIV2 platform. + if (!$variantABIV2Keyword) { + if ($BSF =~ /^ARMV6_ABIV1$/i) { + $BSF = "ARMV6"; + $CustomizedPlatName = "ARMV5"; + } + elsif ($BSF =~ /^ARMV6$/i) { + $BSF = "ARMV6_ABIV2"; + $CustomizedPlatName = "ARMV5_ABIV2"; + $platname = "ABIV2"; + } + } + # BSF File check Ends + + # Set the root platform name + $Plat{$BSF}{'ROOTPLATNAME'} = $CustomizedPlatName; + } + } + else + { + my $rootbsf = $Path.$root.".bsf"; + if ( -e $rootbsf ) { + # BSF file customizes another BSF file which has not been read yet. + # So defer current BSF file reading until the root BSF file is read. + delete $Plat{$BSF}; + push(@BSFs, $BSF); + next; + } + } + # If the customizes platform is not a valid BSF platform or BPABI platorm or ARMV5 or ARMV5_ABIV1, + # then throw warning. + unless ($rootPlatFound || $root =~ /^ARMV5(_ABIV1)?$/ || (grep /^$root$/i, @BPABIPlats)) { + warn "warning: \"$File\" Invalid BSF specification - customization restricted to ARMV5, ABIv2 and valid BSF platforms\n"; + close FILE; + delete $Plat{$BSF}; + next; + } + + my ( $key, $value); + while (($key, $value) = each %{$Plat{$platname}}) { + $Plat{$BSF}{$key}=$value; + } + + push @{$Plat{$CustomizedPlatName}{'CUSTOMIZATIONS'}}, $BSF; + $Plat{$BSF}{'CUSTOMIZES'} = $CustomizedPlatName; + while () { + next if (/^$|^\#/); + if (/^\s*SMP\s*$/i) { + $Plat{$BSF}{'SMP'} = 1; + $Plat{$BSF}{'StatLink'} = lc $BSF; + next; + } + $Plat{$BSF}{'CUSTOMIZATION_DATA'} .= $_; + } + # BSF file statements will have newline character("\n") at the end, except for the last statement. + # So append "\n" for the last BSF file statement. + # "\n" will be used to split BSF statements to support hierarchy of customizations. + $Plat{$BSF}{'CUSTOMIZATION_DATA'} .= "\n"; + close FILE; + } + 1; +} + +sub Plat_Init ($) { # takes path to ASSP modules + my ($Path)=@_; + + my %PlatHashKeys=( + ABI=>1, + ASSPABI=>1, + SINGLE=>1, + Compiler=>1, + CPU=>1, + MakeMod=>1, + MakeCmd=>1, + OS=>1, + DefFile=>1, + ASSP=>1, + ); + +# Include the list of BPABI platforms + &Set_Plat; + + Init_BSFs($Path); + +# get a list of modules + opendir DIR, $Path; + my @_ASSPs=grep s/^([^\.].*)\.ASSP$/$1/, map { uc $_ } readdir DIR; + closedir DIR; + + my @ASSPs; + foreach (@_ASSPs) { + if (!$ENV{USEARMCC} and /EDG$/i) { +# warn( +# "Note: ASSP \"$_\" disabled\n" +# ); + + next; + } + push @ASSPs, $_; + } + +# open each module in turn, and add it to the array + my $ASSP; + foreach $ASSP (@ASSPs) { + my $File=$Path.$ASSP.'.assp'; +# check whether the assp is already defined + if (defined %{$Plat{$ASSP}}) { + warn( + "$File : warning: ASSP \"$ASSP\" already defined\n", + " ... skipping this module\n" + ); + + next; + } +# open the module + unless (open FILE, $File) { + warn "warning: Can't open assp module \"$File\"\n"; + next; + } + my %Data=(); + my %SingleData=(); + my $MatchingSingle=""; + my @Errors=(); + while () { +# strip comments + s/^([^#]*)#.*$/$1/o; +# skip blank lines + if (/^\s*$/o) { + next; + } +# get the key-value pair + unless (/^\s*(\w+)\s+(\w+)\s*$/o) { + push @Errors, "$File($.) : warning: syntax error - only key-value pairs allowed\n"; + next; + } + my ($Key, $Val)=($1, $2); + if ($PlatHashKeys{$Key}!=1) { + push @Errors, "$File($.) : warning: unrecognized keyword - $Key\n"; + next; + } + if ($Key eq "SINGLE") { + $SingleData{Single} = 1; + $SingleData{ASSP} = $ASSP; + $MatchingSingle = uc $2; + } else { + $Data{$Key}=$Val; + $SingleData{$Key}=$Val; + } + } + close FILE; + if (@Errors) { + warn( + @Errors, + " ... skipping this module\n" + ); + next; + } +# change - Allow ASSPs to pick up all the options of the ABI they specify, +# in particular the compiler they need. + $Data{'ASSP'} = $ASSP unless $Data{'ASSP'}; + if ($Plat{$Data{'ABI'}}) { + foreach (keys %{$Plat{$Data{'ABI'}}}) { + $Data{$_} = $Plat{$Data{'ABI'}}{$_} unless ($_ =~ /^GENERIC$/i) or $Data{$_}; + } + } + + %{$Plat{$ASSP}}=%Data; + if ($MatchingSingle ne "") { + foreach (keys %Data) { + $SingleData{$_} = $Data{$_} unless ($_ =~ /^GENERIC$/i) or $SingleData{$_}; + } + %{$Plat{$MatchingSingle}}=%SingleData; + } + } +} + +sub Plat_GetL ($$$$) { # takes Platform name, ref to plat hash, ref to bldmacrohash, bldmake plat command notifier + my ($Candidate,$PlatHash_ref,$BldMacrosHash_ref,$platcommand)=@_; + $Candidate=uc $Candidate; + +# is platform in our list? + unless (defined $Plat{$Candidate}) { + + # is platform BPABI compliant one? + if (!$variantABIV2Keyword && $Candidate eq 'ARMV5') { + } + elsif (not(grep /^$Candidate$/i, @BPABIPlats)) + { + die "ERROR: Platform \"$Candidate\" not supported\n"; + } + } + + my $BPABIPlat; + my %PlatHash=(); + +# check the data +# All BPABI platforms inherit ABIV2 properties + if (grep /^$Candidate$/i, @BPABIPlats) + { + $BPABIPlat='ABIV2'; + %PlatHash=%{$Plat{$BPABIPlat}}; + } +# In v1 mode, ARMV5 platform implies ARMV5_ABIV1 platform listed in the platlist + elsif (!$variantABIV2Keyword && $Candidate eq 'ARMV5') { + %PlatHash=%{$Plat{ARMV5_ABIV1}}; + } + else { + %PlatHash=%{$Plat{$Candidate}}; + } + +# set the defaults + $PlatHash{Name}=$Candidate; + $PlatHash{Real}=$PlatHash{Name} unless $PlatHash{Real}; + $PlatHash{Ext}=".$PlatHash{Real}" unless $PlatHash{Ext}; + $PlatHash{ASSP}=$PlatHash{Real} unless $PlatHash{ASSP}; + +# Get the root platform name to support hierarchy of customizations + my $CustomizedPlat=$PlatHash{'ROOTPLATNAME'}; + + if ((defined($Candidate) && ($Candidate =~ /^ARMV5/i)) || (defined($CustomizedPlat) && ($CustomizedPlat =~ /^ARMV5/i))) { +# Compiler name should be set as ARMCC for all ARMV5 platforms + $PlatHash{Compiler}='ARMCC'; + $PlatHash{Toolchain}='rvct22'; + } + elsif ($BPABIPlat) { +# Compiler name should be set as that of platform name for all BPABI platforms + $PlatHash{Compiler}=$Candidate; + $PlatHash{Toolchain}=$Candidate; + } + elsif ($CustomizedPlat) { +# Compiler name should be set as that of the customized platform name incase of customization + $PlatHash{Compiler}=$CustomizedPlat; + $PlatHash{Toolchain}=$CustomizedPlat; + } + + $PlatHash{Compiler}='GCC32' unless $PlatHash{Compiler}; + $PlatHash{OS}='EPOC32' unless $PlatHash{OS}; + $PlatHash{MakeMod}='Cl_gcc' unless $PlatHash{MakeMod}; + $PlatHash{MakeCmd}='make' unless $PlatHash{MakeCmd}; + $PlatHash{CPU}='MARM' unless $PlatHash{CPU}; + $PlatHash{Single}=0 unless $PlatHash{Single}; + $PlatHash{UsrHdrsOnly}=0 unless $PlatHash{UsrHdrsOnly}; + $PlatHash{Generic}=0 unless $PlatHash{Generic}; # generic means "for a target device but no particular ASSP" + $PlatHash{SupportsMultiplePlatforms}=0 unless $PlatHash{SupportsMultiplePlatforms}; + + $PlatHash{ABI}='ARMI' unless $PlatHash{ABI}; + $PlatHash{ASSPABI}='ARM4' unless defined $PlatHash{ASSPABI}; + + unless (defined $PlatHash{DefFile}) { + if ($PlatHash{Compiler} eq 'VC32') { + $PlatHash{DefFile}='WINS'; + } else { + $PlatHash{DefFile}='MARM'; + } + } + +# .MMP macros - keeping the order is useful + @{$PlatHash{MmpMacros}}=$PlatHash{Compiler}; + push @{$PlatHash{MmpMacros}}, $PlatHash{OS}; + push @{$PlatHash{MmpMacros}}, $PlatHash{CPU} unless $PlatHash{CPU} eq $PlatHash{OS}; + push @{$PlatHash{MmpMacros}}, $PlatHash{ASSP} unless $PlatHash{ASSP}=~/^($PlatHash{CPU}|$PlatHash{OS})$/; + + if ($PlatHash{Single}) { + push @{$PlatHash{MmpMacros}}, 'SINGLE'; + } + if ($PlatHash{SMP}) { + push @{$PlatHash{MmpMacros}}, 'SMP'; + } + if ($PlatHash{EABI}) { + push @{$PlatHash{MmpMacros}}, 'EABI'; + } + if ($PlatHash{Compiler} eq 'VC32') { + my $MSVCVer = &Winutl_MSVCVer($platcommand); + my $MSVCSubVer = &Winutl_MSVCSubVer($platcommand); + push @{$PlatHash{MmpMacros}}, 'MSVC'.$MSVCVer; + push @{$PlatHash{MmpMacros}}, 'MSVC'.$MSVCVer.$MSVCSubVer; + if ($MSVCVer > 6) { + push @{$PlatHash{MmpMacros}}, 'MSVCDOTNET'; + } + } + if ($PlatHash{Compiler} eq 'ARMCC') { + my ($MajVer, $MinVer) = RVCT_plat2set::get_version_list($Candidate); + push @{$PlatHash{MmpMacros}}, 'ARMCC_'.$MajVer; + push @{$PlatHash{MmpMacros}}, 'ARMCC_'.$MajVer.'_'.$MinVer; + } + + if ($PlatHash{Compiler} eq 'X86GCC') { + push @{$PlatHash{MmpMacros}}, 'GCC32'; + } + + ## TOOLS2 Specific Macros ## + + if ($PlatHash{Compiler} eq 'GCC32') { + push @{$PlatHash{MmpMacros}}, 'MINGW32'; + push @{$PlatHash{MmpMacros}}, '_STLP_LITTLE_ENDIAN'; + + } + + # add GCCXML to the mmp macro list, so we can filter out stuff in bld.inf files and mmps. + # note that this mean that __GCCXML__ is automacally routed to makefile, so we can take out explicit call. + if( $PlatHash{Name} eq "GCCXML") { + push @{$PlatHash{MmpMacros}}, 'GCCXML'; + } + +# add specific platform macros for platforms customising others. + if (Plat_Customizes($PlatHash{Name})) { + push @{$PlatHash{MmpMacros}}, $PlatHash{Name} unless grep /$PlatHash{Name}/, @{$PlatHash{MmpMacros}}; + } + +# compilation macros + @{$PlatHash{Macros}}=@EpocMacros; + foreach (@{$PlatHash{MmpMacros}}) { + ## If STLP_LTTLE_ENDIAN is used, then dont append __ to the macro name ## + if ($_ =~ m/STLP_LITTLE_ENDIAN/) { + push @{$PlatHash{Macros}}, $_; + } else { + push @{$PlatHash{Macros}}, '__'.$_.'__'; + } + } + +# extra special .MMP macros which aren't applied for compilation + if ($PlatHash{Generic}) { + push @{$PlatHash{MmpMacros}}, "GENERIC_$PlatHash{CPU}"; + if ($PlatHash{CPU} eq 'MARM') { +# we can't define this for ASSP platforms because we won't be sure what +# the ABI is until we've processed the .MMP file + push @{$PlatHash{MmpMacros}}, "MARM_$PlatHash{ABI}"; + } + } + +# builds + @{$PlatHash{Blds}}=@{$BldLists{$PlatHash{OS}}}; + +# output some information + if ($Mode{Verbose}) { + print + "Platform $PlatHash{Name}\n", + "Real Name $PlatHash{Real}\n", + "Compiler $PlatHash{Compiler}\n", + "OS $PlatHash{OS}\n", + "CPU $PlatHash{CPU}\n", + "ASSP $PlatHash{ASSP}\n", + "ABI $PlatHash{ABI}\n", + "ASSPABI $PlatHash{ASSPABI}\n", + "Makefile Module $PlatHash{MakeMod}\n", + "Makefile Type $PlatHash{MakeCmd}\n", + "MMP Macros @{$PlatHash{MmpMacros}}\n", + "Macros @{$PlatHash{Macros}}\n", + "Blds @{$PlatHash{Blds}}\n" + ; + } + + %{$PlatHash_ref}=%PlatHash; + %{$BldMacrosHash_ref}=%BldMacros; +} + +sub Plat_List () { + +# Include the list of BPABI platforms + &Set_Plat; + +# return list of supported platforms + + #sort keys %Plat; + my @PlatList; + my $Key; + foreach $Key (keys %Plat) { + if (!$variantABIV2Keyword && $Key =~ /^armv5_abiv1$/i) { + $Key = 'ARMV5'; + } + unless (grep /^$Key$/i, @PlatList) { + push @PlatList, $Key; + } + } + return @PlatList +} + +sub Plat_AssocIDE ($$) { +# return the IDE associated with a "Real" platform if there is one + my ($Candidate, $AssocIDEs)=@_; + + unless (defined $Plat{$Candidate}) { + die "ERROR: Platform \"$Candidate\" not supported\n"; + } + + my $Key; + foreach $Key (keys %Plat) { + if (${Plat{$Key}}{Real}) { + if (${Plat{$Key}}{Real} eq $Candidate) { + push @$AssocIDEs, $Key; + } + } + } +} + +1; diff -r 223dcf462b73 -r d10c1f04b2be imgtools/romtools/rombuild/E32Variant.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rombuild/E32Variant.pm Sat Jul 17 15:09:24 2010 +0100 @@ -0,0 +1,156 @@ +# Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "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: +# + +package E32Variant; + +require Exporter; + +@ISA = qw(Exporter); + +@EXPORT = qw(Variant_GetMacroList Variant_GetMacroHRHFile Variant_GetMacro); + +use Pathutl; + +# using $FindBin::Bin to figure out the location of the epoc32\tools directory as +# IDE doesn't understand env{EPOCROOT} + +my $PerlBinPath; # fully qualified pathname of the directory containing this script + +BEGIN { + require 5.005_03; # check user has a version of perl that will cope + $PerlBinPath = $FindBin::Bin; # X:/epoc32/tools + $PerlBinPath =~ s/\//\\/g; # X:\epoc32\tools +} + +# get epocroot if it is set +my $epocroot = $ENV{EPOCROOT}; +my $toolspath; + +#if epocroot is not set figure it out +if(!$epocroot){ + $epocroot = $PerlBinPath . "\\..\\..\\" ; #infer epocroot + $toolspath = $PerlBinPath; +}else{ + $toolspath = $epocroot . "epoc32\\tools\\"; +} + +$epocroot=~s/^(.:)//io; # remove drive letter +$epocroot=&Path_Strip($epocroot); # collapse + +my $cfgFile = $toolspath . "variant\\variant.cfg"; # default location +$cfgFile =~ /^(.:)/i; # match the drive +my $MacroHRHLocation_Drive = lc($1); # save the drive + +sub Variant_GetMacroHRHFile{ + my $file; + if(-e $cfgFile){ + open(FILE, $cfgFile) || die "\nCould not open: " . $cfgFile ."\n"; + while () { + # strip comments + s/^([^#]*)#.*$/$1/o; + # skip blank lines + if (/^\s*$/o) { + next; + } + # get the hrh file + if($_ =~ /\.hrh/xi){ + $file = $_; + last; + } + } + close FILE; + die "\nERROR: No variant file specified in $cfgFile!\n" unless $file; + $file =~ s/\s+//g; + $file=~s/^(.:)//io; # remove drive letter + my $paths_drive = lc($1); + + $file = Path_MakeEAbs($epocroot."EPOC32\\", $epocroot, $file); # assume relative to EPOCROOT + + if($paths_drive){ + die "\nERROR: Variant file specified in $cfgFile is not on the same drive as \\epoc32\\\n" + unless ($paths_drive eq $MacroHRHLocation_Drive); + } + if(!(-e $file)) { + die "\nERROR: $cfgFile specifies $file which doesn't exist!\n"; + } + + # make sure it is in dos syntax + $file=~ s/\//\\/g; + } + return $file; +} + + +# returns the variant specific macro definitions as a list +sub Variant_GetMacroList{ + + my @macros = (); + my $vfile = Variant_GetMacroHRHFile(); + + if($vfile) + { + my $VariantFilePath = Path_Split('Path',$vfile); + chop( $VariantFilePath ); + $VariantFilePath = &Path_PrefixWithDriveAndQuote($VariantFilePath); + $vfile = &Path_PrefixWithDriveAndQuote($vfile); + my $e32Path = &Path_PrefixWithDriveAndQuote($epocroot."epoc32\\include"); + + open CPPPIPE,"cpp -I $e32Path -I $VariantFilePath -undef -dM $vfile |" or die "ERROR: Can't invoke CPP.EXE\n"; + while(){ + if($_ =~ /(\#define)(\s+)(.+)/){ + push @macros, $3; + } + } + close CPPPIPE; + } + return @macros; +} + +sub Variant_GetMacro{ + + my $file; + if(-e $cfgFile){ + open(FILE, $cfgFile) || die "\nCould not open: " . $cfgFile ."\n"; + while () { + # strip comments + s/^([^#]*)#.*$/$1/o; + # skip blank lines + if (/^\s*$/o) { + next; + } + # get the hrh file + if($_ =~ /^ENABLE_ABIV2_MODE$/xi){ + close FILE; + return 1; + } + } + close FILE; + } + return 0; +} + +1; + + + + + + + + + + + + diff -r 223dcf462b73 -r d10c1f04b2be imgtools/romtools/rombuild/GCCEV5.bsf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rombuild/GCCEV5.bsf Sat Jul 17 15:09:24 2010 +0100 @@ -0,0 +1,20 @@ +## +# 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 "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: +# This BSF file is to support building for the ARMV6 architecture. + +CUSTOMIZES GCCE + +INVARIANT_OPTIONS -march=armv5 -mapcs -mthumb-interwork + diff -r 223dcf462b73 -r d10c1f04b2be imgtools/romtools/rombuild/romnibus.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/romtools/rombuild/romnibus.pl Sat Jul 17 15:09:24 2010 +0100 @@ -0,0 +1,1052 @@ +#!/usr/bin/perl +# +# Copyright (c) 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: +# Mike Kinghan, mikek@symbian.org, for Symbian Foundation +# +# Description: +# + +# romnibus.pl - Build a rom like rom_sbs.pl but without Windows dependencies. +# +# Pre-processes the .oby/iby files then invokes rombuild.exe +# (or other specified builder) + +# First, read our config file + +use strict; +use Getopt::Long; +use Cwd; +use Cwd 'abs_path'; +use File::Spec; + +my $on_windows; +my $epocroot_vol; +my $epocroot_dir; +my $epocroot_file; +my %dir_listings = (); +my %opts=(); +my $param_count = scalar(@ARGV); +my (@assps, @builds, %variants, @templates, %flags, %insts, %zip, %builder); +my $main; +my $kmain; +my $toroot; +my $e32path; +my $rombuildpath; +my $euserdir; +my $elocldir; +my $kbdir; +my $romname; +my $single; +my $smain; +my $pagedCode; +my $debug; +my $quiet; +my $drive; +my $toolpath; +my $epoc32path; +my $epocroot; +my $drive = ""; +my $base_path; +my $line; +sub Variant_GetMacroHRHFile; +sub is_RVCT_build($); +sub parse_cfg; +sub ASSPS; +sub BUILDS; +sub TEMPLATES; +sub usage; +sub rectify($$$); +sub match_abbrev($$); +sub check_opts; +sub lookup_file_info($$); +sub lookupSymbolInfo($$); +sub parse_patch_data($$); +sub gen_file; +sub nix_fixes { +# Fix case-sensitivity offenders for unix/linux environment. + my $e32plat_pm = File::Spec->catfile($toolpath,"e32plat.pm"); + my $armutl_pm = File::Spec->catfile($toolpath,"armutl.pm"); + my $bpabiutl_pm = File::Spec->catfile($toolpath,"bpabiutl.pm"); + my $e32variant_pm = File::Spec->catfile($toolpath,"e32variant.pm"); + my $E32Plat_pm = File::Spec->catfile($toolpath,"E32Plat.pm"); + my $Armutl_pm = File::Spec->catfile($toolpath,"Armutl.pm"); + my $BPABIutl_pm = File::Spec->catfile($toolpath,"BPABIutl.pm"); + my $E32Variant_pm = File::Spec->catfile($toolpath,"E32Variant.pm"); + # Create symlinks for case-sensitively misnamed modules we need. + unless ( -f $E32Plat_pm or -l $E32Plat_pm) { + symlink($e32plat_pm,$E32Plat_pm); + } + unless ( -f $Armutl_pm or -l $Armutl_pm) { + symlink($armutl_pm,$Armutl_pm); + } + unless ( -f $BPABIutl_pm or -l $BPABIutl_pm) { + symlink($bpabiutl_pm,$BPABIutl_pm); + } + unless ( -f $E32Variant_pm or -l $E32Variant_pm) { + symlink($e32variant_pm,$E32Variant_pm); + } + # Make uppercase symlinks to all .bsf files in /epoc32/tools + my @bsf_files = glob(File::Spec->catfile($toolpath,"*.bsf")); + foreach my $bsf_file (@bsf_files) { + my ($vol,$dirs,$file) = File::Spec->splitpath($bsf_file); + $file =~ /^(\S+)\.bsf/; + my $uc_stem = uc($1); + my $uc_bsf_file = File::Spec->catpath($vol,$dirs,($uc_stem .".bsf")); + unless ( -f $uc_bsf_file or -l $uc_bsf_file ) { + symlink($bsf_file,$uc_bsf_file) or die "Can't symlink $bsf_file -> $uc_bsf_file. $!"; + } + } +} + + +BEGIN { + $on_windows = $^O =~ /^MSWin/ ? 1 : 0; + $epocroot = $ENV{EPOCROOT}; + die "ERROR: Must set the EPOCROOT environment variable.\n" if (!defined($epocroot)); + print "Environmental epocroot - >$epocroot<\n"; + $epocroot = abs_path($epocroot); + die "ERROR: EPOCROOT must specify an existing directory.\n" if (!-d $epocroot); + ($epocroot_vol,$epocroot_dir,$epocroot_file) = File::Spec->splitpath($epocroot); + $epocroot = File::Spec->catfile(($epocroot_vol,$epocroot_dir,$epocroot_file),undef); + print "EPOCROOT=$ENV{EPOCROOT} resolved as \"$epocroot\"\n"; + $epoc32path = "${epocroot}epoc32"; + $toolpath = File::Spec->catfile($epoc32path,"tools"); + push @INC, $toolpath; + nix_fixes(), unless ($on_windows); +} + + +my $result = GetOptions (\%opts, "assp=s", + "inst=s", + "type=s", + "variant=s", + "build=s", + "conf=s", + "name=s", + "modules=s", + "xabi=s", + "clean", + "quiet", + "help", + "debug", + "zip", + "symbol", + "noheader", + "kerneltrace=s", + "rombuilder=s", + "define=s@", + "rofsbuilder=s", + "compress", + ); + +$debug = $opts{debug}; +$quiet = $opts{quiet} unless $debug; + +if ($on_windows) { + #The cpp needed a drive apparently + $drive = $epocroot_vol; + $epoc32path = File::Spec->catpath($epocroot_vol,$epoc32path,undef); +} + +my $cwd = Cwd::cwd(); +my ($vol,$dirs,$file) = File::Spec->splitpath($cwd); +my @path_parts = File::Spec->splitdir($dirs); +while(@path_parts[-1] ne "sf") { + pop(@path_parts); +} +$e32path = File::Spec->catdir((@path_parts,"os")); +$base_path = $e32path; # ?? +$rombuildpath = File::Spec->catfile($e32path,"kernelhwsrv","kernel","eka","rombuild"); + +use E32Plat; +{ + Plat_Init($toolpath . ($on_windows ? '\\' : '/')); +} + +if ($debug) { + print "epocroot = $epocroot\n"; + print "epoc32path = $epoc32path\n"; + print "drive = $drive\n"; + print "toolpath = $toolpath\n"; + print "toroot = $toroot\n"; + print "e32path = $e32path\n"; + print "rombuildpath = $rombuildpath\n"; + print "base_path = $base_path\n"; +} + +my $cppflags="-P -undef -Wno-endif-labels -traditional -lang-c++ -nostdinc -iwithprefixbefore $rombuildpath -I $rombuildpath -I $drive$epoc32path "; + +# Include variant hrh file defines when processing oby and ibys with cpp +# (Code copied from \\EPOC\master\cedar\generic\tools\romkit\tools\buildrom.pm - +# it used relative path to the working dir but we are using absolute path seems neater) + +my $variantMacroHRHFile = Variant_GetMacroHRHFile(); +if($variantMacroHRHFile){ + my ($ignore1,$dir,$file) = File::Spec->splitpath($variantMacroHRHFile); + $cppflags .= " -I " . File::Spec->catpath($epocroot_vol,$dir,undef) . " -include " . File::Spec->catpath($epocroot_vol,$dir,$file); +} + +if($param_count == 0 || $opts{'help'} || !$result) { + usage(); + exit 0; +} + +# Now check that the options we have make sense + +checkopts(); + +if (!$quiet) { + print "Starting directory: ", Cwd::cwd(), "\n"; + print <catfile($rombuildpath,"$opts{'type'}.oby"); +} +unless (-e $skel) { + die "Can't find type file for type $opts{'type'}, $!"; +} + +print "Using type file $skel\n" if !$quiet; + +# If clean is specified, zap all the image and .oby files + +if($opts{'clean'}) { + unlink glob("*.img"); + unlink "rom.oby"; + unlink "rombuild.log"; + unlink glob("*.rofs"); + unlink "rofsbuild.log"; +} + +# Now pre-pre-process this file to point to the right places for .ibys +# Unfortunately cpp won't do macro replacement in #include strings, so +# we have to do it by hand + +my $k = $opts{kerneltrace}; + +if ($opts{assp}=~/^m(\S+)/i) { + $kbdir="kb$1"; + $kbdir="kbarm" if (lc $1 eq 'eig'); +} else { + $kbdir="kb$opts{assp}"; +} +$single=1 if ($opts{assp}=~/^s(\S+)/i); + +if ($single) { + # Hackery to cope with old compiler + if ($main eq 'MARM') { + $smain='SARM'; + } else { + $smain="S$main"; + } +} else { + $smain=$main; +} + +open(X, "$skel") || die "Can't open type file $skel, $!"; +open(OUT, "> rom1.tmp") || die "Can't open output file, $!"; + +# First output the ROM name +print OUT "\nromname=$romname\n"; +while() { + unless ($on_windows) { + if (m/#include/) { + s|\\|\/|g; + } + } + s/\#\#ASSP\#\#/$opts{'assp'}/; + s/\#\#VARIANT\#\#/$opts{'variant'}/; + s/\#\#BUILD\#\#/$opts{'build'}/; + s/\#\#MAIN\#\#/$main/; + s/\#\#KMAIN\#\#/$kmain/; + s/\#\#E32PATH\#\#/$e32path/; + s/\#\#BASEPATH\#\#/$base_path/; + s/\#\#EUSERDIR\#\#/$euserdir/; + s/\#\#ELOCLDIR\#\#/$elocldir/; + s/\#\#KBDIR\#\#/$kbdir/; + print OUT; +} + +close X; +close OUT; + +# Use cpp to pull in include chains and replace defines + +my $defines = ""; +$defines .= "-D MAIN=$main "; +$defines .= "-D KMAIN=$kmain "; +$defines .= "-D EUSERDIR=$euserdir "; +$defines .= "-D ELOCLDIR=$elocldir "; +$defines .= "-D E32PATH=$e32path "; +$defines .= "-D BASEPATH=$base_path "; +$defines .= "-D EPOCROOT=$epocroot "; +$defines .= "-D SMAIN=$smain " if $smain; + +foreach (@{$opts{'define'}}) { + my @array=split(/,/,$_); + foreach (@array) { + $defines.="-D ".uc $_." "; + $pagedCode = 1 if $_ eq 'PAGED_CODE'; + } + } + +if ($opts{'modules'}) { + my @array=split(/,/,$opts{'modules'}); + foreach (@array) { + $defines.="-D ".uc $_." "; + } + } + +foreach (keys %opts) { + next if ($_ eq 'name'); + next if ($_ eq 'modules'); + next if ($_ eq 'zip'); + next if ($_ eq 'symbol'); + next if ($_ eq 'kerneltrace'); + next if ($_ eq 'define'); + $defines.="-D ".uc $_."=".$opts{$_}." "; + $defines.="-D ".uc $_."_".$opts{$_}." "; +} + +$defines.="-D SINGLE " if ($single); +$defines.="-D RVCT " if (IsRVCTBuild($main)); + +print "Using defines $defines\n" if !$quiet; + +my $ret=1; +my $cppcmd; +if($opts{'build'}=~/^u/i and $on_windows) { + # Unicode build + $cppcmd = File::Spec->catfile($epoc32path,"gcc","bin","cpp") . " $cppflags -D UNICODE $defines rom1.tmp rom2.tmp"; +} else { + $cppcmd = "cpp $cppflags $defines rom1.tmp rom2.tmp"; +} +print "Executing CPP:\n\t$cppcmd\n" if $debug; +$ret = system($cppcmd); +die "ERROR EXECUTING CPP\n" if $ret; + +# Purge remarks and blank lines. Complete source filenames and adapt them to host filesystem. +rectify("rom2.tmp", "rom3.tmp", $k); + + +# scan tmp file and generate auxiliary files, if required +open TMP, "rom3.tmp" or die("Can't open rom3.tmp\n"); +while ($line=) + { + if ($line=~/\s*gentestpaged/i) { + genfile("paged"); } + if ($line=~/\s*gentestnonpaged/i) { + genfile("nonpaged"); } + } + +parsePatchData("rom3.tmp", "rom4.tmp"); + +# break down the oby file into rom, rofs and extensions oby files + +my $oby_index =0; +my $dumpfile="rom.oby"; +my $rofs=0; +my $extension=0; +my $corerofsname=""; +open DUMPFILE, ">$dumpfile" or die("Can't create $dumpfile\n"); +open TMP, "rom4.tmp" or die("Can't open rom4.tmp\n"); +while ($line=) + { + if ($line=~/^\s*rofsname/i) + { + close DUMPFILE; # close rom.oby or previous rofs#/extension#.oby + $oby_index=1; + $corerofsname=$line; + $corerofsname =~ s/rofsname\s*=\s*//i; # save core rofs name + chomp($corerofsname); + unlink $corerofsname || print "unable to delete $corerofsname"; + my $dumpfile="rofs".$rofs.".oby"; + $rofs++; + open DUMPFILE, ">$dumpfile" or (close TMP and die("Can't create $dumpfile\n")); + } + + if ($line=~/^\s*coreimage/i) + { + close DUMPFILE; # close rofs.oby + if ($oby_index ne 1) { + close TMP; + die "Must specify ROFS image before ROFS extension\n"; + } + my $name=$line; + $name =~ s/coreimage\s*=\s*//i; # read core rofs name + chomp($name); # remove trailing \n + if ($name ne $corerofsname) { + close TMP; + die "This extension does not relate to previous ROFS\n"; + } + $oby_index=33; # open window + my $dumpfile="extension".$extension.".oby"; + $extension++; + open DUMPFILE, ">$dumpfile" or (close TMP and die("Can't create $dumpfile\n")); + } + + if ($line=~/^\s*extensionrofs/i) + { + $oby_index=3 if ($oby_index eq 2); + } + + if (($oby_index eq 2) && !($line=~/^\s*$/)) { + close TMP; + die "Bad ROFS extension specification\n"; + } + print DUMPFILE $line; + $oby_index=2 if ($oby_index eq 33); # close window + } +close DUMPFILE; +close TMP; + +# For paged roms that use rofs, move all data= lines in rom which are not 'paging_unmovable' to rofs, so that paged ram-loaded code +# is automatically put into rofs +rename('rom.oby', 'rom4.tmp') || die; + +open(IN, 'rom4.tmp') || die "Can't read rom4.tmp"; +open(ROM, '>rom.oby') || die "Can't write to rom.oby"; + +if ($oby_index >= 1 && $pagedCode) { + open(ROFS, '>>rofs0.oby') || die "Can't append to rofs0.oby"; +} + +while ($line=) +{ + if(($oby_index >= 1) && ($pagedCode) && ($line=~/^\s*data\s*=/) && !($line=~/\.*paging_unmovable\s*/)) { + print ROFS $line; + } + else { + $line=~s/paging_unmovable//; + print ROM $line; + } +} + +close IN; +close ROM; + +if ($oby_index >= 1 && $pagedCode) { + close ROFS; +} + unlink 'rom4.tmp'; + +my $flags; + +foreach (@{$flags{$opts{'assp'}}}) { + $flags.=" -$_"; +} + +if($opts{'noheader'}) { + $flags.=" -no-header"; +} + +if($opts{'compress'}) { + $flags.=" -compress"; +} + +my $builder = $opts{'rombuilder'}; +if ($on_windows) { + $builder = File::Spec->catfile($toolpath,"rombuild.exe") unless ($builder); +} +else { + $builder = File::Spec->catfile($toolpath,"rombuild") unless ($builder); + unless ( -x $builder ) { + chmod 0755,$builder; + } +} + +print "$builder $flags -type-safe-link -S rom.oby 2>&1\n\n"; + +open(Y, "$builder $flags -type-safe-link -S rom.oby 2>&1 | ") || + die "Can't start $builder command, $!"; + +my $nerrors=0; +my $nwarnings=0; + +while() { + my $error=(/^error:/i); + my $warning=(/^warning:/i); + print if ($error or $warning or !$quiet); + $nerrors++ if ($error); + $nwarnings++ if ($warning); +} + +print "\nGenerated .oby file is rom.oby\n" if !$quiet; +print "\nGenerated image file is $romname\n" if (!$nerrors); + +my$rerrors; +my $rofsbuilder; +if ($rofs) { + $rofsbuilder = $opts{'rofsbuilder'}; + $rofsbuilder = "rofsbuild" unless ($rofsbuilder); + for(my $i=0;$i<$rofs;++$i) { + print "Executing $rofsbuilder on main rofs\n" if !$quiet; + my $image="rofs".$i.".oby"; + system("$rofsbuilder $image"); + if ($? != 0) + { + print "$rofsbuilder $image returned $?\n"; + $rerrors++; + } + rename "rofsbuild.log", "rofs$i.log" + } +} + +if ($rofs and $extension) { + for(my $i=0;$i<$extension;++$i) { + print "Executing $rofsbuilder on extension rofs\n" if !$quiet; + my $image="extension".$i.".oby"; + system("$rofsbuilder $image"); + if ($? != 0) + { + print "$rofsbuilder $image returned $?\n"; + $rerrors++; + } + rename "rofsbuild.log", "extension$i.log" + } +} + +if ($nerrors) { + print "\n\n Errors found during $builder!!\n\nLeaving tmp files\n"; +} elsif ($nwarnings) { + print "\n\n Warnings during $builder!!\n\nLeaving tmp files\n"; +} elsif ($rerrors) { + print "\n\n Errors during $rofsbuilder!!\n\nLeaving tmp files\n"; +} else { + unlink glob("*.tmp") if !$debug; +} +if ($opts{zip} or $zip{$opts{assp}}) { + my $zipname=$romname; + $zipname =~ s/\.(\w+)$/\.zip/i; + unlink $zipname; + system("zip $zipname $romname"); +} +if ($opts{symbol}) { + my $logname=$romname; + $logname =~ s/\.(\w+)$/\.log/i; + my $obyname=$romname; + $obyname =~ s/\.(\w+)$/\.oby/i; + unlink $logname; + unlink $obyname; + system("rename rombuild.log $logname"); + system("rename rom.oby $obyname"); + system("maksym $logname"); +} + +#IMK if ($nerrors || $nwarnings || $rerrors) { +#IMK exit 4; +#IMK} +if ($nerrors || $rerrors) { + exit 4; +} + + +exit 0; + + +################################ Subroutines ################################## + +sub usage { + print < + +Generate a rom image for the specified target, along with a rom.oby file +that can be fed to (a) rombuild to regenerate the image. + +The following options are required: + --variant= e.g. --variant=assabet + --inst= e.g. --inst=arm4 + --build= e.g. --build=udeb + --type= + tshell for a text shell rom + e32tests for a rom with e32tests + f32tests for rom with f32tests + alltests for all the tests + +The following are optional: + --name= Give image file specified name + --noheader Pass -no-header option on to rombuild + --help This help message. + --clean Remove existing generated files first + --quiet Be less verbose + --modules= List of additional modules for this ROM + --define= List of CPP macros to define + +Options may be specified as a short abbreviation +e.g. -b udeb instead of --build udeb + +EOT +} + +sub rectify($$$) { + my ($in, $out, $k) = @_; + my $lastblank; + my $lineno = 0; + + open(OUTPUT_FILE, "> $out") or die "Cannot open $out for output"; + open(INPUT_FILE, "< $in") or die "Cannot open for $in input"; + + while ($line=) { + ++$lineno; + if ($line =~ /^\/\// ) {} # Ignore c++ commented lines. + elsif ($line =~ /^\s*REM\s+/i) {} # Ignore REM commented lines. + elsif ($line =~ /^\s*$/) { # Compress blank lines down to one + if($lastblank) { + # Do nothing + } + else { + # This is the first blank line + $lastblank=1; + print OUTPUT_FILE $line; + } + } + else { + # Not blank + $lastblank = 0; + $line =~ s|##||g; # Delete "token-pasting" ops + $line =~ s|//.*$||g; # Delete trailing c++ comments + # prefix the epocroot dir to occurrences of 'epoc32' in all "KEYWORD=..." lines. + $line =~ s/(=\s*)[\\\/]epoc32/\1${epocroot}epoc32/i; + if (!defined($1)) { # Not a keyword line. + if ($k and $line=~/^\s*kerneltrace/i) { + $line = "kerneltrace $k\n"; + } + } + elsif ($line =~ /^(\s*\S+\s*=\s*)(\S+)(\s*\S*)/) { + if ($on_windows) { + $line =~ s|\/|\\|g; + } + else { + my $keyword_part = $1; + my $src = $2; + my $dest = $3; + $src =~ s|\\|\/|g; + if ($dest) { + my ($vol,$dir,$leaf) = File::Spec->splitpath($src); + my $lc_leaf = lc($leaf); + my $lc_dir = lc($dir); + $lc_dir =~ s/\/$//; + my $fulldir = $lc_dir; + $fulldir =~ s|//|/|g; + unless ( -d $fulldir ) { + chomp $line; + # Lower-cased source directory doesn't exist. Give up. + die "Guessed source directory \"$fulldir\" does not exist for line $lineno: \"$line\"\n"; + } + if (($leaf eq $lc_leaf) or (-f "$fulldir\/$leaf")) { + # Using source directory lowercase and source filename as input. + $line = "${keyword_part}${lc_dir}\/${leaf}${dest}\n"; + } + elsif ( -f "$fulldir\/$lc_leaf") { + # Using source directory source filename both lowercase. + $line = "${keyword_part}${lc_dir}\/${lc_leaf}${dest}\n"; + } + else { # Harder. + my @dirlist; + my $found = 0; + if (!defined($dir_listings{$fulldir})) { + # Haven't got a cached dir listing for the source directory. + # Make one now. + @dirlist = glob("$fulldir.*"); + $dir_listings{$fulldir} = \@dirlist; + } + @dirlist = @{dir_listings{$fulldir}}; # Get listing of source directory from cache. + foreach my $file (@dirlist) { + # See if any file in the source directory case-insensitively matches the input source file. + if ( (-f "$fulldir\/$file") and (lc($file) eq $lc_leaf)) { + $line = "${keyword_part}${lc_dir}\/${file}${dest}\n"; + $found = 1; + last; + } + } + unless ($found) { + die "Cannot find any file case-insensitively matching \"$fulldir\/$leaf\" at line $lineno: \"$line\"\n"; + } + } + } + } + } + print OUTPUT_FILE $line; + } + } + close(INPUT_FILE); + close(OUTPUT_FILE); +} + +sub IsRVCTBuild($) { + my ($build)=@_; + return 1 if ($build =~ /^ARMV/i); + my @customizations = Plat_Customizations('ARMV5'); + return 1 if (grep /$build/, @customizations); + return 0; +} + + +sub IsSmp($) { + my %SmpKernelDirs=( + 'x86smp' => 1, + 'x86gmp' => 1, + 'arm4smp' => 1, + 'armv4smp' => 1, + 'armv5smp' => 1 + ); + + my ($kdir) = @_; + return $SmpKernelDirs{lc $kdir}; +} + +sub checkopts { + unless($opts{variant}) { die "No Variant specified"; } + $opts{'build'}="UDEB" unless($opts{'build'}); + $opts{'type'}="TSHELL" unless($opts{'type'}); + $opts{'inst'}="ARM4" unless($opts{'inst'}); + + my $additional; + if ($opts{'modules'}) { + $additional="_".$opts{modules}; + $additional=~ s/,/_/ig; + } + my $build=lc $opts{build}; + my $inst=uc $opts{'inst'}; + if ($inst eq "MARM") { + # Hackery to cope with old compiler + $main="MARM"; + $euserdir="MARM"; + $elocldir="MARM"; + } + else { + $main=$inst; + if ($main eq "THUMB") { + $euserdir="ARMI"; + } else { + $euserdir=$main; + } + if ($main eq "ARMI" or $main eq "THUMB") { + $elocldir="ARM4"; + } else { + $elocldir=$main; + } + } + $kmain = $opts{'xabi'}; + $kmain = $main unless ($kmain); + if (IsSmp($kmain)) { + $euserdir = $kmain; + } + if ($opts{name}) { + $romname=$opts{name}; + } else { + $romname=uc($opts{variant}.$additional.$main); + if ($build=~/^\w*DEB$/i) { + $romname.='D'; + } + $romname.='.IMG'; + } +} + +sub lookupFileInfo($$) +{ + my ($infile, $fullname) = @_; + + my ($name, $ext) = $fullname =~ /^(.+)\.(\w+)$/ ? ($1, $2) : ($fullname, undef); + + open TMP, $infile or die("Can't open $infile\n"); + while() + { + $_ = lc; + if(/^\s*(\S+)\s*=\s*(\S+)\s+(\S+)/i) + { + my ($src, $dest) = ($2, $3); + + my $destFullname = $dest =~ /^.*\\(.+)$/ ? $1 : $dest; + my ($destName, $destExt) = $destFullname =~ /^(.+?)\.(\w+)$/ ? ($1, $2) : ($destFullname, undef); + + if ($destName eq $name && (!$ext || $ext eq $destExt)) + { + close TMP; + return ($src, $dest); + } + } + } + + die "patchdata: Can't find file $fullname\n"; +} + +sub lookupSymbolInfo($$) +{ + my ($file, $name) = @_; + + open TMP, $file or die "Can't read $file\n"; + + # ignore local symbols. + while () + { + last if /Global Symbols|Linker script and memory map/; + } + + my @return_values = (); + my $line; + while ($line = ) + { + next if (index($line, $name) < 0); + + # RVCT 2.2 + # + # KHeapMinCellSize 0x0004e38c Data 4 mem.o(.constdata) + # + if ($line =~ /^\s*(\S+)\s+(\S+)\s+data\s+(\S+)/i) + { + my ($symbol, $addr, $size) = ($1, $2, $3); + if ($symbol eq $name) + { + @return_values = ($addr, $size); + last; + } + } + + # This is a quick fix for RVCT 3.1, which uses the text "(EXPORTED)" + # in the map file. Here is an example: + # + # KHeapMinCellSize (EXPORTED) 0x0003d81c Data 4 mem.o(.constdata) + # + elsif ($line =~ /^\s*(\S+)\s+\(exported\)\s+(\S+)\s+data\s+(\S+)/i) + { + my ($symbol, $addr, $size) = ($1, $2, $3); + if ($symbol eq $name) + { + @return_values = ($addr, $size); + last; + } + } + + # GCC 4.x map files + # 0x00114c68 KHeapMinCellSize + # 0x00114c6c KHeapShrinkHysRatio + # .rodata 0x00115130 0x968 M:/epoc32/build/kernel/c_99481fddbd6c6f58/_omap3530_ekern_exe/armv5/udeb/heap_hybrid.o + # + elsif ($line =~ /^.+\s+(0x\S+)\s+(\S+)/i) + { + my ($addr, $symbol) = ($1, $2); + if ($symbol eq $name) + { + my $next_line = ; + if ($next_line =~ /^.+\s+(0x\S+)\s+(\S+)/i) + { + my $addr2 = $1; + + @return_values = ($addr, hex($addr2) - hex($addr)); + last; + } + } + } + + } + close TMP; + + die "patchdata: Can't find symbol $name\n" if (scalar @return_values == 0); + return @return_values; +} + +sub parsePatchData($$) +{ + my ($infile, $outfile) = @_; + + open IN, $infile or die("Can't read $infile\n"); + open OUT, ">$outfile" or die("Can't write $outfile\n"); + + my $line; + while($line = ) + { + if ($line =~ /^\s*patchdata\s+(.+?)\s*$/i) + { + if ($1 !~ /(\S+)\s*@\s*(\S+)\s+(\S+)\s*$/) + { + die "Bad patchdata command: $line\n"; + } + + my ($file, $symbol, $value) = (lc $1, $2, $3); + my ($srcFile, $destFile) = lookupFileInfo($infile, $file); + my ($index, $elementSize) = (undef, undef); + if ($symbol =~ s/:(\d+)\[(\d+)\]$//) + { + ($index, $elementSize) = ($2, $1); + $index = hex($index) if $index =~ /^0x/i; + } + + if ($srcFile =~ /\\armv5(smp)?\\/i) + { + my ($symbolAddr, $symbolSize) = lookupSymbolInfo("$srcFile.map", $symbol); + + my $max; + if (defined($index)) + { + my $bytes; + $bytes = 1, $max = 0xff if $elementSize == 8; + $bytes = 2, $max = 0xffff if $elementSize == 16; + $bytes = 4, $max = 0xffffffff if $elementSize == 32; + die("patchdata: invalid element size $elementSize: $line\n") unless defined($bytes); + + if ($bytes > 1 && (($symbolSize & ($bytes-1)) != 0)) + { + die("patchdata: unexpected symbol size $symbolSize for array $symbol ($elementSize-bit elements)\n"); + } + + if ($index >= int($symbolSize / $bytes)) + { + die("patchdata: index $index out of bounds for $symbol of $symbolSize bytes ($elementSize-bit elements)\n"); + } + + $symbolAddr = hex($symbolAddr) if $symbolAddr =~ /^0x/i; + $symbolAddr += $index * $bytes; + $symbolAddr = sprintf("0x%x", $symbolAddr); + + $symbolSize = $bytes; + } + elsif ($symbolSize == 1) { $max = 0xff; } + elsif ($symbolSize == 2) { $max = 0xffff; } + elsif ($symbolSize == 4) { $max = 0xffffffff; } + else { die "patchdata: Unexpected symbol size $symbolSize for $symbol\n"; } + + $value = hex($value) if $value =~ /^0x/i; + if ($value > $max) + { + print("Warning: Value overflow of $symbol\n"); + $value &= $max; + } + $value = sprintf("0x%08x", $value); + + $line = "patchdata $destFile addr $symbolAddr $symbolSize $value\n"; + } + else + { + $line = ""; + } + + } + + print OUT $line; + } + + close IN; + close OUT; +} + +sub genfile { + my $count=0; + if($_[0] eq 'paged') { + my $file='gentestpaged.txt'; + unlink $file; + open(OUTFILE, ">$file") or die "Can't open output file, $!"; + for(my $i=0;$i<50000;++$i) { + if(($i >5) && ($i % 40 ==0)) { + print OUTFILE "\n"; + $count++; + } + if(($i+$count) % 5 ==0) { + print OUTFILE "SATOR "; + } + if(($i+$count) % 5 ==1) { + print OUTFILE "AREPO "; + } + if(($i+$count) % 5 ==2) { + print OUTFILE "TENET "; + } + if(($i+$count) % 5 ==3) { + print OUTFILE "OPERA "; + } + if(($i+$count) % 5 ==4) { + print OUTFILE "ROTAS "; + } + } + } else { + my $file='gentestnonpaged.txt'; + unlink $file; + open(OUTFILE, ">$file") or die "Can't open output file, $!"; + for(my $i=0;$i<20000;++$i) { + if(($i >5) && ($i % 40 ==0)) { + print OUTFILE "\n"; + $count++; + } + if(($i+$count) % 4 ==0) { + print OUTFILE "STEP "; + } + if(($i+$count) % 4 ==1) { + print OUTFILE "TIME "; + } + if(($i+$count) % 4 ==2) { + print OUTFILE "EMIT "; + } + if(($i+$count) % 4 ==3) { + print OUTFILE "PETS "; + } + } + } +} + +sub Variant_GetMacroHRHFile { + my $cfgFile = File::Spec->catfile($toolpath,"variant","variant.cfg"); # default location + # save the volume, if any. + my ($cfg_vol,$ignore1,$ignore2) = File::Spec->splitpath($cfgFile); + my $file; + if(-e $cfgFile){ + open(FILE, $cfgFile) || die "\nCould not open for reading: " . $cfgFile ."\n"; + while () { + # strip comments + s/^([^#]*)#.*$/$1/o; + # skip blank lines + if (/^\s*$/o) { + next; + } + # get the hrh file + if($_ =~ /\.hrh/xi){ + $file = $_; + last; + } + } + close FILE; + die "\nERROR: No variant file specified in $cfgFile!\n" unless $file; + $file =~ s/\s+//g; + $file =~ s|\\|\/|g, unless($on_windows); + + if (File::Spec->file_name_is_absolute($file)) { + unless ( -f $file) { + $file = substr $file,1; + $file = File::Spec->catfile($epocroot,$file); + } + my ($vol,$dir,$leaf) = File::Spec->splitpath($file); + die "\nERROR: Variant file specified in $cfgFile is not on the same volume as EPOCROOT\n", if (lc($vol) ne lc($cfg_vol)); + #$file = File::Spec->catfile($dir,$file); + } + else { + $file = File::Spec->catfile($epoc32path,$file); + } + + unless(-e $file) { + die "\nERROR: $cfgFile specifies $file which doesn't exist!\n"; + } + + $file =~ s/\//\\/g, if ($on_windows); + } + return $file; +} +