diff -r 000000000000 -r 044383f39525 imgtools/buildrom/tools/ImageContentHandler.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/buildrom/tools/ImageContentHandler.pm Tue Oct 27 16:36:35 2009 +0000 @@ -0,0 +1,1550 @@ +# +# 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. abi_dir\udeb\drtaeabi.dll, 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;