2009-07-17 11:10:31 +02:00
## @file
# process FFS generation from INF statement
#
2011-05-11 12:26:49 +02:00
# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
2009-07-17 11:10:31 +02:00
#
2010-05-18 07:04:32 +02:00
# This program and the accompanying materials
2009-07-17 11:10:31 +02:00
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
# Import Modules
#
import Rule
import os
import shutil
2011-05-11 12:26:49 +02:00
import StringIO
from struct import *
2009-07-17 11:10:31 +02:00
from GenFdsGlobalVariable import GenFdsGlobalVariable
import Ffs
import subprocess
import sys
import Section
import RuleSimpleFile
import RuleComplexFile
from CommonDataClass . FdfClass import FfsInfStatementClassObject
from Common . String import *
from Common . Misc import PathClass
from Common . Misc import GuidStructureByteArrayToGuidString
from Common import EdkLogger
from Common . BuildToolError import *
2010-03-01 00:39:39 +01:00
from GuidSection import GuidSection
from FvImageSection import FvImageSection
from Common . Misc import PeImageClass
2011-09-18 14:17:25 +02:00
from AutoGen . GenDepex import DependencyExpression
2009-07-17 11:10:31 +02:00
## generate FFS from INF
#
#
class FfsInfStatement ( FfsInfStatementClassObject ) :
## The constructor
#
# @param self The object pointer
#
def __init__ ( self ) :
FfsInfStatementClassObject . __init__ ( self )
self . TargetOverrideList = [ ]
self . ShadowFromInfFile = None
self . KeepRelocFromRule = None
self . InDsc = True
self . OptRomDefs = { }
2011-05-11 12:26:49 +02:00
self . PiSpecVersion = ' 0x00000000 '
2011-08-26 09:46:26 +02:00
self . InfModule = None
2011-09-18 14:17:25 +02:00
self . FinalTargetSuffixMap = { }
2011-08-26 09:46:26 +02:00
2011-09-18 14:17:25 +02:00
## GetFinalTargetSuffixMap() method
2011-08-26 09:46:26 +02:00
#
# Get final build target list
2011-09-18 14:17:25 +02:00
def GetFinalTargetSuffixMap ( self ) :
2011-08-26 09:46:26 +02:00
if not self . InfModule or not self . CurrentArch :
return [ ]
2011-09-18 14:17:25 +02:00
if not self . FinalTargetSuffixMap :
FinalBuildTargetList = GenFdsGlobalVariable . GetModuleCodaTargetList ( self . InfModule , self . CurrentArch )
for File in FinalBuildTargetList :
self . FinalTargetSuffixMap . setdefault ( os . path . splitext ( File ) [ 1 ] , [ ] ) . append ( File )
# Check if current INF module has DEPEX
if ' .depex ' not in self . FinalTargetSuffixMap and self . InfModule . ModuleType != " USER_DEFINED " \
and not self . InfModule . DxsFile and not self . InfModule . LibraryClass :
ModuleType = self . InfModule . ModuleType
PlatformDataBase = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , self . CurrentArch , GenFdsGlobalVariable . TargetName , GenFdsGlobalVariable . ToolChainTag ]
if ModuleType != DataType . SUP_MODULE_USER_DEFINED :
for LibraryClass in PlatformDataBase . LibraryClasses . GetKeys ( ) :
if LibraryClass . startswith ( " NULL " ) and PlatformDataBase . LibraryClasses [ LibraryClass , ModuleType ] :
self . InfModule . LibraryClasses [ LibraryClass ] = PlatformDataBase . LibraryClasses [ LibraryClass , ModuleType ]
StrModule = str ( self . InfModule )
PlatformModule = None
if StrModule in PlatformDataBase . Modules :
PlatformModule = PlatformDataBase . Modules [ StrModule ]
for LibraryClass in PlatformModule . LibraryClasses :
if LibraryClass . startswith ( " NULL " ) :
self . InfModule . LibraryClasses [ LibraryClass ] = PlatformModule . LibraryClasses [ LibraryClass ]
DependencyList = [ self . InfModule ]
LibraryInstance = { }
DepexList = [ ]
while len ( DependencyList ) > 0 :
Module = DependencyList . pop ( 0 )
if not Module :
continue
for Dep in Module . Depex [ self . CurrentArch , ModuleType ] :
if DepexList != [ ] :
DepexList . append ( ' AND ' )
DepexList . append ( ' ( ' )
DepexList . extend ( Dep )
if DepexList [ - 1 ] == ' END ' : # no need of a END at this time
DepexList . pop ( )
DepexList . append ( ' ) ' )
if ' BEFORE ' in DepexList or ' AFTER ' in DepexList :
break
for LibName in Module . LibraryClasses :
if LibName in LibraryInstance :
continue
if PlatformModule and LibName in PlatformModule . LibraryClasses :
LibraryPath = PlatformModule . LibraryClasses [ LibName ]
else :
LibraryPath = PlatformDataBase . LibraryClasses [ LibName , ModuleType ]
if not LibraryPath :
LibraryPath = Module . LibraryClasses [ LibName ]
if not LibraryPath :
continue
LibraryModule = GenFdsGlobalVariable . WorkSpace . BuildObject [ LibraryPath , self . CurrentArch , GenFdsGlobalVariable . TargetName , GenFdsGlobalVariable . ToolChainTag ]
LibraryInstance [ LibName ] = LibraryModule
DependencyList . append ( LibraryModule )
if DepexList :
Dpx = DependencyExpression ( DepexList , ModuleType , True )
if len ( Dpx . PostfixNotation ) != 0 :
# It means this module has DEPEX
self . FinalTargetSuffixMap [ ' .depex ' ] = [ os . path . join ( self . EfiOutputPath , self . BaseName ) + ' .depex ' ]
return self . FinalTargetSuffixMap
2011-08-26 09:46:26 +02:00
2009-07-17 11:10:31 +02:00
## __InfParse() method
#
# Parse inf file to get module information
#
# @param self The object pointer
# @param Dict dictionary contains macro and value pair
#
def __InfParse__ ( self , Dict = { } ) :
GenFdsGlobalVariable . VerboseLogger ( " Begine parsing INf file : %s " % self . InfFileName )
self . InfFileName = self . InfFileName . replace ( ' $(WORKSPACE) ' , ' ' )
if self . InfFileName [ 0 ] == ' \\ ' or self . InfFileName [ 0 ] == ' / ' :
self . InfFileName = self . InfFileName [ 1 : ]
if self . InfFileName . find ( ' $ ' ) == - 1 :
InfPath = NormPath ( self . InfFileName )
if not os . path . exists ( InfPath ) :
InfPath = GenFdsGlobalVariable . ReplaceWorkspaceMacro ( InfPath )
if not os . path . exists ( InfPath ) :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , " Non-existant Module %s ! " % ( self . InfFileName ) )
self . CurrentArch = self . GetCurrentArch ( )
#
# Get the InfClass object
#
PathClassObj = PathClass ( self . InfFileName , GenFdsGlobalVariable . WorkSpaceDir )
2010-09-06 03:58:00 +02:00
ErrorCode , ErrorInfo = PathClassObj . Validate ( " .inf " )
2009-07-17 11:10:31 +02:00
if ErrorCode != 0 :
EdkLogger . error ( " GenFds " , ErrorCode , ExtraData = ErrorInfo )
if self . CurrentArch != None :
Inf = GenFdsGlobalVariable . WorkSpace . BuildObject [ PathClassObj , self . CurrentArch ]
#
# Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath
#
self . BaseName = Inf . BaseName
self . ModuleGuid = Inf . Guid
self . ModuleType = Inf . ModuleType
2010-03-01 00:39:39 +01:00
if Inf . Specification != None and ' PI_SPECIFICATION_VERSION ' in Inf . Specification :
2009-11-09 12:47:35 +01:00
self . PiSpecVersion = Inf . Specification [ ' PI_SPECIFICATION_VERSION ' ]
2009-07-17 11:10:31 +02:00
if Inf . AutoGenVersion < 0x00010005 :
self . ModuleType = Inf . ComponentType
self . VersionString = Inf . Version
self . BinFileList = Inf . Binaries
self . SourceFileList = Inf . Sources
if self . KeepReloc == None and Inf . Shadow :
self . ShadowFromInfFile = Inf . Shadow
else :
Inf = GenFdsGlobalVariable . WorkSpace . BuildObject [ PathClassObj , ' COMMON ' ]
self . BaseName = Inf . BaseName
self . ModuleGuid = Inf . Guid
self . ModuleType = Inf . ModuleType
2010-03-01 00:39:39 +01:00
if Inf . Specification != None and ' PI_SPECIFICATION_VERSION ' in Inf . Specification :
2009-11-09 12:47:35 +01:00
self . PiSpecVersion = Inf . Specification [ ' PI_SPECIFICATION_VERSION ' ]
2009-07-17 11:10:31 +02:00
self . VersionString = Inf . Version
self . BinFileList = Inf . Binaries
self . SourceFileList = Inf . Sources
if self . BinFileList == [ ] :
EdkLogger . error ( " GenFds " , GENFDS_ERROR ,
" INF %s specified in FDF could not be found in build ARCH %s ! " \
% ( self . InfFileName , GenFdsGlobalVariable . ArchList ) )
if len ( self . SourceFileList ) != 0 and not self . InDsc :
EdkLogger . warn ( " GenFds " , GENFDS_ERROR , " Module %s NOT found in DSC file; Is it really a binary module? " % ( self . InfFileName ) )
2011-05-11 12:26:49 +02:00
if self . ModuleType == ' SMM_CORE ' and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
2009-11-09 12:47:35 +01:00
EdkLogger . error ( " GenFds " , FORMAT_NOT_SUPPORTED , " SMM_CORE module type can ' t be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A " , File = self . InfFileName )
2009-07-17 11:10:31 +02:00
if Inf . _Defs != None and len ( Inf . _Defs ) > 0 :
self . OptRomDefs . update ( Inf . _Defs )
2011-08-26 09:46:26 +02:00
self . InfModule = Inf
2009-07-17 11:10:31 +02:00
GenFdsGlobalVariable . VerboseLogger ( " BaseName : %s " % self . BaseName )
GenFdsGlobalVariable . VerboseLogger ( " ModuleGuid : %s " % self . ModuleGuid )
GenFdsGlobalVariable . VerboseLogger ( " ModuleType : %s " % self . ModuleType )
GenFdsGlobalVariable . VerboseLogger ( " VersionString : %s " % self . VersionString )
GenFdsGlobalVariable . VerboseLogger ( " InfFileName : %s " % self . InfFileName )
#
# Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\
#
self . OutputPath = os . path . join ( GenFdsGlobalVariable . FfsDir , \
self . ModuleGuid + self . BaseName )
if not os . path . exists ( self . OutputPath ) :
os . makedirs ( self . OutputPath )
self . EfiOutputPath = self . __GetEFIOutPutPath__ ( )
GenFdsGlobalVariable . VerboseLogger ( " ModuelEFIPath: " + self . EfiOutputPath )
## GenFfs() method
#
# Generate FFS
#
2010-03-01 00:39:39 +01:00
# @param self The object pointer
# @param Dict dictionary contains macro and value pair
# @param FvChildAddr Array of the inside FvImage base address
# @param FvParentAddr Parent Fv base address
# @retval string Generated FFS file name
2009-07-17 11:10:31 +02:00
#
2010-03-01 00:39:39 +01:00
def GenFfs ( self , Dict = { } , FvChildAddr = [ ] , FvParentAddr = None ) :
2009-07-17 11:10:31 +02:00
#
# Parse Inf file get Module related information
#
self . __InfParse__ ( Dict )
2010-11-15 03:51:34 +01:00
#
# Allow binary type module not specify override rule in FDF file.
#
if len ( self . BinFileList ) > 0 and not self . InDsc :
if self . Rule == None or self . Rule == " " :
self . Rule = " BINARY "
2009-07-17 11:10:31 +02:00
#
# Get the rule of how to generate Ffs file
#
Rule = self . __GetRule__ ( )
GenFdsGlobalVariable . VerboseLogger ( " Packing binaries from inf file : %s " % self . InfFileName )
2009-11-09 12:47:35 +01:00
#
# Convert Fv File Type for PI1.1 SMM driver.
#
2011-05-11 12:26:49 +02:00
if self . ModuleType == ' DXE_SMM_DRIVER ' and int ( self . PiSpecVersion , 16 ) > = 0x0001000A :
2009-11-09 12:47:35 +01:00
if Rule . FvFileType == ' DRIVER ' :
Rule . FvFileType = ' SMM '
#
# Framework SMM Driver has no SMM FV file type
#
2011-05-11 12:26:49 +02:00
if self . ModuleType == ' DXE_SMM_DRIVER ' and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
2009-11-09 12:47:35 +01:00
if Rule . FvFileType == ' SMM ' or Rule . FvFileType == ' SMM_CORE ' :
EdkLogger . error ( " GenFds " , FORMAT_NOT_SUPPORTED , " Framework SMM module doesn ' t support SMM or SMM_CORE FV file type " , File = self . InfFileName )
2009-07-17 11:10:31 +02:00
#
# For the rule only has simpleFile
#
if isinstance ( Rule , RuleSimpleFile . RuleSimpleFile ) :
SectionOutputList = self . __GenSimpleFileSection__ ( Rule )
FfsOutput = self . __GenSimpleFileFfs__ ( Rule , SectionOutputList )
return FfsOutput
#
# For Rule has ComplexFile
#
elif isinstance ( Rule , RuleComplexFile . RuleComplexFile ) :
2010-03-01 00:39:39 +01:00
InputSectList , InputSectAlignments = self . __GenComplexFileSection__ ( Rule , FvChildAddr , FvParentAddr )
2009-07-17 11:10:31 +02:00
FfsOutput = self . __GenComplexFileFfs__ ( Rule , InputSectList , InputSectAlignments )
return FfsOutput
## __ExtendMacro__() method
#
# Replace macro with its value
#
# @param self The object pointer
# @param String The string to be replaced
# @retval string Macro replaced string
#
def __ExtendMacro__ ( self , String ) :
MacroDict = {
' $(INF_OUTPUT) ' : self . EfiOutputPath ,
' $(MODULE_NAME) ' : self . BaseName ,
' $(BUILD_NUMBER) ' : self . BuildNum ,
' $(INF_VERSION) ' : self . VersionString ,
' $(NAMED_GUID) ' : self . ModuleGuid
}
String = GenFdsGlobalVariable . MacroExtend ( String , MacroDict )
return String
## __GetRule__() method
#
# Get correct rule for generating FFS for this INF
#
# @param self The object pointer
# @retval Rule Rule object
#
def __GetRule__ ( self ) :
CurrentArchList = [ ]
if self . CurrentArch == None :
CurrentArchList = [ ' common ' ]
else :
CurrentArchList . append ( self . CurrentArch )
for CurrentArch in CurrentArchList :
RuleName = ' RULE ' + \
' . ' + \
CurrentArch . upper ( ) + \
' . ' + \
self . ModuleType . upper ( )
if self . Rule != None :
RuleName = RuleName + \
' . ' + \
self . Rule . upper ( )
Rule = GenFdsGlobalVariable . FdfParser . Profile . RuleDict . get ( RuleName )
if Rule != None :
GenFdsGlobalVariable . VerboseLogger ( " Want To Find Rule Name is : " + RuleName )
return Rule
RuleName = ' RULE ' + \
' . ' + \
' COMMON ' + \
' . ' + \
self . ModuleType . upper ( )
if self . Rule != None :
RuleName = RuleName + \
' . ' + \
self . Rule . upper ( )
GenFdsGlobalVariable . VerboseLogger ( ' Trying to apply common rule %s for INF %s ' % ( RuleName , self . InfFileName ) )
Rule = GenFdsGlobalVariable . FdfParser . Profile . RuleDict . get ( RuleName )
if Rule != None :
GenFdsGlobalVariable . VerboseLogger ( " Want To Find Rule Name is : " + RuleName )
return Rule
if Rule == None :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , ' Don \' t Find common rule %s for INF %s ' \
% ( RuleName , self . InfFileName ) )
## __GetPlatformArchList__() method
#
# Get Arch list this INF built under
#
# @param self The object pointer
# @retval list Arch list
#
def __GetPlatformArchList__ ( self ) :
InfFileKey = os . path . normpath ( os . path . join ( GenFdsGlobalVariable . WorkSpaceDir , self . InfFileName ) )
DscArchList = [ ]
PlatformDataBase = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , ' IA32 ' ]
if PlatformDataBase != None :
if InfFileKey in PlatformDataBase . Modules :
DscArchList . append ( ' IA32 ' )
PlatformDataBase = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , ' X64 ' ]
if PlatformDataBase != None :
if InfFileKey in PlatformDataBase . Modules :
DscArchList . append ( ' X64 ' )
PlatformDataBase = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , ' IPF ' ]
if PlatformDataBase != None :
if InfFileKey in ( PlatformDataBase . Modules ) :
DscArchList . append ( ' IPF ' )
PlatformDataBase = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , ' ARM ' ]
if PlatformDataBase != None :
if InfFileKey in ( PlatformDataBase . Modules ) :
DscArchList . append ( ' ARM ' )
PlatformDataBase = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , ' EBC ' ]
if PlatformDataBase != None :
if InfFileKey in ( PlatformDataBase . Modules ) :
DscArchList . append ( ' EBC ' )
return DscArchList
## GetCurrentArch() method
#
# Get Arch list of the module from this INF is to be placed into flash
#
# @param self The object pointer
# @retval list Arch list
#
def GetCurrentArch ( self ) :
TargetArchList = GenFdsGlobalVariable . ArchList
PlatformArchList = self . __GetPlatformArchList__ ( )
CurArchList = TargetArchList
if PlatformArchList != [ ] :
CurArchList = list ( set ( TargetArchList ) & set ( PlatformArchList ) )
GenFdsGlobalVariable . VerboseLogger ( " Valid target architecture(s) is : " + " " . join ( CurArchList ) )
ArchList = [ ]
if self . KeyStringList != [ ] :
for Key in self . KeyStringList :
Key = GenFdsGlobalVariable . MacroExtend ( Key )
Target , Tag , Arch = Key . split ( ' _ ' )
if Arch in CurArchList :
ArchList . append ( Arch )
if Target not in self . TargetOverrideList :
self . TargetOverrideList . append ( Target )
else :
ArchList = CurArchList
UseArchList = TargetArchList
if self . UseArch != None :
UseArchList = [ ]
UseArchList . append ( self . UseArch )
ArchList = list ( set ( UseArchList ) & set ( ArchList ) )
self . InfFileName = NormPath ( self . InfFileName )
if len ( PlatformArchList ) == 0 :
self . InDsc = False
PathClassObj = PathClass ( self . InfFileName , GenFdsGlobalVariable . WorkSpaceDir )
2010-09-06 03:58:00 +02:00
ErrorCode , ErrorInfo = PathClassObj . Validate ( " .inf " )
2009-07-17 11:10:31 +02:00
if ErrorCode != 0 :
EdkLogger . error ( " GenFds " , ErrorCode , ExtraData = ErrorInfo )
if len ( ArchList ) == 1 :
Arch = ArchList [ 0 ]
return Arch
elif len ( ArchList ) > 1 :
if len ( PlatformArchList ) == 0 :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , " GenFds command line option has multiple ARCHs %s . Not able to determine which ARCH is valid for Module %s ! " % ( str ( ArchList ) , self . InfFileName ) )
else :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , " Module built under multiple ARCHs %s . Not able to determine which output to put into flash for Module %s ! " % ( str ( ArchList ) , self . InfFileName ) )
else :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , " Module %s appears under ARCH %s in platform %s , but current deduced ARCH is %s , so NO build output could be put into flash. " \
% ( self . InfFileName , str ( PlatformArchList ) , GenFdsGlobalVariable . ActivePlatform , str ( set ( UseArchList ) & set ( TargetArchList ) ) ) )
## __GetEFIOutPutPath__() method
#
# Get the output path for generated files
#
# @param self The object pointer
# @retval string Path that output files from this INF go to
#
def __GetEFIOutPutPath__ ( self ) :
Arch = ' '
OutputPath = ' '
( ModulePath , FileName ) = os . path . split ( self . InfFileName )
Index = FileName . find ( ' . ' )
FileName = FileName [ 0 : Index ]
Arch = " NoneArch "
if self . CurrentArch != None :
Arch = self . CurrentArch
OutputPath = os . path . join ( GenFdsGlobalVariable . OutputDirDict [ Arch ] ,
Arch ,
ModulePath ,
FileName ,
' OUTPUT '
)
OutputPath = os . path . realpath ( OutputPath )
return OutputPath
## __GenSimpleFileSection__() method
#
# Generate section by specified file name or a list of files with file extension
#
# @param self The object pointer
# @param Rule The rule object used to generate section
# @retval string File name of the generated section file
#
def __GenSimpleFileSection__ ( self , Rule ) :
#
# Prepare the parameter of GenSection
#
FileList = [ ]
OutputFileList = [ ]
2010-03-01 00:39:39 +01:00
GenSecInputFile = None
2009-07-17 11:10:31 +02:00
if Rule . FileName != None :
GenSecInputFile = self . __ExtendMacro__ ( Rule . FileName )
2011-05-11 12:26:49 +02:00
if os . path . isabs ( GenSecInputFile ) :
GenSecInputFile = os . path . normpath ( GenSecInputFile )
else :
2010-03-01 00:39:39 +01:00
GenSecInputFile = os . path . normpath ( os . path . join ( self . EfiOutputPath , GenSecInputFile ) )
2009-07-17 11:10:31 +02:00
else :
FileList , IsSect = Section . Section . GetFileList ( self , ' ' , Rule . FileExtension )
Index = 1
2009-11-09 12:47:35 +01:00
SectionType = Rule . SectionType
#
# Convert Fv Section Type for PI1.1 SMM driver.
#
2011-05-11 12:26:49 +02:00
if self . ModuleType == ' DXE_SMM_DRIVER ' and int ( self . PiSpecVersion , 16 ) > = 0x0001000A :
2009-11-09 12:47:35 +01:00
if SectionType == ' DXE_DEPEX ' :
SectionType = ' SMM_DEPEX '
#
# Framework SMM Driver has no SMM_DEPEX section type
#
2011-05-11 12:26:49 +02:00
if self . ModuleType == ' DXE_SMM_DRIVER ' and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
2009-11-09 12:47:35 +01:00
if SectionType == ' SMM_DEPEX ' :
EdkLogger . error ( " GenFds " , FORMAT_NOT_SUPPORTED , " Framework SMM module doesn ' t support SMM_DEPEX section type " , File = self . InfFileName )
2009-07-17 11:10:31 +02:00
NoStrip = True
if self . ModuleType in ( ' SEC ' , ' PEI_CORE ' , ' PEIM ' ) :
if self . KeepReloc != None :
NoStrip = self . KeepReloc
elif Rule . KeepReloc != None :
NoStrip = Rule . KeepReloc
elif self . ShadowFromInfFile != None :
NoStrip = self . ShadowFromInfFile
if FileList != [ ] :
for File in FileList :
SecNum = ' %d ' % Index
GenSecOutputFile = self . __ExtendMacro__ ( Rule . NameGuid ) + \
Ffs . Ffs . SectionSuffix [ SectionType ] + ' SEC ' + SecNum
Index = Index + 1
OutputFile = os . path . join ( self . OutputPath , GenSecOutputFile )
2010-03-01 00:39:39 +01:00
File = GenFdsGlobalVariable . MacroExtend ( File , Dict , self . CurrentArch )
#Get PE Section alignment when align is set to AUTO
if self . Alignment == ' Auto ' and ( SectionType == ' PE32 ' or SectionType == ' TE ' ) :
ImageObj = PeImageClass ( File )
if ImageObj . SectionAlignment < 0x400 :
self . Alignment = str ( ImageObj . SectionAlignment )
else :
self . Alignment = str ( ImageObj . SectionAlignment / 0x400 ) + ' K '
2009-07-17 11:10:31 +02:00
if not NoStrip :
FileBeforeStrip = os . path . join ( self . OutputPath , ModuleName + ' .reloc ' )
if not os . path . exists ( FileBeforeStrip ) or \
( os . path . getmtime ( File ) > os . path . getmtime ( FileBeforeStrip ) ) :
shutil . copyfile ( File , FileBeforeStrip )
StrippedFile = os . path . join ( self . OutputPath , ModuleName + ' .stipped ' )
GenFdsGlobalVariable . GenerateFirmwareImage (
StrippedFile ,
2010-03-01 00:39:39 +01:00
[ File ] ,
2009-07-17 11:10:31 +02:00
Strip = True
)
File = StrippedFile
if SectionType == ' TE ' :
TeFile = os . path . join ( self . OutputPath , self . ModuleGuid + ' Te.raw ' )
GenFdsGlobalVariable . GenerateFirmwareImage (
TeFile ,
2010-03-01 00:39:39 +01:00
[ File ] ,
2009-07-17 11:10:31 +02:00
Type = ' te '
)
File = TeFile
GenFdsGlobalVariable . GenerateSection ( OutputFile , [ File ] , Section . Section . SectionType [ SectionType ] )
OutputFileList . append ( OutputFile )
else :
SecNum = ' %d ' % Index
GenSecOutputFile = self . __ExtendMacro__ ( Rule . NameGuid ) + \
Ffs . Ffs . SectionSuffix [ SectionType ] + ' SEC ' + SecNum
OutputFile = os . path . join ( self . OutputPath , GenSecOutputFile )
2010-03-01 00:39:39 +01:00
GenSecInputFile = GenFdsGlobalVariable . MacroExtend ( GenSecInputFile , Dict , self . CurrentArch )
#Get PE Section alignment when align is set to AUTO
if self . Alignment == ' Auto ' and ( SectionType == ' PE32 ' or SectionType == ' TE ' ) :
ImageObj = PeImageClass ( GenSecInputFile )
if ImageObj . SectionAlignment < 0x400 :
self . Alignment = str ( ImageObj . SectionAlignment )
else :
self . Alignment = str ( ImageObj . SectionAlignment / 0x400 ) + ' K '
2009-07-17 11:10:31 +02:00
if not NoStrip :
FileBeforeStrip = os . path . join ( self . OutputPath , ModuleName + ' .reloc ' )
if not os . path . exists ( FileBeforeStrip ) or \
( os . path . getmtime ( GenSecInputFile ) > os . path . getmtime ( FileBeforeStrip ) ) :
shutil . copyfile ( GenSecInputFile , FileBeforeStrip )
StrippedFile = os . path . join ( self . OutputPath , ModuleName + ' .stipped ' )
GenFdsGlobalVariable . GenerateFirmwareImage (
StrippedFile ,
2010-03-01 00:39:39 +01:00
[ GenSecInputFile ] ,
2009-07-17 11:10:31 +02:00
Strip = True
)
GenSecInputFile = StrippedFile
if SectionType == ' TE ' :
TeFile = os . path . join ( self . OutputPath , self . ModuleGuid + ' Te.raw ' )
GenFdsGlobalVariable . GenerateFirmwareImage (
TeFile ,
2010-03-01 00:39:39 +01:00
[ GenSecInputFile ] ,
2009-07-17 11:10:31 +02:00
Type = ' te '
)
GenSecInputFile = TeFile
GenFdsGlobalVariable . GenerateSection ( OutputFile , [ GenSecInputFile ] , Section . Section . SectionType [ SectionType ] )
OutputFileList . append ( OutputFile )
return OutputFileList
## __GenSimpleFileFfs__() method
#
# Generate FFS
#
# @param self The object pointer
# @param Rule The rule object used to generate section
# @param InputFileList The output file list from GenSection
# @retval string Generated FFS file name
#
def __GenSimpleFileFfs__ ( self , Rule , InputFileList ) :
FfsOutput = self . OutputPath + \
os . sep + \
self . __ExtendMacro__ ( Rule . NameGuid ) + \
' .ffs '
GenFdsGlobalVariable . VerboseLogger ( self . __ExtendMacro__ ( Rule . NameGuid ) )
InputSection = [ ]
SectionAlignments = [ ]
for InputFile in InputFileList :
InputSection . append ( InputFile )
2010-03-01 00:39:39 +01:00
SectionAlignments . append ( Rule . SectAlignment )
2009-07-17 11:10:31 +02:00
if Rule . NameGuid != None and Rule . NameGuid . startswith ( ' PCD( ' ) :
PcdValue = GenFdsGlobalVariable . GetPcdValue ( Rule . NameGuid )
if len ( PcdValue ) == 0 :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , ' %s NOT defined. ' \
% ( Rule . NameGuid ) )
if PcdValue . startswith ( ' { ' ) :
PcdValue = GuidStructureByteArrayToGuidString ( PcdValue )
RegistryGuidStr = PcdValue
if len ( RegistryGuidStr ) == 0 :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , ' GUID value for %s in wrong format. ' \
% ( Rule . NameGuid ) )
self . ModuleGuid = RegistryGuidStr
GenFdsGlobalVariable . GenerateFfs ( FfsOutput , InputSection ,
Ffs . Ffs . FdfFvFileTypeToFileType [ Rule . FvFileType ] ,
self . ModuleGuid , Fixed = Rule . Fixed ,
CheckSum = Rule . CheckSum , Align = Rule . Alignment ,
SectionAlign = SectionAlignments
)
return FfsOutput
## __GenComplexFileSection__() method
#
# Generate section by sections in Rule
#
2010-03-01 00:39:39 +01:00
# @param self The object pointer
# @param Rule The rule object used to generate section
# @param FvChildAddr Array of the inside FvImage base address
# @param FvParentAddr Parent Fv base address
# @retval string File name of the generated section file
2009-07-17 11:10:31 +02:00
#
2010-03-01 00:39:39 +01:00
def __GenComplexFileSection__ ( self , Rule , FvChildAddr , FvParentAddr ) :
2009-07-17 11:10:31 +02:00
if self . ModuleType in ( ' SEC ' , ' PEI_CORE ' , ' PEIM ' ) :
if Rule . KeepReloc != None :
self . KeepRelocFromRule = Rule . KeepReloc
SectFiles = [ ]
SectAlignments = [ ]
Index = 1
2011-05-11 12:26:49 +02:00
HasGneratedFlag = False
2009-07-17 11:10:31 +02:00
for Sect in Rule . SectionList :
SecIndex = ' %d ' % Index
SectList = [ ]
2009-11-09 12:47:35 +01:00
#
# Convert Fv Section Type for PI1.1 SMM driver.
#
2011-05-11 12:26:49 +02:00
if self . ModuleType == ' DXE_SMM_DRIVER ' and int ( self . PiSpecVersion , 16 ) > = 0x0001000A :
2009-11-09 12:47:35 +01:00
if Sect . SectionType == ' DXE_DEPEX ' :
Sect . SectionType = ' SMM_DEPEX '
#
# Framework SMM Driver has no SMM_DEPEX section type
#
2011-05-11 12:26:49 +02:00
if self . ModuleType == ' DXE_SMM_DRIVER ' and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
2009-11-09 12:47:35 +01:00
if Sect . SectionType == ' SMM_DEPEX ' :
EdkLogger . error ( " GenFds " , FORMAT_NOT_SUPPORTED , " Framework SMM module doesn ' t support SMM_DEPEX section type " , File = self . InfFileName )
2010-03-01 00:39:39 +01:00
#
# process the inside FvImage from FvSection or GuidSection
#
if FvChildAddr != [ ] :
if isinstance ( Sect , FvImageSection ) :
Sect . FvAddr = FvChildAddr . pop ( 0 )
elif isinstance ( Sect , GuidSection ) :
Sect . FvAddr = FvChildAddr
if FvParentAddr != None and isinstance ( Sect , GuidSection ) :
Sect . FvParentAddr = FvParentAddr
2009-07-17 11:10:31 +02:00
if Rule . KeyStringList != [ ] :
SectList , Align = Sect . GenSection ( self . OutputPath , self . ModuleGuid , SecIndex , Rule . KeyStringList , self )
else :
SectList , Align = Sect . GenSection ( self . OutputPath , self . ModuleGuid , SecIndex , self . KeyStringList , self )
2011-05-11 12:26:49 +02:00
if not HasGneratedFlag :
UniVfrOffsetFileSection = " "
ModuleFileName = os . path . join ( GenFdsGlobalVariable . WorkSpaceDir , self . InfFileName )
InfData = GenFdsGlobalVariable . WorkSpace . BuildObject [ PathClass ( ModuleFileName ) , self . CurrentArch ]
#
# Search the source list in InfData to find if there are .vfr file exist.
#
VfrUniBaseName = { }
VfrUniOffsetList = [ ]
for SourceFile in InfData . Sources :
if SourceFile . Type . upper ( ) == " .VFR " :
#
# search the .map file to find the offset of vfr binary in the PE32+/TE file.
#
VfrUniBaseName [ SourceFile . BaseName ] = ( SourceFile . BaseName + " Bin " )
if SourceFile . Type . upper ( ) == " .UNI " :
#
# search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
#
VfrUniBaseName [ " UniOffsetName " ] = ( self . BaseName + " Strings " )
if len ( VfrUniBaseName ) > 0 :
VfrUniOffsetList = self . __GetBuildOutputMapFileVfrUniInfo ( VfrUniBaseName )
#
# Generate the Raw data of raw section
#
os . path . join ( self . OutputPath , self . BaseName + ' .offset ' )
UniVfrOffsetFileName = os . path . join ( self . OutputPath , self . BaseName + ' .offset ' )
UniVfrOffsetFileSection = os . path . join ( self . OutputPath , self . BaseName + ' Offset ' + ' .raw ' )
self . __GenUniVfrOffsetFile ( VfrUniOffsetList , UniVfrOffsetFileName )
UniVfrOffsetFileNameList = [ ]
UniVfrOffsetFileNameList . append ( UniVfrOffsetFileName )
""" Call GenSection """
GenFdsGlobalVariable . GenerateSection ( UniVfrOffsetFileSection ,
UniVfrOffsetFileNameList ,
" EFI_SECTION_RAW "
)
os . remove ( UniVfrOffsetFileName )
SectList . append ( UniVfrOffsetFileSection )
HasGneratedFlag = True
2009-07-17 11:10:31 +02:00
for SecName in SectList :
SectFiles . append ( SecName )
SectAlignments . append ( Align )
Index = Index + 1
return SectFiles , SectAlignments
## __GenComplexFileFfs__() method
#
# Generate FFS
#
# @param self The object pointer
# @param Rule The rule object used to generate section
# @param InputFileList The output file list from GenSection
# @retval string Generated FFS file name
#
def __GenComplexFileFfs__ ( self , Rule , InputFile , Alignments ) :
if Rule . NameGuid != None and Rule . NameGuid . startswith ( ' PCD( ' ) :
PcdValue = GenFdsGlobalVariable . GetPcdValue ( Rule . NameGuid )
if len ( PcdValue ) == 0 :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , ' %s NOT defined. ' \
% ( Rule . NameGuid ) )
if PcdValue . startswith ( ' { ' ) :
PcdValue = GuidStructureByteArrayToGuidString ( PcdValue )
RegistryGuidStr = PcdValue
if len ( RegistryGuidStr ) == 0 :
EdkLogger . error ( " GenFds " , GENFDS_ERROR , ' GUID value for %s in wrong format. ' \
% ( Rule . NameGuid ) )
self . ModuleGuid = RegistryGuidStr
FfsOutput = os . path . join ( self . OutputPath , self . ModuleGuid + ' .ffs ' )
GenFdsGlobalVariable . GenerateFfs ( FfsOutput , InputFile ,
Ffs . Ffs . FdfFvFileTypeToFileType [ Rule . FvFileType ] ,
self . ModuleGuid , Fixed = Rule . Fixed ,
CheckSum = Rule . CheckSum , Align = Rule . Alignment ,
SectionAlign = Alignments
)
return FfsOutput
## __GetGenFfsCmdParameter__() method
#
# Create parameter string for GenFfs
#
# @param self The object pointer
# @param Rule The rule object used to generate section
# @retval tuple (FileType, Fixed, CheckSum, Alignment)
#
def __GetGenFfsCmdParameter__ ( self , Rule ) :
result = tuple ( )
result + = ( ' -t ' , Ffs . Ffs . FdfFvFileTypeToFileType [ Rule . FvFileType ] )
if Rule . Fixed != False :
result + = ( ' -x ' , )
if Rule . CheckSum != False :
result + = ( ' -s ' , )
if Rule . Alignment != None and Rule . Alignment != ' ' :
result + = ( ' -a ' , Rule . Alignment )
return result
2011-05-11 12:26:49 +02:00
## __GetBuildOutputMapFileVfrUniInfo() method
#
# Find the offset of UNI/INF object offset in the EFI image file.
#
# @param self The object pointer
# @param VfrUniBaseName A name list contain the UNI/INF object name.
# @retval RetValue A list contain offset of UNI/INF object.
#
def __GetBuildOutputMapFileVfrUniInfo ( self , VfrUniBaseName ) :
RetValue = [ ]
MapFileName = os . path . join ( self . EfiOutputPath , self . BaseName + " .map " )
try :
fInputfile = open ( MapFileName , " r " , 0 )
try :
FileLinesList = fInputfile . readlines ( )
except :
EdkLogger . error ( " GenFds " , FILE_READ_FAILURE , " File read failed for %s " % MapFileName , None )
finally :
fInputfile . close ( )
except :
EdkLogger . error ( " GenFds " , FILE_OPEN_FAILURE , " File open failed for %s " % MapFileName , None )
IsHex = False
for eachLine in FileLinesList :
for eachName in VfrUniBaseName . values ( ) :
if eachLine . find ( eachName ) != - 1 :
eachLine = eachLine . strip ( )
Element = eachLine . split ( )
#
# MSFT/ICC/EBC map file
#
if ( len ( Element ) == 4 ) :
try :
int ( Element [ 2 ] , 16 )
IsHex = True
except :
IsHex = False
if IsHex :
RetValue . append ( ( eachName , Element [ 2 ] ) )
IsHex = False
#
# GCC map file
#
elif ( len ( Element ) == 2 ) and Element [ 0 ] . startswith ( " 0x " ) :
RetValue . append ( ( eachName , Element [ 0 ] ) )
return RetValue
## __GenUniVfrOffsetFile() method
#
# Generate the offset file for the module which contain VFR or UNI file.
#
# @param self The object pointer
# @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
# @param UniVfrOffsetFileName The output offset file name.
#
def __GenUniVfrOffsetFile ( self , VfrUniOffsetList , UniVfrOffsetFileName ) :
try :
fInputfile = open ( UniVfrOffsetFileName , " wb+ " , 0 )
except :
EdkLogger . error ( " GenFds " , FILE_OPEN_FAILURE , " File open failed for %s " % UniVfrOffsetFileName , None )
# Use a instance of StringIO to cache data
fStringIO = StringIO . StringIO ( ' ' )
for Item in VfrUniOffsetList :
if ( Item [ 0 ] . find ( " Strings " ) != - 1 ) :
#
# UNI offset in image.
# GUID + Offset
# { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
#
UniGuid = [ 0xe0 , 0xc5 , 0x13 , 0x89 , 0xf6 , 0x33 , 0x86 , 0x4d , 0x9b , 0xf1 , 0x43 , 0xef , 0x89 , 0xfc , 0x6 , 0x66 ]
UniGuid = [ chr ( ItemGuid ) for ItemGuid in UniGuid ]
fStringIO . write ( ' ' . join ( UniGuid ) )
UniValue = pack ( ' Q ' , int ( Item [ 1 ] , 16 ) )
fStringIO . write ( UniValue )
else :
#
# VFR binary offset in image.
# GUID + Offset
# { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
#
VfrGuid = [ 0xb4 , 0x7c , 0xbc , 0xd0 , 0x47 , 0x6a , 0x5f , 0x49 , 0xaa , 0x11 , 0x71 , 0x7 , 0x46 , 0xda , 0x6 , 0xa2 ]
VfrGuid = [ chr ( ItemGuid ) for ItemGuid in VfrGuid ]
fStringIO . write ( ' ' . join ( VfrGuid ) )
type ( Item [ 1 ] )
VfrValue = pack ( ' Q ' , int ( Item [ 1 ] , 16 ) )
fStringIO . write ( VfrValue )
#
# write data into file.
#
try :
fInputfile . write ( fStringIO . getvalue ( ) )
except :
EdkLogger . error ( " GenFds " , FILE_WRITE_FAILURE , " Write data to file %s failed, please check whether the file been locked or using by other applications. " % UniVfrOffsetFileName , None )
fStringIO . close ( )
fInputfile . close ( )