diff -r 820b22e13ff1 -r 39c28ec933dd imgtools/buildrom/tools/featuresutil.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imgtools/buildrom/tools/featuresutil.pm Mon May 10 19:54:49 2010 +0100 @@ -0,0 +1,534 @@ +# +# Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of 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: +# + +package featuresutil; + + +require Exporter; +@ISA = qw(Exporter); +@EXPORT = qw( + parseXMLDatabase + createFeatureFile + convert_FeatRegToFeatMgr +); + +use strict; +use XML::Handler::XMLWriter; +use IO; + +use featureparser; +use featuremanager; +use featureregistry; +use featuresdat; +use featurecfg; + +my $xmlDBHandle = undef; #Object of feature parser + +my @includeFeatureList; #List of included features. The included feature in this list is a hash table giving the + #Uid or the name. These features are collected from the iby/obey files. +my @excludeFeatureList; #List of excluded features.The excluded feature in this list is a hash table giving the + #Uid or the name. These features are collected from the iby/obey files. + +my $verboseFlg = 0; # verbose mode flag +my $strictFlg = 1; # strict mode flag + +# Subroutine to generate warning messages. +sub WARN +{ + print "WARNING: ".$_[0]."\n"; +} + +# Subroutine to generate error messages. +sub ERROR +{ + print "ERROR: ".$_[0]."\n"; +} + +# Verbose mode output routine +sub MSG +{ + if($verboseFlg) { + print "**".$_[0]."...\n"; + } +} + +# Subroutine to parse feature list XML database file. +# @param dbfileList - List of XML database file names seperated by commas. +# @param fmFlag - Flag to generate features data file. +# @param strictFlg - Flag to enable strict mode (optional). +# @param verboseFlg - Flag to enable verbose mode (optional). +sub parseXMLDatabase +{ + my $dbfileList = shift; + my $fmFlag = shift; + $strictFlg = shift; + $verboseFlg = shift; + + # list of xml databases + my @filelist = split(/,/,$dbfileList); + + # return status + my $retStatus = 0; + + # default mode is strict + $strictFlg=0 if(!defined $strictFlg); + # default mode is nonverbose + $verboseFlg=0 if(!defined $verboseFlg); + + # multiple file support is not applicable for feature registry option + if( (@filelist > 1) && (!$fmFlag) ) { + &ERROR("Multiple XML database file support is not applicable for featureregistry option"); + return 0; + } + + if($fmFlag) # Feature manager option handling + { + # create the object of feature manager class + $xmlDBHandle = new featuremanager; + + if($xmlDBHandle) { + foreach my $file (@filelist) + { + my $status = 1; + if(-e $file) { + + &MSG("Parsing $file"); + + # parse the feature manager xml file + $status = $xmlDBHandle->parseXMLFile($file); + if(! $status) { + + # create the object of feature registry class + my $registryObj = new featureregistry; + # parse the feature registry xml file + $status = $registryObj->parseXMLFile($file); + if($status < 0) { + if($strictFlg) { + &ERROR("Invalid features database $file"); + $xmlDBHandle = undef; + return 0; + } + else { + &WARN("Invalid features database $file"); + } + } + elsif(! $status) { + # if the xml file is not valid feature list xml file + if($strictFlg) { + &ERROR("Error in reading features database file \"$file\""); + $xmlDBHandle = undef; + return 0; + } + else { + &WARN("Error in reading features database file \"$file\""); + } + } + else { + MSG("Converting featureregistry database to featuremanager"); + + # add the feature registry file object to the feature manager file object + if(! $xmlDBHandle->addFeatureRegistry($registryObj)) { + if($strictFlg) { + MSG("Error in reading features database file \"$file\""); + $xmlDBHandle = undef; + return 0; + } + else { + &WARN("Error in reading features database file \"$file\""); + } + } + else { + # parsing feature registry database success + $retStatus = 1; + } + } + } + elsif( $status < 0 ) { + if($strictFlg) { + &ERROR("Invalid features database $file"); + $xmlDBHandle = undef; + return 0; + } + else { + &WARN("Invalid features database $file"); + } + } + else { + # parsing feature manager database success + $retStatus = 1; + } + } + else { + if(!$strictFlg) { + &WARN($file." doesn\'t exist"); + next; + } + else { + &ERROR($file." doesn\'t exist"); + $xmlDBHandle = undef; + return 0; + } + } + } + } + else { + &ERROR("Couldn't create feature parser object"); + } + } + else # Feature registry file handling + { + if(@filelist) { + my $file = $filelist[0]; + $xmlDBHandle = new featureregistry; + + if($xmlDBHandle) { + if(-e $file) { + + MSG("Parsing $file"); + + my $status = $xmlDBHandle->parseXMLFile($file); + + if($status < 0) { + &ERROR($file." is invalid feature registry file"); + $xmlDBHandle = undef; + return 0; + } + elsif(!$status) { + &ERROR("Error in reading feature registry file ".$file); + $xmlDBHandle = undef; + } + else { + # parsing feature registry database success + $retStatus = 1; + } + } + else { + if(!$strictFlg) { + &WARN($file." doesn\'t exist -- "); + } + else { + &ERROR($file." doesn\'t exist -- "); + } + $xmlDBHandle = undef; + } + } + else { + &ERROR("Couldn't create feature parser object"); + } + } + } + + if($retStatus) { + return $xmlDBHandle + } + else { + return $retStatus; + } +} + +# Subroutine to generate feature manager database file from the given feature registry database +# @param strictFlg - strict mode flag +# @param verboseFlg - verbose mode flag +# @param outpath - destination path for the converted database file(s) +# @param dblist - list of xml file names +sub convert_FeatRegToFeatMgr +{ + $strictFlg = shift; + $verboseFlg = shift; + my $outpath = shift; + my @dblist = @_; + + # default mode is strict + $strictFlg=0 if(!defined $strictFlg); + # default mode is nonverbose + $verboseFlg=0 if(!defined $verboseFlg); + + foreach my $file (@dblist) + { + # Create the object of feature registry + my $fileHandle = new featureregistry; + + if(-e $file) { + # Parse the database + if($fileHandle->parseXMLFile($file) > 0) { + MSG("Converting Feature Registry database $file"); + + # Create directory if it doesn't exists + if(!(-e $outpath)) { + if(!mkdir($outpath)) { + &ERROR("Failed to create $outpath folder"); + return 0; + } + } + # Emit the contents of feature registry object into an feature manager database file + &generateXML($fileHandle, $outpath); + } + } + else { + if(!$strictFlg) { + &WARN($file." doesn\'t exist -- "); + next; + } + else { + &ERROR($file." doesn\'t exist -- "); + return 0; + } + } + } +} + +# Subroutine to emit XML output for the given featureregistry object +# @param frObject - object of feature registry database +# @param outPath - destination path for the converted database file +sub generateXML +{ + my ($frObject, $outPath) = @_; + + my $outputFile = $frObject->fileName(); + + # Extract absolute file name + if( $outputFile =~ /[\\\/]/) { + $outputFile =~ /.*[\\\/](.+)\z/; + $outputFile = $1; + } + + # Add suffix _converted + $outputFile =~ s/(.*)([\.].+)\z/$1_converted$2/; + + my $fileHandle = new IO::File(">$outPath$outputFile"); + + if($fileHandle) { + my $writer = XML::Handler::XMLWriter->new(Output => $fileHandle); + + # Header + $writer->start_document(); + $writer->print("\n\n"); + # DOCTYPE + $writer->print("\n\n"); + + # Root element begin + $writer->start_element({Name => 'featuredatabase', Attributes => {}}); + + # FeatureSet element + $writer->print("\n\t"); + $writer->start_element({Name => 'featureset', Attributes => {}}); + my $nameuidmap = $frObject->featureNameUidMap(); + foreach my $uid (sort(values %$nameuidmap)) { + my $featinfo = $frObject->getFeatureInfo($uid); + my %attributes = (); + + $attributes{uid} = sprintf("0x%08X",$uid); + $attributes{statusflags} = "0x00000001"; + $attributes{name} = $featinfo->{name}; + + $writer->print("\n\t\t"); + $writer->start_element({Name => 'feature', Attributes => \%attributes}); + $writer->end_element({Name => 'feature'}); + } + $writer->print("\n\t"); + $writer->end_element({Name => 'featureset'}); + + # defaultfeaturerange element + my $rangeList = $frObject->defaultRangeList(); + foreach my $range (@$rangeList) { + my %attributes = (); + + next if(lc($range->{support}) eq "exclude"); + + $attributes{higheruid} = sprintf("0x%08X",$range->{max}); + $attributes{loweruid} = sprintf("0x%08X",$range->{min}); + + $writer->print("\n\t"); + $writer->start_element({Name => 'defaultfeaturerange', Attributes => \%attributes}); + $writer->end_element({Name => 'defaultfeaturerange'}); + } + + # Root element close + $writer->print("\n"); + $writer->end_element({Name => 'featuredatabase'}); + + # Footer + $writer->end_document(); + } + else { + &ERROR("Failed to create $outPath$outputFile file"); + } +} + +# Subroutine to create Feature Registry/Features Data file +# @param romimage - Rom image number. +# @param featurefile - Feature file number. +# @param featurefilename - Name of the feature file to be generated. +# @param featureslist - Reference to array of hashes containing features to included/excluded. +# @param featuremanager - Flag to generate features data file. +# @param singleDATfile - Flag to generate single features.dat file. +sub createFeatureFile +{ + if($xmlDBHandle == undef) + { + ERROR("No XML Database opened"); + return 0; + } + my ($romimage,$featurefile,$featurefilename,$featureslist,$featuremanager,$singleDATfile) = @_; + + # Default setting for singleDATfile flag + $singleDATfile = 0 if(!defined $singleDATfile); + + # Clear the global include/exclude feature list. + @includeFeatureList = (); + @excludeFeatureList = (); + + + for(my $k=0;$k[$k]{rom}==$romimage && $featureslist->[$k]{cfgfile} == $featurefile)) + { + AddToFeatureList($featureslist->[$k],$featuremanager); + } + } + + my $features = &featureparser::getFeatures(\@includeFeatureList, \@excludeFeatureList); + if (!$features) + { + ERROR("No feature file generated for ROM_IMAGE[".$romimage."]"); + return 0; + } + else + { + my $object; + if ($featuremanager) + { + $object = new featuresdat($xmlDBHandle); + } + else + { + $object = new featurecfg($xmlDBHandle); + } + return $object->createFile($featurefilename, $features , $featuremanager); + } +} + +# Subroutine to add the feature specified to the included/excluded feature list +# @param featureData - Reference to hash containing feature information (i.e. name/uid, +# included/excluded,SF and UD). +# @param featuremanager - Flag to generate features data file. +sub AddToFeatureList +{ + my ($featureData, $featuremanager) = @_; + + my %feat = (); + my $feature = $featureData->{feature}; + +# Check if the given value is a feature name. + my $value = $xmlDBHandle->getFeatureUID($feature); + +# If not a feature, then may be uid value + if(!defined $value) + { + if (!featureparser::IsValidNum($feature)) + { + ERROR("Feature \"".$feature."\" not found in feature list XML"); + return; + } + if (&featureparser::ValidateUIDValue($feature)) + { + my $featureUid = $feature; + $feature = &featureparser::ConvertHexToDecimal($feature); + my $featureInfo = $xmlDBHandle->getFeatureInfo($feature); + if (!$featureInfo) + { + ERROR("Feature \"".$featureUid."\" not found in feature list XML"); + return; + } + else + { + $feat{uid} = $feature; + $feat{name} = $featureInfo->{name}; + } + } + else + { + return; + } + } + else + { + $feat{name} = $feature; + $feat{uid} = $value; + } + + # Set the values of "SF" and "UD" for feature manager. + if ($featuremanager) + { + &setFeatureArguments(\%feat,$featureData->{SF},$featureData->{UD}); + } + + if($featureData->{include} == 1) + { + $feat{include} = 1; + push @includeFeatureList, \%feat; + } + else + { + $feat{exclude} = 1; + push @excludeFeatureList, \%feat; + } +} + +# Subroutine to set the values of "SF" and "UD" for the specified feature +# @param feat - Reference to hash containing information(i.e. name and uid) +# of the specified feature. +# @param SF - Value of "SF" provided in the iby/oby file. +# @param UD - Value of "UD" provided in the iby/oby file. +sub setFeatureArguments +{ + my($feat,$SF,$UD)= @_; + + my $featureInfo = $xmlDBHandle->getFeatureInfo($feat->{uid}); + + # If the values of 'SF' and 'UD' are not provided in the iby/oby file, then take the values + # from Feature Database XML file. + if ($SF && featureparser::IsValidNum($SF)) + { + $feat->{SF} = &featureparser::ConvertHexToDecimal($SF); + } + else + { + # Generate warning if the value of "SF" provided for the feature in iby/oby file + # is invalid. + if ($SF) + { + WARN("Invalid SF value \"$SF\" provided for feature \"$feat->{name}\". Defaulting to value provided in XML file"); + } + $feat->{SF} = &featureparser::ConvertHexToDecimal($featureInfo->{statusflags}); + } + if ($UD && featureparser::IsValidNum($UD)) + { + $feat->{UD} = &featureparser::ConvertHexToDecimal($UD); + } + else + { + # Generate warning if the value of "UD" provided for the feature in iby/oby file + # is invalid. + if ($UD) + { + WARN("Invalid UD value \"$UD\" provided for feature \"$feat->{name}\". Defaulting to value provided in XML file"); + } + $feat->{UD} = &featureparser::ConvertHexToDecimal($featureInfo->{userdata}); + } +} + +1;