#
# 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;
use romutl;
#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 = &get_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 = &get_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;