fix: support new trace compiler features for preventing clashes. Automatically turn on OST_TRACE_COMPILER_IN_USE macro. Look for trace header in systemincludes. Make directories in makefile parse to prevent clashes during build. Correct path for autogen headers. Correct case issue with autogen headers on Linux.
#
# 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 the License "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
#
# This package processes the Image Content XML, and creates an OBY file to create a Rom image.
package ImageContentHandler;
require Exporter;
@ISA=qw(Exporter);
@EXPORT=qw(
ParseImageContentXML
ProcessImageContent
AddBinary
GetBldRomOpts
SetBldRomOpts
GenObyFile
GetObyFiles
AddBinaryFromOby
UpdateObyBinaryStaticDep
PrintMsg
DumpBinaries
);
use strict;
use genericparser;
use cdfparser;
use Dep_Lister;
#Error list
my @errors;
my %ImageContent=(); #Image details are stored in this tree
my $RootNode; #The root node of the XML root document element
my @TargetImageList; #The list of target element nodes in the XML. These are ordered based on their
# imageid (if it is a number, else, based on the availibility of Rom locations within 0..7).
my @binarySelectionArray; #This array stores the ABI directories to be looked up to select binaries.
my @ImageContentBinaries; #This list is for the biaries mentioned in Image content XML for
# keywords like, 'primary', 'secondary', 'device', 'extension', 'variant'.
# List that contains information of binary from OBY file. This list is maintained to check if their static dependencies
# have been included already in Rom.
my %obyFileInfo=();
my $ImageIndex=-1;
my @Includes; #List of included features. The included feature in this list is a hash table giving the
#Uid or the name. These features are collected either from the Image content or the CDF XMLs.
my @Excludes; #List of excluded features.The excluded feature in this list is a hash table giving the
#Uid or the name. These features are collected either from the Image content or the CDF XMLs.
my %DefaultDirs =();#This hash table records the default ABI and the BUILD directories. These are updated in case
# the overriding buildrom options are provided e.g., -D_FULL_DEBUG or -D_PLAT=GCCE etc.
my @BPABIPlats = &BPABIutl::BPABIutl_Plat_List; # Add the BPABI Platforms to be added
my $isEcomPlugin=0; # This flag will be set when PLUGINs are provided in the CDF file.
sub ParseImageContentXML
{
my $XMLFile = shift;
$XMLFile =~ s/\\/\//g;
$RootNode = &getRootElement($XMLFile);
&SetImageDetails(\%ImageContent, $RootNode);
}
my @padding;
#This subroutine traverses the XML tree and stores the fields in the hast table %ImageContent. The keys
# are the branch names. For target nodes., it stores the nodes themselves in the hash table and doesn't
# go deeper. These nodes are processed laster. For the other nodes, it keeps traversing recursively.
# There are some special keys used to store the nodes and values in the tree. While storing an XML::DOM
# node, it sores with the keys 'nodes', while, for storing a value, it is stored with the key 'vals'.
# These are the keys used to retrieve the contents of the tree while generating the final OBY.
sub SetImageDetails
{
my ($ImageDetailRef, $ImageNode) = @_;
my @children = &genericparser::getChildElements($ImageNode);
my $child;
my $TreeRef;
my $branch;
my $parentName = &genericparser::getElementName($ImageNode);
my $childCnt = scalar @children;
my ($indent) = join('', @padding);
my $val = &genericparser::getElementValue($ImageNode);
$val = Trim($val);
if($val ne "")
{
push @{$ImageDetailRef->{vals}}, $val;
}
my $NodeRef;
foreach $child (@children)
{
$branch = &genericparser::getElementName($child);
$NodeRef = \%{$ImageDetailRef->{$branch}};
if($branch eq "cdf" and $parentName eq "romscope")
{
# Record the romscope node. This node indicates the oby files or cdf files/directories
# that may be used.
push @{$NodeRef->{nodes}}, $child;
next;
}
if($branch eq "target" and $parentName eq "romtarget")
{
push @{$NodeRef->{nodes}}, $child;
next;
}
if( ($branch =~ /primary/i ) ||
($branch =~ /secondary/i) ||
($branch =~ /extension/i) ||
($branch =~ /variant/i ) ||
($branch =~ /device/i ) )
{
next;
}
if( $child->hasChildNodes() )
{
$NodeRef->{hasChildren} = 1;
push @padding, ".";
SetImageDetails($NodeRef, $child);
}
else
{
$NodeRef->{hasChildren} = 0;
}
# Get all attributes...
my $attribs = &genericparser::getNodeAttributes($child);
my $attrib;
my $nodeName;
my $nodeVal;
my %attr=();
my $attrLen = $attribs->getLength;
for (my $pos = 0; $pos < $attrLen;$pos++)
{
$attrib = $attribs->item($pos);
if(!$attrib)
{
next;
}
$nodeName = lc ($attrib->getName);
$nodeVal = lc ($attrib->getValue);
$attr{$nodeName}=$nodeVal;
}
push @{$NodeRef->{vals}}, \%attr;
}
pop @padding;
}
my @romGeometry; #Array to store all Roms mentioned in RomGeometry
my %romGeometryHash = (); #This Hash table records the indices in @romGeometry array, keying on their Ids.
my $curRomImageIndex; #This scalar records the current Rom image being processed. An binary encountered
# becomes part of the Rom image corresponding to this partition.
# This subroutine associates the RomGeometry and the RomTarget sub-trees to set indices for the Rom-target
# nodes.It stores the Image content XML entries for primary/secondary/device/extension/variant keywords.
# It also stores the features that are included/excluded in Image content XML.
sub ProcessImageContent
{
my $TotalImages = &ProcessRomGeometry();
my @trgList;
if( defined @{$ImageContent{romtarget}{target}{nodes}})
{
@trgList = @{$ImageContent{romtarget}{target}{nodes}};
}
# Go through the romgeometry to find the location of each image. The valid IDs are 0 through 7.
foreach my $trg (@trgList)
{
# The ID field in romgeometry can be an integer in the range 0 through 7.
# If it is not a number, its location is assumed as its sequence number
my $imageid = &genericparser::getAttrValue($trg, "imageid");
if($imageid =~ /Any/i)
{
next;
}
elsif(exists $romGeometryHash{$imageid})
{
$ImageIndex = $romGeometryHash{$imageid};
push @{$TargetImageList[$ImageIndex]} , $trg;
}
}
# Romscope - update the maps if the files and directories are mentioned.
my @romScopeNodes;
if(defined @{$ImageContent{romscope}{cdf}{nodes}})
{
@romScopeNodes = @{$ImageContent{romscope}{cdf}{nodes}};
}
my $type;
my $file;
my $dir;
foreach my $aNode (@romScopeNodes)
{
$type = &genericparser::getAttrValue($aNode, "type");
if( $type =~ /dir/i)
{
$dir = &genericparser::getElementValue($aNode);
&cdfparser::CreateCDFFileBinaryMapFromDir($dir);
}
elsif($type =~ /file/i)
{
$file = &genericparser::getElementValue($aNode);
&cdfparser::CreateCDFFileBinaryMap($file);
}
}
my $availablePos = 0;
foreach my $trg (@trgList)
{
if(&genericparser::getAttrValue($trg, "imageid") =~ /Any/i)
{
while($availablePos < $TotalImages)
{
if( !defined($TargetImageList[$availablePos][0]) )
{
push @{$TargetImageList[$availablePos]}, $trg;
last;
}
$availablePos++;
}
}
}
my $pos = 0;
while( $pos < 8)
{
if( defined $TargetImageList[$pos][0] )
{
# Record the current Rom image index so that the binaries are included in the corresponding
# Rom image.
# The romGeometry and TargetImageList arrays are associated both being indexed on
# the Rom-image index.
$curRomImageIndex = $pos;
&ProcessTarget($pos, \@{$TargetImageList[$pos]});
}
$pos++;
}
# Pick the primary/secondary/device binaries
my @nodes = &genericparser::getNodeFromTree($RootNode, "options", "primary", "file");
if( defined @nodes)
{
&SaveImageContentBinaries(\@nodes, "primary");
}
@nodes = &genericparser::getNodeFromTree($RootNode, "options", "secondary", "file");
if( defined @nodes)
{
&SaveImageContentBinaries(\@nodes, "secondary");
}
@nodes = &genericparser::getNodeFromTree($RootNode, "options", "extension", "file");
if( defined @nodes)
{
&SaveImageContentBinaries(\@nodes, "extension");
}
@nodes = &genericparser::getNodeFromTree($RootNode, "options", "variant", "file");
if( defined @nodes)
{
&SaveImageContentBinaries(\@nodes, "variant");
}
@nodes = &genericparser::getNodeFromTree($RootNode, "options", "device", "file");
if( defined @nodes)
{
&SaveImageContentBinaries(\@nodes, "device");
}
foreach my $imgBin (@ImageContentBinaries)
{
&ProcessStaticDep($imgBin->{source});
}
# Pick the binary selection order
if (exists($ImageContent{options}{binaryselectionorder}{vals}))
{
my ($abiDirs) = @{$ImageContent{options}{binaryselectionorder}{vals}};
@binarySelectionArray = split(',', $abiDirs);
@binarySelectionArray = Trim(@binarySelectionArray);
}
my $featureList = &cdfparser::GetIncludedFeatureList();
foreach my $feature (@$featureList)
{
push @Includes, $feature;
}
$featureList = &cdfparser::GetExcludedFeatureList();
foreach my $feature (@$featureList)
{
push @Excludes, $feature;
}
}
#Arrange the Rom-geometry according to their Id when they are numbers. The named images
#are arranged starting from the empty slots in Rom geometry array.
sub ProcessRomGeometry
{
my $RomImageCount = 0;
my $pos = 0;
while($pos < 8)
{
$romGeometry[$pos++] = undef;
}
my @roms = @{$ImageContent{romgeometry}{image}{vals}};
$RomImageCount = scalar (@roms);
my @namedImages;
# Visit all images and allocate them the indices they mention.
foreach my $img (@roms)
{
if($img->{id} =~ /(\d+)/)
{
$pos = $1;
if( defined($romGeometry[$pos]) )
{
print "Error: $romGeometry[$pos]->{id} and $img->{id} cant be allocated the same position\n";
exit;
}
$romGeometry[$pos] = $img;
# Record the index of this Rom
$romGeometryHash{$img->{id}} = $pos;
}
else
{
# These are the named images that are allocated there positions sequentially starting from
# the first available empty position
push @namedImages, $img;
}
}
# Revisit the images and allocate the remaining (unallocated) positions.
$pos = 0;
my $namedImageCount = scalar (@namedImages);
my $firstNamedImgIdx = 0;
my $img;
while( ($pos < 8) and ($namedImageCount > 0) )
{
if( $romGeometry[$pos] )
{
# skip the positions already allocated.
$pos++;
next;
}
$img = $namedImages[$firstNamedImgIdx];
$romGeometry[$pos] = $img;
# Record the index of this Rom
$romGeometryHash{$img->{id}} = $pos;
$pos++;$firstNamedImgIdx++;
$namedImageCount--;
}
return $RomImageCount;
}
my @ObyFileList;
#This subrouting processes the target nodes that may include OBYs/CDFs or features. For CDFs, the satic/dynamic
# dependencies are evaluated.
sub ProcessTarget
{
my ($ImgPos , $trgNodesRef) = @_;
my @cdfFileList;
# For all the 'target' nodes associated with an image in romgeometry at the given index...
# The link between a target and an image in romGeometry is the image id. If the imageid
# of a target is 'Any', then the first available image in romGeometry is allocated to
# that target.
foreach my $target (@$trgNodesRef)
{
# Fetch any cdfs included within the Image Content file
my @cdfs = &getNodeFromTree($target, "include","cdf");
my $type;
my $file;
my $dir;
foreach my $cdfNode (@cdfs)
{
$type = &genericparser::getAttrValue($cdfNode, "type");
if( !($type) || ($type eq "file") )
{
$file = &genericparser::getElementValue($cdfNode);
push @cdfFileList, $file;
}
elsif($type eq "dir")
{
$dir = &genericparser::getElementValue($cdfNode);
&cdfparser::CreateCDFFileBinaryMapFromDir($dir);
}
}
# Collect all the obey files mentioned in this 'target' node.
my @obys = &getNodeFromTree($target, "include","obyFile");
foreach my $obyNode (@obys)
{
$file = &genericparser::getElementValue($obyNode);
push @ObyFileList, $file;
}
&CollectFeatures($target, 1, \@Includes);
&CollectFeatures($target, 0, \@Excludes);
}
ProcessCDFList(\@cdfFileList);
}
# This subroutine updates the include or exclude feature list collected from Image content XML.
sub CollectFeatures
{
# Collect all the features included/excluded in this 'target' node.
my ($target, $Inc, $IncludeExcludeListRef) = @_;
my $IncExcStr;
if($Inc == 1)
{
$IncExcStr = "include";
}
else
{
$IncExcStr = "exclude";
}
my @nodes = &getNodeFromTree($target, $IncExcStr,"feature");
foreach my $node (@nodes)
{
my %aFeatureInfo = ();
my $isValidFeature = 0;
my $feature = &genericparser::getAttrValue($node, "name");
if($Inc)
{
# Mark the feature included.
$aFeatureInfo{include} = 1;
}
else
{
# Mark the feature excluded.
$aFeatureInfo{exclude} = 1;
}
if(defined $feature and $feature ne "")
{
$aFeatureInfo{name}= $feature;
$aFeatureInfo{uid} = undef;
$isValidFeature = 1;
}
else
{
$feature = &genericparser::getAttrValue($node, "uid");
if(!defined $feature or $feature eq "")
{
print "Warning: Neither feature name nor uid is defined \n";
}
else
{
if(&featureparser::ValidateUIDValue($feature))
{
$feature = &featureparser::ConvertHexToDecimal($feature);
$aFeatureInfo{uid}= $feature;
$aFeatureInfo{name}= undef;
$isValidFeature = 1;
}
else
{
print "The uid value $feature specified in the Image Content Description is not a valid number\n";
}
}
}
if($isValidFeature)
{
push @$IncludeExcludeListRef, \%aFeatureInfo;
}
}
}
sub DumpImageDetails
{
my ($HRef) = @_;
my %hash = %$HRef;
my $ChildHRef;
foreach my $Key (keys %hash)
{
if($Key eq "hasChildren" || $Key eq "vals")
{
next;
}
my $indent = join('', @padding);
&PrintMsg ($indent. $Key);
if($hash{$Key}{hasChildren} == 1)
{
push @padding, ".";
&PrintMsg ("\n");
$ChildHRef = \%{$hash{$Key}};
&DumpImageDetails($ChildHRef);
}
elsif( defined ($hash{$Key}{vals}) )
{
&PrintMsg ("\nVals $hash{$Key}{vals}\n");
push @padding, ".";
$indent = join('', @padding);
my @array = @{$hash{$Key}{vals}};
&PrintMsg ("array len = " . scalar(@array) . "\n");
foreach my $attrib ( @array )
{
foreach my $key1 (keys %$attrib)
{
&PrintMsg ($indent . $Key. " ". "$key1=$$attrib{$key1}\n");
}
&PrintMsg ("\n");
}
}
elsif( defined (@{$hash{$Key}{nodes}}) )
{
my $node = $hash{$Key}{nodes}[0];
&PrintMsg ("{". scalar(@{$hash{$Key}{nodes}})."}\n");
}
}
pop @padding;
}
sub CheckErrors
{
if($#errors > -1)
{
&PrintMsg ("errors..........$#errors \n");
foreach (@errors)
{
&PrintMsg ($_ ."\n");
}
exit;
}
}
my @ImageBinaryList;#2d array storing the list of binaries per rom image
sub AddBinary
{
my ($binaryName) = @_;
{
push @{$ImageBinaryList[$curRomImageIndex]}, $binaryName;
}
}
sub SetBldRomOpts
{
my ($key, $value) = @_;
if( $key eq undef )
{
# The default ABI directory is armv5 unless specified otherwise in the buildrom command-line.
# The default build directory is urel unless specified otherwise in the buildrom command-line.
$DefaultDirs{ABI_DIR} = 'ARMV5';
$DefaultDirs{BUILD_DIR}='urel';
$DefaultDirs{DEST_DIR}= "\\sys\\bin";
}
else
{
# trim the value for leading/trailing whitespace
$value = Trim($value);
$DefaultDirs{$key} = $value;
}
}
sub Trim()
{
my @out = @_;
for (@out) {
s/^\s+//;
s/\s+$//;
}
return wantarray ? @out : $out[0];
}
sub GetBldRomOpts
{
my ($key) = @_;
return $DefaultDirs{$key};
}
sub DumpBinaries
{
&PrintMsg ("***********Binaries in ROM***********\n");
my $img_idx = 0;
while ($img_idx < 8 and defined ($ImageBinaryList[$img_idx]))
{
my @list = @{$ImageBinaryList[$img_idx]};
&PrintMsg ("Image $img_idx has ". scalar (@list ) . " binaries\n");
foreach my $bin (@list)
{
&PrintMsg ("file[$img_idx]=$bin\n");
}
$img_idx++;
}
&PrintMsg ("***********END***********\n");
}
sub PrintMsg
{
my ($msg) = @_;
print "$msg";
}
# This subroutine is used to generate OBY-contents based on contents of the Image content XML. The image content XML
# may have, in turn, included other OBYs/CDFs. These contents are appended to the Phase-I OBY file (where, the
# Phase-I OBY file is generated by the preprocessor which is the conglomeration of all the buildrom supplied OBY files).
sub GenObyFile
{
my ($ObyFileName) = @_;
open (OBYFH, ">>$ObyFileName") or die("* Can't open $ObyFileName\n");
my $binRef;
my $line;
my $index;
my $new_src_path;
my $exec_src_path = $ENV{EPOCROOT};#This is the Executable source path
$exec_src_path .= "epoc32\\release\\";
my $abidir = $DefaultDirs{ABI_DIR};
my $blddir = $DefaultDirs{BUILD_DIR};
GenObyHeader(*OBYFH);
for($index = 0;$index < 8;$index++)
{
if( !defined $romGeometry[$index] )
{
next;
}
$line = "rom_image $index ";
$line .= $romGeometry[$index]{name} . " ";
$line .= "size=" . $romGeometry[$index]{size} . " ";
if( $romGeometry[$index]{type} =~ /nonxip/)
{
$line .= " non-xip ";
}
else
{
$line .= " xip ";
}
$line .= $romGeometry[$index]{compression} . " ";
if($romGeometry[$index]{extension} eq "yes")
{
$line .= " extension ";
}
$line .= "\n";
print OBYFH $line;
$line = "ROM_IMAGE[$index] {\n"; #Start of contents of this image
print OBYFH $line;
foreach my $binary (@{$ImageBinaryList[$index]}) {
$binRef = &cdfparser::GetBinaryInfo($binary);
if( defined ($binRef) and $binRef->{IsFoundInCDF})
{
if(exists $binRef->{default})
{
$line = "DEFAULT_LANGUAGE $binRef->{default} \n";
print OBYFH "$line";
}
if(exists $binRef->{language})
{
my $langCodes = $binRef->{language};
foreach my $lang (@$langCodes)
{
$line = "LANGUAGE_CODE $lang \n";
print OBYFH "$line";
}
}
# Replace the BUILD_DIR with udeb or urel
# Default BUILD_DIR is urel and can be overridden by using cmd line option '_FULL_DEBUG'
# If a binary is to be picked always from udeb, then the src path in CDF must be mentioned
# as udeb e.g. <source>abi_dir\udeb\drtaeabi.dll</source>, in which case, the mentioned dir
# is picked as it is.
$new_src_path = $binRef->{source};
$new_src_path =~ s/ABI_DIR/$abidir/i;
$new_src_path =~ s/BUILD_DIR/$blddir/i;
$new_src_path =~ s/DEBUG_DIR/udeb/i;
$new_src_path =~ s/epocroot/EPOCROOT/;
$new_src_path =~ s/zresource/ZRESOURCE/;
$new_src_path =~ s/zprivate/ZPRIVATE/;
$new_src_path =~ s/zsystem/ZSYSTEM/;
my $FileFound = 0;
if($binRef->{IsExecutable})
{
$new_src_path = $exec_src_path . $new_src_path;
if(!-f $new_src_path)
{
foreach my $newAbiDir (@binarySelectionArray)
{
$new_src_path =~ s/$abidir/$newAbiDir/i;
if(-f $new_src_path)
{
$FileFound = 1;
last;
}
$abidir = $newAbiDir;
}
if( !$FileFound )
{
$FileFound = fallback($abidir, \$new_src_path);
if( !$FileFound )
{
print "Missing file $binRef->{source} \n";
$new_src_path = $binRef->{source};
}
}
}
# compress options
if(exists $binRef->{compress} and ($binRef->{compress} eq "uncompress") )
{
$line = "fileuncompress=";
}
elsif($binRef->{compress} eq "compress")
{
$line = "filecompress=";
}
elsif( exists $binRef->{dll})
{
$line = "dll=";
}
# Checks the plugin type
elsif( exists $binRef->{type} and $binRef->{type} eq "plugin")
{
if (exists $binRef->{plugin_name})
{
$isEcomPlugin=1;
$line = "__$binRef->{plugin_name}_PLUGIN(ABI_DIR\\BUILD_DIR,ECOM_BIN_DIR,DATAZ_,ECOM_RSC_DIR,$binRef->{id},$binRef->{id})\n";
}
}
else
{
$isEcomPlugin=0;
$line = "file=";
}
if (!$isEcomPlugin)
{
$line .= $new_src_path . " ";
$line .= $binRef->{destination};
}
# stack,heap,fixed,priority,uid,dll,dlldatatop
if( exists $binRef->{stack})
{
$line .= " stack " . $binRef->{stack};
}
if( exists $binRef->{heapmin})
{
$line .= " heapmin " . $binRef->{heapmin};
}
if( exists $binRef->{heapmax})
{
$line .= " heapmax " . $binRef->{heapmax};
}
if( exists $binRef->{fixed})
{
$line .= " fixed";
}
if( exists $binRef->{priority})
{
$line .= " priority " . $binRef->{priority};
}
if( exists $binRef->{uid1})
{
$line .= " uid1 " . $binRef->{uid1};
}
if( exists $binRef->{uid2})
{
$line .= " uid2 " . $binRef->{uid2};
}
if( exists $binRef->{uid3})
{
$line .= " uid3 " . $binRef->{uid3};
}
if( exists $binRef->{dlldatatop})
{
$line .= " dlldatatop ". $binRef->{dlldatatop};
}
if( exists $binRef->{customisable} and $binRef->{customisable} eq "true")
{
$line .= " patched ";
}
}
else
{
my $type = $binRef->{type};
if($type =~ /normal/i)
{
$line = "data=";
}
if($type =~ /aif/i)
{
$line = "aif=";
}
elsif($type =~ /compressedbitmap/i)
{
$line = "compressed-bitmap=";
}
elsif($type =~ /autobitmap/i)
{
$line = "auto-bitmap=";
}
elsif($type =~ /bitmap/i)
{
$line = "bitmap=";
}
if(exists $binRef->{multilinguify})
{
my $extension;
my $srcNameWithoutExt;
my $dstNameWithoutExt;
if($new_src_path =~ /(.*)\.(.*)/)
{
$srcNameWithoutExt = $1;
$extension = $2;
}
if($binRef->{destination} =~ /(.*)\.(.*)/)
{
$dstNameWithoutExt = $1;
}
$line .= "MULTI_LINGUIFY(";
$line .= $extension . " ";
$line .= $srcNameWithoutExt . " ";
$line .= $dstNameWithoutExt;
$line .= ") ";
}
else
{
$line .= $new_src_path . " ";
$line .= $binRef->{destination};
}
}
$line .= "\n";
print OBYFH $line;
}
else
{
#Check if the binary is from ImageContent XML file.
my $imagecontentbin = 0;
foreach my $bin (@ImageContentBinaries) {
my $source;
if( $bin->{source} =~ /.*\\(\S+)/)
{
$source = $1;
}
if (grep /$binary/i, $source) {#Skip the binary that is already included in the OBY Header
$imagecontentbin = 1;
next;
}
}
if ($imagecontentbin) {
next;
}
my $obyInfo = &ImageContentHandler::GetObyBinaryInfo($binary);
if(!defined $obyInfo)
{
$line = "file=" . $exec_src_path. $DefaultDirs{ABI_DIR}. "\\" . $DefaultDirs{BUILD_DIR}. "\\". $binary. " ";
$line .= $DefaultDirs{DEST_DIR}. "\\". $binary;
$line .= "\n";
print OBYFH $line;
}
}
}
$line = "\n}\n";
print OBYFH $line;
}
close OBYFH;
}
#Sets default target to ARMV5 directory if the requested binary is not found
sub fallback{
my ($abidir, $abiFileRef) = @_;
my $foundFile=0;
foreach my $BpabiPlat (@BPABIPlats)
{
if ($$abiFileRef =~ /^(.*)\\$BpabiPlat\\(.*)$/)
{
$$abiFileRef =~ s/$abidir/ARMV5/i;
if(-f $$abiFileRef)
{
$foundFile = 1;
last;
}
}
}
return $foundFile;
}
# This subroutine generates the Rom configuration details like, 'bootbinary', 'romlinearbase', romalign,
# 'kerneldataaddress', 'kernelheapmin' etc.
sub GenObyHeader
{
my ($fh) = @_;
my $line;
# version
if( defined @{$ImageContent{version}{vals}})
{
my $ver = @{$ImageContent{version}{vals}}[0];
if(defined $ver)
{
$line = "version=$ver\n";
print $fh $line;
}
}
# romchecksum
if( defined @{$ImageContent{romchecksum}{vals}})
{
my $cksum = @{$ImageContent{romchecksum}{vals}}[0];
if(defined $cksum)
{
$line = "romchecksum=$cksum\n";
print $fh $line;
}
}
# time
if( defined @{$ImageContent{time}{vals}})
{
my $time = @{$ImageContent{time}{vals}}[0];
if(defined $time)
{
$line = "time=ROMDATE $time\n";
print $fh $line;
}
}
# The Binary selection order
if(scalar @binarySelectionArray )
{
my $abilist = join (',', @binarySelectionArray);
$line = "\nBINARY_SELECTION_ORDER $abilist\n";
print $fh $line;
}
# trace
if( defined @{$ImageContent{options}{trace}{vals}})
{
my @traceFlags = @{$ImageContent{options}{trace}{vals}};
if(scalar @traceFlags)
{
$line = "trace $traceFlags[0]\n";
print $fh $line;
}
}
# The bootbinary
if( defined @{$ImageContent{options}{bootbinary}{vals}})
{
my $binary;
my @bootbin = @{$ImageContent{options}{bootbinary}{vals}};
if(scalar @bootbin)
{
$binary = $bootbin[0];
$binary =~ s/abi_dir/ABI_DIR/;
$line = "bootbinary=$binary\n";
print $fh $line;
}
}
# dataaddress
if( defined @{$ImageContent{options}{dataaddress}{vals}})
{
my @dataAddr = @{$ImageContent{options}{dataaddress}{vals}};
if(scalar @dataAddr)
{
$line = "dataaddress=$dataAddr[0]\n";
print $fh $line;
}
}
# debugport
if( defined @{$ImageContent{options}{debugport}{vals}})
{
my @dgbPort = @{$ImageContent{options}{debugport}{vals}};
if(scalar @dgbPort)
{
$line = "debugport=$dgbPort[0]\n";
print $fh $line;
}
}
# defaultstackreserve
if( defined @{$ImageContent{options}{defaultstackreserve}{vals}})
{
my @defStackRes = @{$ImageContent{options}{defaultstackreserve}{vals}};
if(scalar @defStackRes)
{
$line = "defaultstackreserve=$defStackRes[0]\n";
print $fh $line;
}
}
# wrapper
if( defined @{$ImageContent{options}{wrapper}{vals}})
{
my %tbl = @{$ImageContent{options}{wrapper}{vals}}[0];
if(exists $tbl{epoc})
{
$line = "epocwrapper\n";
print $fh $line;
}
elsif(exists $tbl{coff})
{
$line = "coffwrapper\n";
print $fh $line;
}
elsif(exists $tbl{none})
{
$line = "nowrapper\n";
print $fh $line;
}
}
# kernel options
my $val;
if( defined @{$ImageContent{options}{kernel}{name}{vals}})
{
$val = @{$ImageContent{options}{kernel}{name}{vals}}[0];
$line = "kernelromname=$val\n";
print $fh $line;
}
if( defined @{$ImageContent{options}{kernel}{dataaddress}{vals}})
{
$val = @{$ImageContent{options}{kernel}{dataaddress}{vals}}[0];
$line = "kerneldataaddress=$val\n";
print $fh $line;
}
if( defined @{$ImageContent{options}{kernel}{trace}{vals}})
{
$val = @{$ImageContent{options}{kernel}{trace}{vals}}[0];
$line = "kerneltrace $val\n";
print $fh $line;
}
if( defined @{$ImageContent{options}{kernel}{heapmin}{vals}})
{
$val = @{$ImageContent{options}{kernel}{heapmin}{vals}}[0];
$line = "kernelheapmin=$val\n";
print $fh $line;
}
if( defined @{$ImageContent{options}{kernel}{heapmax}{vals}})
{
$val = @{$ImageContent{options}{kernel}{heapmax}{vals}}[0];
$line = "kernelheapmax=$val\n";
print $fh $line;
}
# romlinearbase
if( defined @{$ImageContent{options}{romlinearbase}{vals}})
{
my @romLinBase = @{$ImageContent{options}{romlinearbase}{vals}};
if(scalar @romLinBase)
{
$line = "romlinearbase=$romLinBase[0]\n";
print $fh $line;
}
}
# romalign
if( defined @{$ImageContent{options}{romalign}{vals}})
{
my @romAlign = @{$ImageContent{options}{romalign}{vals}};
if(scalar @romAlign )
{
$line = "romalign=$romAlign[0]\n";
print $fh $line;
}
}
# autosize keyword with the block size
if( defined @{$ImageContent{options}{autosize}{vals}})
{
my @autoSz = @{$ImageContent{options}{autosize}{vals}};
if(scalar @autoSz )
{
$line = "autosize=$autoSz[0]\n";
print $fh $line;
}
}
# coreimage keyword with the coreimage name.
if( defined @{$ImageContent{options}{coreimage}{vals}})
{
my @coreImg = @{$ImageContent{options}{coreimage}{vals}};
if(scalar @coreImg)
{
$line = "coreimage=$coreImg[0]\n";
print $fh $line;
}
}
foreach my $imgBin (@ImageContentBinaries)
{
$line = $imgBin->{keyword};
my $srcPath = $imgBin->{source};
$srcPath =~ s/abi_dir/ABI_DIR/;
$srcPath =~ s/kernel_dir/KERNEL_DIR/;
$srcPath =~ s/debug_dir/DEBUG_DIR/;
$srcPath =~ s/build_dir/BUILD_DIR/;
if(! ($imgBin->{keyword} =~ /secondary/i) )
{
# VARID mentioned for primary, device, extension and variant keywords.
$line .= "[VARID]" ;
}
$line .= "=" . $srcPath . "\t\t" . $imgBin->{destination};
for my $key (keys %$imgBin)
{
if( ($key =~ /keyword/i) ||
($key =~ /source/i) ||
($key =~ /destination/i))
{
# These keys are already taken care.
next;
}
# Write the rest of the keywords if any, (e.g., 'fixed' or HEAPMAX(0x40000) ) to the oby line.
$line .= " ".($key);
if( defined $imgBin->{$key})
{
$line .= "(". $imgBin->{$key}. ") ";
}
}
print $fh "$line\n";
}
}
sub GetObyFiles
{
return \@ObyFileList;
}
sub GetBinarySelectionOrder
{
return \@binarySelectionArray;
}
sub GetFeatures()
{
my %FeatureMap = ();
my @FeatList;
my $featRef;
my $uid;
foreach my $feat (@Includes)
{
if($feat->{name})
{
$uid = &featureparser::getFeatureUID($feat->{name});
if(!defined $uid)
{
print "Error: Feature $feat->{name} not found in feature list XML\n";
next;
}
$feat->{uid} = $uid;
}
else
{
$uid = $feat->{uid};
if(!&featureparser::getFeatureInfo($uid))
{
print "Error: Feature Uid $uid not found in feature list XML\n";
next;
}
}
$featRef = $FeatureMap{$uid};
if( $featRef->{include} == 1 )
{
# Already added to the final feature list
}
else
{
$FeatureMap{$uid} = $feat;
push @FeatList, $feat;
}
}
foreach my $feat (@Excludes)
{
if($feat->{name})
{
$uid = &featureparser::getFeatureUID($feat->{name});
if(!defined $uid)
{
print "Error: Feature $feat->{name} not found in feature list XML\n";
next;
}
$feat->{uid} = $uid;
}
else
{
$uid = $feat->{uid};
if(!&featureparser::getFeatureInfo($uid))
{
print "Error: Feature Uid $uid not found in feature list XML\n";
next;
}
}
$featRef = $FeatureMap{$uid};
if( $featRef->{include} == 1 )
{
print "Error:The feature Uid $uid was added into the include as well as exclude list\n";
next;
}
elsif($featRef->{exclude} == 1)
{
# Already added to the final feature list
next;
}
else
{
$FeatureMap{$uid} = $feat;
push @FeatList, $feat;
}
}
return \@FeatList;
}
sub AddBinaryFromOby
{
my $aBinary = lc shift;
my $aFullPath = lc shift;
my $bin = \%{$obyFileInfo{$aBinary}};
$bin->{IsFoundInOby} = 1;
$bin->{fullpath} = $aFullPath;
}
sub GetObyBinaryInfo
{
my $aBinary = lc shift;
my $aBinaryInfoHash = \%{$obyFileInfo{$aBinary}};
if( $aBinaryInfoHash->{IsFoundInOby} == 1)
{
return $aBinaryInfoHash;
}
return undef;
}
sub UpdateObyBinaryStaticDep
{
# Go through the files added from Oby to see if any of their static
# dependencies need to be resolved.
foreach my $obyBin (keys %obyFileInfo)
{
if(!defined (&VisitedBinaryInfo($obyBin)) )
{
&ProcessStaticDep($obyFileInfo{$obyBin}{fullpath});
}
}
}
sub SaveImageContentBinaries
{
my ($binaryListRef, $aKeyword) = @_;
foreach my $node (@$binaryListRef)
{
my %binInfo = ();
# The keywords being primary, secondary, extension, variant and device
$binInfo{keyword} = $aKeyword;
my @children = &genericparser::getChildElements($node);
foreach my $child (@children)
{
my $name = &genericparser::getElementName($child);
my $val = &genericparser::getElementValue($child);
$binInfo{$name} = $val;
}
push @ImageContentBinaries, \%binInfo;
}
}
my %VisitedBinaries = ();
my @RomIncludeList;
sub ProcessCDFList {
my ($CDFListRef) = @_;
foreach my $cdf (@$CDFListRef)
{
&LoadFromCDF($cdf);
}
}
my @padding ;
sub LoadFromCDF
{
my $cdf;
my $binFile;
my @BinList;
($cdf, $binFile) = @_;
#Load the XML and get its contents
cdfparser::LoadCDF($cdf);
#Get all binaries from the mdf
(@BinList) = &cdfparser::GetBinaries($cdf);
my $DynBinListRef;
my $aBinary;
my $aFile;
my $VisitedBinaryInfoHash;
my $indent = join('', @padding);
my $binInfo;
foreach $aBinary (@BinList)
{
$VisitedBinaryInfoHash = &VisitedBinaryInfo($aBinary);
if($VisitedBinaryInfoHash)
{
next;
}
else
{
$VisitedBinaryInfoHash = \%{$VisitedBinaries{$aBinary}};
}
&ImageContentHandler::AddBinary($aBinary);
$VisitedBinaryInfoHash->{Marked} = 1;
push @RomIncludeList, $aBinary;
# Include the dynamic dependencies.
($DynBinListRef) = cdfparser::GetDynamicDependencies($aBinary);
foreach $aFile (@$DynBinListRef)
{
if(grep $aFile, @BinList)
{
# the dynamic dependency is found in the same cdf file which
# is already loaded.
next;
}
my $new_cdf = cdfparser::GetCDFFileName($aFile);
# In case there is no cdf describing this binary, ignore it.
if( defined $new_cdf )
{
push @padding, ".";
LoadFromCDF($new_cdf, $aFile);
}
}
$binInfo = cdfparser::GetBinaryInfo($aBinary);
&ProcessStaticDep($binInfo->{source}, $aBinary);
}
}
sub ProcessStaticDep
{
my ($aBinary) = @_;
my $aAbsFile;
# Include the static dependencies.
my $dir = "$ENV{EPOCROOT}epoc32\\release\\";
my $abidir = &ImageContentHandler::GetBldRomOpts("ABI_DIR");
my $blddir = &ImageContentHandler::GetBldRomOpts("BUILD_DIR");
if($aBinary =~ /(.*)\\.*/)
{
$aBinary =~ s/ABI_DIR/$abidir/i;
$aBinary =~ s/BUILD_DIR/$blddir/i;
$aBinary =~ s/DEBUG_DIR/udeb/i;
}
else
{
$dir .= $abidir . "\\";
$dir .= $blddir. "\\";
}
$aAbsFile = $dir. $aBinary;
if(!-f $aAbsFile)
{
# While evaluating the static dependency, check if the file is found in the
# default abi directory. Otherwise, look into the binary selection order.
my $binSelOrderRef = &ImageContentHandler::GetBinarySelectionOrder();
my $foundFile = 0;
foreach my $newAbiDir (@$binSelOrderRef)
{
$aAbsFile =~ s/$abidir/$newAbiDir/i;
if(-f $aAbsFile)
{
$foundFile = 1;
last;
}
$abidir = $newAbiDir;
}
if($foundFile == 0)
{
#While evaluating the static dependency, check if the file is found in the
#default abi directory. Otherwise, fallback to the default ARMV5 directory.
$foundFile = fallback($abidir, \$aAbsFile);
if($foundFile == 0)
{
return;
}
}
}
# Collect the static dependencies of this binary.
my (@StatDepsList) = &Dep_Lister::StaticDeps($aAbsFile);
# Remove the path portion from the file name if found to get the filename.
# This is the key into the BinaryInfo map maintained by cdfparser.
my $filename;
if( $aBinary =~ /.*\\(\S+)/)
{
$filename = $1;
}
else
{
$filename = $aBinary;
}
my $binaryInfoRef = cdfparser::GetBinaryInfo($filename);
if( defined $binaryInfoRef)
{
# Mark the binary it it is a valid E32 executable.
if(defined @StatDepsList)
{
$binaryInfoRef->{IsExecutable} = 1;
}
else
{
$binaryInfoRef->{IsExecutable} = 0;
}
}
my $VisitedBinaryInfoHash;
foreach my $aFile (@StatDepsList)
{
my $new_cdf = cdfparser::GetCDFFileName($aFile);
if(defined($new_cdf))
{
LoadFromCDF($new_cdf, $aFile);
}
else
{
# Include the static dependencies even if there is no mdf describing this binary
$VisitedBinaryInfoHash = &VisitedBinaryInfo($aFile);
if( !defined ($VisitedBinaryInfoHash) )
{
$VisitedBinaryInfoHash = \%{$VisitedBinaries{$aFile}};
$VisitedBinaryInfoHash->{Marked} = 1;
&ImageContentHandler::AddBinary($aFile);
&ProcessStaticDep($aFile);
}
else
{
}
}
}
}
sub VisitedBinaryInfo
{
my ($aBinary) = @_;
my $VisitedBinaryInfoHash = \%{$VisitedBinaries{$aBinary}};
if($VisitedBinaryInfoHash->{Marked} == 1)
{
return $VisitedBinaryInfoHash;
}
return undef;
}
1;