2009-07-17 09:10:31 +00:00
## @file
# process FFS generation from INF statement
#
2018-03-07 14:14:43 +08:00
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
2016-04-16 09:45:02 +08:00
# Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>
2009-07-17 09:10:31 +00:00
#
2019-04-03 16:03:11 -07:00
# SPDX-License-Identifier: BSD-2-Clause-Patent
2009-07-17 09:10:31 +00:00
#
##
# Import Modules
#
2018-10-15 08:27:53 +08:00
from __future__ import absolute_import
2018-07-13 18:18:33 +08:00
from . import Rule
2014-08-15 03:06:48 +00:00
import Common.LongFilePathOs as os
2018-06-25 18:31:36 +08:00
from io import BytesIO
2011-05-11 10:26:49 +00:00
from struct import *
2018-07-13 18:18:33 +08:00
from .GenFdsGlobalVariable import GenFdsGlobalVariable
2018-10-24 01:29:19 +08:00
from .Ffs import SectionSuffix , FdfFvFileTypeToFileType
2009-07-17 09:10:31 +00:00
import subprocess
import sys
2024-02-15 15:39:10 -05:00
from pathlib import Path
2018-07-13 18:18:33 +08:00
from . import Section
from . import RuleSimpleFile
from . import RuleComplexFile
2009-07-17 09:10:31 +00:00
from CommonDataClass.FdfClass import FfsInfStatementClassObject
2015-10-08 09:27:14 +00:00
from Common.MultipleWorkspace import MultipleWorkspace as mws
2019-01-10 03:00:41 +08:00
from Common.DataType import SUP_MODULE_USER_DEFINED
2019-07-01 06:19:13 +00:00
from Common.DataType import SUP_MODULE_HOST_APPLICATION
2018-05-19 18:50:25 +08:00
from Common.StringUtils import *
2009-07-17 09:10:31 +00:00
from Common.Misc import PathClass
from Common.Misc import GuidStructureByteArrayToGuidString
2014-08-28 13:53:34 +00:00
from Common.Misc import ProcessDuplicatedInf
2015-02-06 03:40:27 +00:00
from Common.Misc import GetVariableOffset
2009-07-17 09:10:31 +00:00
from Common import EdkLogger
from Common.BuildToolError import *
2018-07-13 18:18:33 +08:00
from .GuidSection import GuidSection
from .FvImageSection import FvImageSection
2010-02-28 23:39:39 +00:00
from Common.Misc import PeImageClass
2011-09-18 12:17:25 +00:00
from AutoGen.GenDepex import DependencyExpression
2013-11-18 07:41:21 +00:00
from PatchPcdValue.PatchPcdValue import PatchBinaryFile
2014-08-15 03:06:48 +00:00
from Common.LongFilePathSupport import CopyLongFilePath
from Common.LongFilePathSupport import OpenLongFilePath as open
2016-04-20 09:32:52 +08:00
import Common.GlobalData as GlobalData
2018-07-13 18:18:33 +08:00
from .DepexSection import DepexSection
2017-11-22 15:42:25 +08:00
from Common.Misc import SaveFileOnChange
2018-03-03 09:12:18 +08:00
from Common.Expression import *
2018-04-12 07:08:08 +08:00
from Common.DataType import *
2009-07-17 09:10:31 +00: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 10:26:49 +00:00
self . PiSpecVersion = '0x00000000'
2011-08-26 07:46:26 +00:00
self . InfModule = None
2011-09-18 12:17:25 +00:00
self . FinalTargetSuffixMap = {}
2011-10-11 02:49:48 +00:00
self . CurrentLineNum = None
self . CurrentLineContent = None
self . FileName = None
self . InfFileName = None
2014-08-28 13:53:34 +00:00
self . OverrideGuid = None
self . PatchedBinFile = ''
2014-09-12 06:57:22 +00:00
self . MacroDict = {}
2017-11-22 15:42:25 +08:00
self . Depex = False
2011-08-26 07:46:26 +00:00
2011-09-18 12:17:25 +00:00
## GetFinalTargetSuffixMap() method
2011-08-26 07:46:26 +00:00
#
# Get final build target list
2011-09-18 12:17:25 +00:00
def GetFinalTargetSuffixMap ( self ):
2011-08-26 07:46:26 +00:00
if not self . InfModule or not self . CurrentArch :
return []
2011-09-18 12:17:25 +00: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
2019-07-01 06:19:13 +00:00
if '.depex' not in self . FinalTargetSuffixMap and self . InfModule . ModuleType != SUP_MODULE_USER_DEFINED and self . InfModule . ModuleType != SUP_MODULE_HOST_APPLICATION \
2011-09-18 12:17:25 +00:00
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 ]
2019-07-01 06:19:13 +00:00
if ModuleType != SUP_MODULE_USER_DEFINED and ModuleType != SUP_MODULE_HOST_APPLICATION :
2011-09-18 12:17:25 +00:00
for LibraryClass in PlatformDataBase . LibraryClasses . GetKeys ():
2024-02-28 10:47:23 -08:00
if LibraryClass . startswith ( "NULL" ) and LibraryClass [ 4 :] . isdigit () and PlatformDataBase . LibraryClasses [ LibraryClass , ModuleType ]:
2011-09-18 12:17:25 +00:00
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 :
2024-02-28 10:47:23 -08:00
if LibraryClass . startswith ( "NULL" ) and LibraryClass [ 4 :] . isdigit ():
2011-09-18 12:17:25 +00:00
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 07:46:26 +00:00
2009-07-17 09:10:31 +00:00
## __InfParse() method
#
# Parse inf file to get module information
#
# @param self The object pointer
# @param Dict dictionary contains macro and value pair
#
2019-05-29 13:29:34 +08:00
def __InfParse__ ( self , Dict = None , IsGenFfs = False ):
2009-07-17 09:10:31 +00:00
2024-12-09 18:42:33 +00:00
GenFdsGlobalVariable . VerboseLogger ( " Begin parsing INF file : %s " % self . InfFileName )
2009-07-17 09:10:31 +00:00
self . InfFileName = self . InfFileName . replace ( '$(WORKSPACE)' , '' )
2014-08-28 13:53:34 +00:00
if len ( self . InfFileName ) > 1 and self . InfFileName [ 0 ] == ' \\ ' and self . InfFileName [ 1 ] == ' \\ ' :
pass
elif self . InfFileName [ 0 ] == ' \\ ' or self . InfFileName [ 0 ] == '/' :
2024-02-15 15:39:10 -05:00
ws_path = Path ( GenFdsGlobalVariable . WorkSpaceDir )
inf_path = Path ( self . InfFileName )
if ws_path in inf_path . parents :
self . InfFileName = str ( inf_path . relative_to ( ws_path ))
else :
self . InfFileName = self . InfFileName [ 1 :]
2009-07-17 09:10:31 +00:00
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 ):
2024-12-09 18:42:33 +00:00
EdkLogger . error ( "GenFds" , GENFDS_ERROR , "Non-existent Module %s !" % ( self . InfFileName ))
2009-07-17 09:10:31 +00:00
self . CurrentArch = self . GetCurrentArch ()
#
# Get the InfClass object
#
PathClassObj = PathClass ( self . InfFileName , GenFdsGlobalVariable . WorkSpaceDir )
2010-09-06 01:58:00 +00:00
ErrorCode , ErrorInfo = PathClassObj . Validate ( ".inf" )
2009-07-17 09:10:31 +00:00
if ErrorCode != 0 :
EdkLogger . error ( "GenFds" , ErrorCode , ExtraData = ErrorInfo )
2014-08-28 13:53:34 +00:00
2015-12-07 09:08:05 +00:00
#
# Cache lower case version of INF path before processing FILE_GUID override
#
InfLowerPath = str ( PathClassObj ) . lower ()
2014-08-28 13:53:34 +00:00
if self . OverrideGuid :
PathClassObj = ProcessDuplicatedInf ( PathClassObj , self . OverrideGuid , GenFdsGlobalVariable . WorkSpaceDir )
2018-03-27 04:25:43 +08:00
if self . CurrentArch is not None :
2009-07-17 09:10:31 +00:00
2011-10-29 06:59:30 +00:00
Inf = GenFdsGlobalVariable . WorkSpace . BuildObject [ PathClassObj , self . CurrentArch , GenFdsGlobalVariable . TargetName , GenFdsGlobalVariable . ToolChainTag ]
2009-07-17 09:10:31 +00:00
#
2019-02-06 15:44:39 +08:00
# Set Ffs BaseName, ModuleGuid, ModuleType, Version, OutputPath
2009-07-17 09:10:31 +00:00
#
self . BaseName = Inf . BaseName
self . ModuleGuid = Inf . Guid
self . ModuleType = Inf . ModuleType
2018-03-27 04:25:43 +08:00
if Inf . Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf . Specification :
2009-11-09 11:47:35 +00:00
self . PiSpecVersion = Inf . Specification [ 'PI_SPECIFICATION_VERSION' ]
2009-07-17 09:10:31 +00:00
if Inf . AutoGenVersion < 0x00010005 :
self . ModuleType = Inf . ComponentType
self . VersionString = Inf . Version
self . BinFileList = Inf . Binaries
self . SourceFileList = Inf . Sources
2018-03-27 04:25:43 +08:00
if self . KeepReloc is None and Inf . Shadow :
2009-07-17 09:10:31 +00:00
self . ShadowFromInfFile = Inf . Shadow
else :
2018-04-16 21:52:13 +08:00
Inf = GenFdsGlobalVariable . WorkSpace . BuildObject [ PathClassObj , TAB_COMMON , GenFdsGlobalVariable . TargetName , GenFdsGlobalVariable . ToolChainTag ]
2009-07-17 09:10:31 +00:00
self . BaseName = Inf . BaseName
self . ModuleGuid = Inf . Guid
self . ModuleType = Inf . ModuleType
2018-03-27 04:25:43 +08:00
if Inf . Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf . Specification :
2009-11-09 11:47:35 +00:00
self . PiSpecVersion = Inf . Specification [ 'PI_SPECIFICATION_VERSION' ]
2009-07-17 09:10:31 +00: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 ))
2014-08-28 13:53:34 +00:00
if self . OverrideGuid :
self . ModuleGuid = self . OverrideGuid
2009-07-17 09:10:31 +00:00
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 ))
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_SMM_CORE and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
2018-07-05 17:40:04 +08: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-11-09 11:47:35 +00:00
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_MM_CORE_STANDALONE and int ( self . PiSpecVersion , 16 ) < 0x00010032 :
2017-06-27 00:47:43 +08:00
EdkLogger . error ( "GenFds" , FORMAT_NOT_SUPPORTED , "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032" , File = self . InfFileName )
2018-03-27 04:25:43 +08:00
if Inf . _Defs is not None and len ( Inf . _Defs ) > 0 :
2009-07-17 09:10:31 +00:00
self . OptRomDefs . update ( Inf . _Defs )
2014-01-10 05:25:50 +00:00
2013-11-18 07:41:21 +00:00
self . PatchPcds = []
InfPcds = Inf . Pcds
Platform = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , self . CurrentArch , GenFdsGlobalVariable . TargetName , GenFdsGlobalVariable . ToolChainTag ]
FdfPcdDict = GenFdsGlobalVariable . FdfParser . Profile . PcdDict
2018-01-31 16:49:14 +08:00
PlatformPcds = Platform . Pcds
2014-01-10 05:25:50 +00:00
# Workaround here: both build and GenFds tool convert the workspace path to lower case
# But INF file path in FDF and DSC file may have real case characters.
# Try to convert the path to lower case to see if PCDs value are override by DSC.
2013-11-18 07:41:21 +00:00
DscModules = {}
for DscModule in Platform . Modules :
DscModules [ str ( DscModule ) . lower ()] = Platform . Modules [ DscModule ]
for PcdKey in InfPcds :
Pcd = InfPcds [ PcdKey ]
if not hasattr ( Pcd , 'Offset' ):
continue
2018-04-27 00:57:55 +08:00
if Pcd . Type != TAB_PCDS_PATCHABLE_IN_MODULE :
2013-11-18 07:41:21 +00:00
continue
2014-01-10 05:25:50 +00:00
# Override Patchable PCD value by the value from DSC
2013-11-18 07:41:21 +00:00
PatchPcd = None
if InfLowerPath in DscModules and PcdKey in DscModules [ InfLowerPath ] . Pcds :
PatchPcd = DscModules [ InfLowerPath ] . Pcds [ PcdKey ]
elif PcdKey in Platform . Pcds :
PatchPcd = Platform . Pcds [ PcdKey ]
DscOverride = False
if PatchPcd and Pcd . Type == PatchPcd . Type :
DefaultValue = PatchPcd . DefaultValue
DscOverride = True
2014-01-10 05:25:50 +00:00
# Override Patchable PCD value by the value from FDF
2013-11-18 07:41:21 +00:00
FdfOverride = False
if PcdKey in FdfPcdDict :
DefaultValue = FdfPcdDict [ PcdKey ]
FdfOverride = True
2014-01-10 05:25:50 +00:00
2016-04-20 09:32:52 +08:00
# Override Patchable PCD value by the value from Build Option
BuildOptionOverride = False
if GlobalData . BuildOptionPcd :
for pcd in GlobalData . BuildOptionPcd :
if PcdKey == ( pcd [ 1 ], pcd [ 0 ]):
2018-03-07 14:14:43 +08:00
if pcd [ 2 ]:
continue
DefaultValue = pcd [ 3 ]
2016-04-20 09:32:52 +08:00
BuildOptionOverride = True
break
if not DscOverride and not FdfOverride and not BuildOptionOverride :
2013-11-18 07:41:21 +00:00
continue
2018-03-03 09:12:18 +08:00
# Support Flexible PCD format
if DefaultValue :
try :
DefaultValue = ValueExpressionEx ( DefaultValue , Pcd . DatumType , Platform . _GuidDict )( True )
except BadExpression :
EdkLogger . error ( "GenFds" , GENFDS_ERROR , 'PCD [ %s . %s ] Value " %s "' % ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName , DefaultValue ), File = self . InfFileName )
2018-03-07 14:14:43 +08:00
if Pcd . InfDefaultValue :
2018-03-03 09:12:18 +08:00
try :
2018-03-07 14:14:43 +08:00
Pcd . InfDefaultValue = ValueExpressionEx ( Pcd . InfDefaultValue , Pcd . DatumType , Platform . _GuidDict )( True )
2018-03-03 09:12:18 +08:00
except BadExpression :
2018-06-25 18:31:33 +08:00
EdkLogger . error ( "GenFds" , GENFDS_ERROR , 'PCD [ %s . %s ] Value " %s "' % ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName , Pcd . DefaultValue ), File = self . InfFileName )
2018-03-03 09:12:18 +08:00
2014-01-10 05:25:50 +00:00
# Check value, if value are equal, no need to patch
2018-04-11 09:14:05 -07:00
if Pcd . DatumType == TAB_VOID :
2018-04-20 23:51:42 +08:00
if Pcd . InfDefaultValue == DefaultValue or not DefaultValue :
2013-11-18 07:41:21 +00:00
continue
2014-01-10 05:25:50 +00:00
# Get the string size from FDF or DSC
2013-11-18 07:41:21 +00:00
if DefaultValue [ 0 ] == 'L' :
2014-01-10 05:25:50 +00:00
# Remove L"", but the '\0' must be appended
2013-11-18 07:41:21 +00:00
MaxDatumSize = str (( len ( DefaultValue ) - 2 ) * 2 )
elif DefaultValue [ 0 ] == '{' :
MaxDatumSize = str ( len ( DefaultValue . split ( ',' )))
else :
MaxDatumSize = str ( len ( DefaultValue ) - 1 )
if DscOverride :
Pcd . MaxDatumSize = PatchPcd . MaxDatumSize
2014-01-10 05:25:50 +00:00
# If no defined the maximum size in DSC, try to get current size from INF
2018-04-20 23:51:42 +08:00
if not Pcd . MaxDatumSize :
2018-03-07 14:14:43 +08:00
Pcd . MaxDatumSize = str ( len ( Pcd . InfDefaultValue . split ( ',' )))
2013-11-18 07:41:21 +00:00
else :
Base1 = Base2 = 10
2018-03-07 14:14:43 +08:00
if Pcd . InfDefaultValue . upper () . startswith ( '0X' ):
2013-11-18 07:41:21 +00:00
Base1 = 16
if DefaultValue . upper () . startswith ( '0X' ):
Base2 = 16
try :
2018-03-07 14:14:43 +08:00
PcdValueInImg = int ( Pcd . InfDefaultValue , Base1 )
2013-11-18 07:41:21 +00:00
PcdValueInDscOrFdf = int ( DefaultValue , Base2 )
if PcdValueInImg == PcdValueInDscOrFdf :
continue
except :
continue
2014-01-10 05:25:50 +00:00
# Check the Pcd size and data type
2018-04-11 09:14:05 -07:00
if Pcd . DatumType == TAB_VOID :
2013-11-18 07:41:21 +00:00
if int ( MaxDatumSize ) > int ( Pcd . MaxDatumSize ):
EdkLogger . error ( "GenFds" , GENFDS_ERROR , "The size of VOID* type PCD ' %s . %s ' exceeds its maximum size %d bytes." \
% ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName , int ( MaxDatumSize ) - int ( Pcd . MaxDatumSize )))
else :
2018-04-12 07:08:08 +08:00
if PcdValueInDscOrFdf > MAX_VAL_TYPE [ Pcd . DatumType ] \
or PcdValueInImg > MAX_VAL_TYPE [ Pcd . DatumType ]:
2013-11-18 07:41:21 +00:00
EdkLogger . error ( "GenFds" , GENFDS_ERROR , "The size of %s type PCD ' %s . %s ' doesn't match its data type." \
% ( Pcd . DatumType , Pcd . TokenSpaceGuidCName , Pcd . TokenCName ))
2014-08-28 13:53:34 +00:00
self . PatchPcds . append (( Pcd , DefaultValue ))
2011-08-26 07:46:26 +00:00
self . InfModule = Inf
2013-11-18 07:41:21 +00:00
self . PcdIsDriver = Inf . PcdIsDriver
self . IsBinaryModule = Inf . IsBinaryModule
2018-09-11 06:18:05 +08:00
if len ( Inf . Depex . data ) > 0 and len ( Inf . DepexExpression . data ) > 0 :
2017-11-22 15:42:25 +08:00
self . Depex = True
2013-11-18 07:41:21 +00: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 )
2009-07-17 09:10:31 +00:00
#
2019-02-06 15:44:39 +08:00
# Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${ModuleName}\
2009-07-17 09:10:31 +00:00
#
2019-05-29 13:29:34 +08:00
if IsGenFfs :
Rule = self . __GetRule__ ()
if GlobalData . gGuidPatternEnd . match ( Rule . NameGuid ):
self . ModuleGuid = Rule . NameGuid
2009-07-17 09:10:31 +00:00
self . OutputPath = os . path . join ( GenFdsGlobalVariable . FfsDir , \
self . ModuleGuid + self . BaseName )
if not os . path . exists ( self . OutputPath ) :
os . makedirs ( self . OutputPath )
2017-11-22 15:42:25 +08:00
self . EfiOutputPath , self . EfiDebugPath = self . __GetEFIOutPutPath__ ()
2024-12-09 18:42:33 +00:00
GenFdsGlobalVariable . VerboseLogger ( "ModuleEFIPath: " + self . EfiOutputPath )
2009-07-17 09:10:31 +00:00
2014-08-28 13:53:34 +00:00
## PatchEfiFile
2013-11-18 07:41:21 +00:00
#
# Patch EFI file with patch PCD
#
# @param EfiFile: EFI file needs to be patched.
# @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name
# If passed in file does not end with efi, return as is
#
2014-08-28 13:53:34 +00:00
def PatchEfiFile ( self , EfiFile , FileType ):
2015-12-07 08:27:53 +00:00
#
# If the module does not have any patches, then return path to input file
2018-07-05 17:40:04 +08:00
#
2013-11-18 07:41:21 +00:00
if not self . PatchPcds :
return EfiFile
2015-12-07 08:27:53 +00:00
#
# Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
2018-07-05 17:40:04 +08:00
#
2019-07-01 06:19:13 +00:00
if FileType != BINARY_FILE_TYPE_PE32 and self . ModuleType != SUP_MODULE_USER_DEFINED and self . ModuleType != SUP_MODULE_HOST_APPLICATION :
2014-08-28 13:53:34 +00:00
return EfiFile
2015-12-07 08:27:53 +00:00
#
# Generate path to patched output file
#
Basename = os . path . basename ( EfiFile )
Output = os . path . normpath ( os . path . join ( self . OutputPath , Basename ))
#
# If this file has already been patched, then return the path to the patched file
#
if self . PatchedBinFile == Output :
return Output
#
# If a different file from the same module has already been patched, then generate an error
2018-07-05 17:40:04 +08:00
#
2014-08-28 13:53:34 +00:00
if self . PatchedBinFile :
EdkLogger . error ( "GenFds" , GENFDS_ERROR ,
'Only one binary file can be patched: \n '
' a binary file has been patched: %s \n '
' current file: %s ' % ( self . PatchedBinFile , EfiFile ),
File = self . InfFileName )
2015-12-07 08:27:53 +00:00
#
# Copy unpatched file contents to output file location to perform patching
2018-07-05 17:40:04 +08:00
#
2014-08-15 03:06:48 +00:00
CopyLongFilePath ( EfiFile , Output )
2015-12-07 08:27:53 +00:00
#
# Apply patches to patched output file
2018-07-05 17:40:04 +08:00
#
2014-08-28 13:53:34 +00:00
for Pcd , Value in self . PatchPcds :
RetVal , RetStr = PatchBinaryFile ( Output , int ( Pcd . Offset , 0 ), Pcd . DatumType , Value , Pcd . MaxDatumSize )
2013-11-18 07:41:21 +00:00
if RetVal :
EdkLogger . error ( "GenFds" , GENFDS_ERROR , RetStr , File = self . InfFileName )
2015-12-07 08:27:53 +00:00
#
# Save the path of the patched output file
2018-07-05 17:40:04 +08:00
#
2015-12-07 08:27:53 +00:00
self . PatchedBinFile = Output
#
# Return path to patched output file
2018-07-05 17:40:04 +08:00
#
2013-11-18 07:41:21 +00:00
return Output
2015-12-07 08:27:53 +00:00
2009-07-17 09:10:31 +00:00
## GenFfs() method
#
# Generate FFS
#
2010-02-28 23:39:39 +00: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 09:10:31 +00:00
#
2019-09-12 16:18:27 +08:00
def GenFfs ( self , Dict = None , FvChildAddr = [], FvParentAddr = None , IsMakefile = False , FvName = None ):
2009-07-17 09:10:31 +00:00
#
# Parse Inf file get Module related information
#
2019-09-12 16:18:27 +08:00
if Dict is None :
Dict = {}
2019-05-29 13:29:34 +08:00
self . __InfParse__ ( Dict , IsGenFfs = True )
2017-11-22 15:42:25 +08:00
Arch = self . GetCurrentArch ()
2018-06-25 18:31:33 +08:00
SrcFile = mws . join ( GenFdsGlobalVariable . WorkSpaceDir , self . InfFileName );
2014-09-11 06:44:17 +00:00
DestFile = os . path . join ( self . OutputPath , self . ModuleGuid + '.ffs' )
2018-07-05 17:40:04 +08:00
2014-09-11 06:44:17 +00:00
SrcFileDir = "."
SrcPath = os . path . dirname ( SrcFile )
SrcFileName = os . path . basename ( SrcFile )
2018-07-05 17:40:04 +08:00
SrcFileBase , SrcFileExt = os . path . splitext ( SrcFileName )
2014-09-11 06:44:17 +00:00
DestPath = os . path . dirname ( DestFile )
DestFileName = os . path . basename ( DestFile )
2018-07-05 17:40:04 +08:00
DestFileBase , DestFileExt = os . path . splitext ( DestFileName )
2014-09-11 06:44:17 +00:00
self . MacroDict = {
# source file
"$ {src} " : SrcFile ,
"$ {s_path} " : SrcPath ,
"$ {s_dir} " : SrcFileDir ,
"$ {s_name} " : SrcFileName ,
"$ {s_base} " : SrcFileBase ,
"$ {s_ext} " : SrcFileExt ,
# destination file
"$ {dst} " : DestFile ,
"$ {d_path} " : DestPath ,
"$ {d_name} " : DestFileName ,
"$ {d_base} " : DestFileBase ,
"$ {d_ext} " : DestFileExt
}
2010-11-15 02:51:34 +00:00
#
# Allow binary type module not specify override rule in FDF file.
2018-07-05 17:40:04 +08:00
#
2014-08-28 13:53:34 +00:00
if len ( self . BinFileList ) > 0 :
2018-03-27 04:25:43 +08:00
if self . Rule is None or self . Rule == "" :
2010-11-15 02:51:34 +00:00
self . Rule = "BINARY"
2017-11-22 15:42:25 +08:00
if not IsMakefile and GenFdsGlobalVariable . EnableGenfdsMultiThread and self . Rule != 'BINARY' :
IsMakefile = True
2009-07-17 09:10:31 +00: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 11:47:35 +00:00
#
# Convert Fv File Type for PI1.1 SMM driver.
#
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int ( self . PiSpecVersion , 16 ) >= 0x0001000A :
2009-11-09 11:47:35 +00:00
if Rule . FvFileType == 'DRIVER' :
Rule . FvFileType = 'SMM'
#
# Framework SMM Driver has no SMM FV file type
#
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
if Rule . FvFileType == 'SMM' or Rule . FvFileType == SUP_MODULE_SMM_CORE :
2009-11-09 11:47:35 +00:00
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 09:10:31 +00:00
#
# For the rule only has simpleFile
#
2017-11-22 15:42:25 +08:00
MakefilePath = None
2018-04-10 09:12:49 +08:00
if self . IsBinaryModule :
IsMakefile = False
2017-11-22 15:42:25 +08:00
if IsMakefile :
2019-09-06 21:22:59 +08:00
PathClassObj = PathClass ( self . InfFileName , GenFdsGlobalVariable . WorkSpaceDir )
if self . OverrideGuid :
PathClassObj = ProcessDuplicatedInf ( PathClassObj , self . OverrideGuid , GenFdsGlobalVariable . WorkSpaceDir )
MakefilePath = PathClassObj . Path , Arch
2018-04-10 09:12:49 +08:00
if isinstance ( Rule , RuleSimpleFile . RuleSimpleFile ):
2017-11-22 15:42:25 +08:00
SectionOutputList = self . __GenSimpleFileSection__ ( Rule , IsMakefile = IsMakefile )
FfsOutput = self . __GenSimpleFileFfs__ ( Rule , SectionOutputList , MakefilePath = MakefilePath )
2009-07-17 09:10:31 +00:00
return FfsOutput
#
# For Rule has ComplexFile
#
elif isinstance ( Rule , RuleComplexFile . RuleComplexFile ):
2017-11-22 15:42:25 +08:00
InputSectList , InputSectAlignments = self . __GenComplexFileSection__ ( Rule , FvChildAddr , FvParentAddr , IsMakefile = IsMakefile )
FfsOutput = self . __GenComplexFileFfs__ ( Rule , InputSectList , InputSectAlignments , MakefilePath = MakefilePath )
2009-07-17 09:10:31 +00:00
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 )
2018-07-05 17:40:04 +08:00
String = GenFdsGlobalVariable . MacroExtend ( String , self . MacroDict )
2009-07-17 09:10:31 +00:00
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 = []
2018-03-27 04:25:43 +08:00
if self . CurrentArch is None :
2009-07-17 09:10:31 +00:00
CurrentArchList = [ 'common' ]
else :
CurrentArchList . append ( self . CurrentArch )
for CurrentArch in CurrentArchList :
RuleName = 'RULE' + \
'.' + \
CurrentArch . upper () + \
'.' + \
self . ModuleType . upper ()
2018-03-27 04:25:43 +08:00
if self . Rule is not None :
2009-07-17 09:10:31 +00:00
RuleName = RuleName + \
'.' + \
self . Rule . upper ()
Rule = GenFdsGlobalVariable . FdfParser . Profile . RuleDict . get ( RuleName )
2018-03-27 04:25:43 +08:00
if Rule is not None :
2009-07-17 09:10:31 +00:00
GenFdsGlobalVariable . VerboseLogger ( "Want To Find Rule Name is : " + RuleName )
return Rule
RuleName = 'RULE' + \
'.' + \
2018-04-16 21:52:13 +08:00
TAB_COMMON + \
2009-07-17 09:10:31 +00:00
'.' + \
self . ModuleType . upper ()
2018-03-27 04:25:43 +08:00
if self . Rule is not None :
2009-07-17 09:10:31 +00:00
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 )
2018-03-27 04:25:43 +08:00
if Rule is not None :
2009-07-17 09:10:31 +00:00
GenFdsGlobalVariable . VerboseLogger ( "Want To Find Rule Name is : " + RuleName )
return Rule
2018-03-27 04:25:43 +08:00
if Rule is None :
2009-07-17 09:10:31 +00:00
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 ):
2015-10-08 09:27:14 +00:00
InfFileKey = os . path . normpath ( mws . join ( GenFdsGlobalVariable . WorkSpaceDir , self . InfFileName ))
2009-07-17 09:10:31 +00:00
DscArchList = []
2016-04-16 09:45:02 +08:00
for Arch in GenFdsGlobalVariable . ArchList :
PlatformDataBase = GenFdsGlobalVariable . WorkSpace . BuildObject [ GenFdsGlobalVariable . ActivePlatform , Arch , GenFdsGlobalVariable . TargetName , GenFdsGlobalVariable . ToolChainTag ]
2018-03-27 04:25:43 +08:00
if PlatformDataBase is not None :
2016-04-16 09:45:02 +08:00
if InfFileKey in PlatformDataBase . Modules :
DscArchList . append ( Arch )
2016-05-11 16:09:26 +08:00
else :
#
# BaseTools support build same module more than once, the module path with FILE_GUID overridden has
# the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,
# but the path (self.MetaFile.Path) is the real path
#
2018-04-17 22:40:15 +08:00
for key in PlatformDataBase . Modules :
2016-05-11 16:09:26 +08:00
if InfFileKey == str (( PlatformDataBase . Modules [ key ]) . MetaFile . Path ):
DscArchList . append ( Arch )
break
2013-08-23 02:18:16 +00:00
2009-07-17 09:10:31 +00:00
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
2018-03-27 04:25:43 +08:00
if self . UseArch is not None :
2009-07-17 09:10:31 +00:00
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 01:58:00 +00:00
ErrorCode , ErrorInfo = PathClassObj . Validate ( ".inf" )
2009-07-17 09:10:31 +00: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 = ''
2017-11-22 15:42:25 +08:00
DebugPath = ''
2009-07-17 09:10:31 +00:00
( ModulePath , FileName ) = os . path . split ( self . InfFileName )
2011-10-11 02:49:48 +00:00
Index = FileName . rfind ( '.' )
2009-07-17 09:10:31 +00:00
FileName = FileName [ 0 : Index ]
2014-08-28 13:53:34 +00:00
if self . OverrideGuid :
FileName = self . OverrideGuid
2009-07-17 09:10:31 +00:00
Arch = "NoneArch"
2018-03-27 04:25:43 +08:00
if self . CurrentArch is not None :
2009-07-17 09:10:31 +00:00
Arch = self . CurrentArch
OutputPath = os . path . join ( GenFdsGlobalVariable . OutputDirDict [ Arch ],
2018-06-25 18:31:33 +08:00
Arch ,
2009-07-17 09:10:31 +00:00
ModulePath ,
FileName ,
'OUTPUT'
)
2017-11-22 15:42:25 +08:00
DebugPath = os . path . join ( GenFdsGlobalVariable . OutputDirDict [ Arch ],
2018-06-25 18:31:33 +08:00
Arch ,
2017-11-22 15:42:25 +08:00
ModulePath ,
FileName ,
'DEBUG'
)
2021-10-12 12:07:38 +08:00
OutputPath = os . path . abspath ( OutputPath )
DebugPath = os . path . abspath ( DebugPath )
2017-11-22 15:42:25 +08:00
return OutputPath , DebugPath
2009-07-17 09:10:31 +00:00
## __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
#
2017-11-22 15:42:25 +08:00
def __GenSimpleFileSection__ ( self , Rule , IsMakefile = False ):
2009-07-17 09:10:31 +00:00
#
# Prepare the parameter of GenSection
#
FileList = []
OutputFileList = []
2010-02-28 23:39:39 +00:00
GenSecInputFile = None
2018-03-27 04:25:43 +08:00
if Rule . FileName is not None :
2009-07-17 09:10:31 +00:00
GenSecInputFile = self . __ExtendMacro__ ( Rule . FileName )
2011-05-11 10:26:49 +00:00
if os . path . isabs ( GenSecInputFile ):
GenSecInputFile = os . path . normpath ( GenSecInputFile )
else :
2010-02-28 23:39:39 +00:00
GenSecInputFile = os . path . normpath ( os . path . join ( self . EfiOutputPath , GenSecInputFile ))
2009-07-17 09:10:31 +00:00
else :
FileList , IsSect = Section . Section . GetFileList ( self , '' , Rule . FileExtension )
Index = 1
2009-11-09 11:47:35 +00:00
SectionType = Rule . SectionType
#
# Convert Fv Section Type for PI1.1 SMM driver.
#
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int ( self . PiSpecVersion , 16 ) >= 0x0001000A :
2018-04-27 00:57:56 +08:00
if SectionType == BINARY_FILE_TYPE_DXE_DEPEX :
SectionType = BINARY_FILE_TYPE_SMM_DEPEX
2009-11-09 11:47:35 +00:00
#
# Framework SMM Driver has no SMM_DEPEX section type
#
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
2018-04-27 00:57:56 +08:00
if SectionType == BINARY_FILE_TYPE_SMM_DEPEX :
2009-11-09 11:47:35 +00:00
EdkLogger . error ( "GenFds" , FORMAT_NOT_SUPPORTED , "Framework SMM module doesn't support SMM_DEPEX section type" , File = self . InfFileName )
2009-07-17 09:10:31 +00:00
NoStrip = True
2018-04-27 00:57:53 +08:00
if self . ModuleType in ( SUP_MODULE_SEC , SUP_MODULE_PEI_CORE , SUP_MODULE_PEIM ):
2018-03-27 04:25:43 +08:00
if self . KeepReloc is not None :
2009-07-17 09:10:31 +00:00
NoStrip = self . KeepReloc
2018-03-27 04:25:43 +08:00
elif Rule . KeepReloc is not None :
2009-07-17 09:10:31 +00:00
NoStrip = Rule . KeepReloc
2018-03-27 04:25:43 +08:00
elif self . ShadowFromInfFile is not None :
2009-07-17 09:10:31 +00:00
NoStrip = self . ShadowFromInfFile
if FileList != [] :
for File in FileList :
SecNum = ' %d ' % Index
GenSecOutputFile = self . __ExtendMacro__ ( Rule . NameGuid ) + \
2018-10-24 01:29:19 +08:00
SectionSuffix [ SectionType ] + SUP_MODULE_SEC + SecNum
2009-07-17 09:10:31 +00:00
Index = Index + 1
OutputFile = os . path . join ( self . OutputPath , GenSecOutputFile )
2010-02-28 23:39:39 +00:00
File = GenFdsGlobalVariable . MacroExtend ( File , Dict , self . CurrentArch )
#Get PE Section alignment when align is set to AUTO
2018-04-27 00:57:56 +08:00
if self . Alignment == 'Auto' and ( SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE ):
2010-02-28 23:39:39 +00:00
ImageObj = PeImageClass ( File )
if ImageObj . SectionAlignment < 0x400 :
self . Alignment = str ( ImageObj . SectionAlignment )
2017-09-20 14:10:04 +08:00
elif ImageObj . SectionAlignment < 0x100000 :
2018-12-07 12:34:44 +08:00
self . Alignment = str ( ImageObj . SectionAlignment // 0x400 ) + 'K'
2017-09-20 14:10:04 +08:00
else :
2018-12-07 12:34:44 +08:00
self . Alignment = str ( ImageObj . SectionAlignment // 0x100000 ) + 'M'
2009-07-17 09:10:31 +00:00
if not NoStrip :
FileBeforeStrip = os . path . join ( self . OutputPath , ModuleName + '.reloc' )
if not os . path . exists ( FileBeforeStrip ) or \
2014-08-15 03:06:48 +00:00
( os . path . getmtime ( File ) > os . path . getmtime ( FileBeforeStrip )):
CopyLongFilePath ( File , FileBeforeStrip )
2009-07-17 09:10:31 +00:00
StrippedFile = os . path . join ( self . OutputPath , ModuleName + '.stipped' )
GenFdsGlobalVariable . GenerateFirmwareImage (
2017-11-22 15:42:25 +08:00
StrippedFile ,
[ File ],
Strip = True ,
IsMakefile = IsMakefile
)
2009-07-17 09:10:31 +00:00
File = StrippedFile
2018-04-27 00:57:56 +08:00
if SectionType == BINARY_FILE_TYPE_TE :
2009-07-17 09:10:31 +00:00
TeFile = os . path . join ( self . OutputPath , self . ModuleGuid + 'Te.raw' )
GenFdsGlobalVariable . GenerateFirmwareImage (
2017-11-22 15:42:25 +08:00
TeFile ,
[ File ],
Type = 'te' ,
IsMakefile = IsMakefile
)
2009-07-17 09:10:31 +00:00
File = TeFile
2017-11-22 15:42:25 +08:00
GenFdsGlobalVariable . GenerateSection ( OutputFile , [ File ], Section . Section . SectionType [ SectionType ], IsMakefile = IsMakefile )
2009-07-17 09:10:31 +00:00
OutputFileList . append ( OutputFile )
else :
SecNum = ' %d ' % Index
GenSecOutputFile = self . __ExtendMacro__ ( Rule . NameGuid ) + \
2018-10-24 01:29:19 +08:00
SectionSuffix [ SectionType ] + SUP_MODULE_SEC + SecNum
2009-07-17 09:10:31 +00:00
OutputFile = os . path . join ( self . OutputPath , GenSecOutputFile )
2010-02-28 23:39:39 +00:00
GenSecInputFile = GenFdsGlobalVariable . MacroExtend ( GenSecInputFile , Dict , self . CurrentArch )
#Get PE Section alignment when align is set to AUTO
2018-04-27 00:57:56 +08:00
if self . Alignment == 'Auto' and ( SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE ):
2010-02-28 23:39:39 +00:00
ImageObj = PeImageClass ( GenSecInputFile )
if ImageObj . SectionAlignment < 0x400 :
self . Alignment = str ( ImageObj . SectionAlignment )
2017-09-20 14:10:04 +08:00
elif ImageObj . SectionAlignment < 0x100000 :
2018-12-07 12:34:44 +08:00
self . Alignment = str ( ImageObj . SectionAlignment // 0x400 ) + 'K'
2017-09-20 14:10:04 +08:00
else :
2018-12-07 12:34:44 +08:00
self . Alignment = str ( ImageObj . SectionAlignment // 0x100000 ) + 'M'
2009-07-17 09:10:31 +00:00
if not NoStrip :
FileBeforeStrip = os . path . join ( self . OutputPath , ModuleName + '.reloc' )
if not os . path . exists ( FileBeforeStrip ) or \
2014-08-15 03:06:48 +00:00
( os . path . getmtime ( GenSecInputFile ) > os . path . getmtime ( FileBeforeStrip )):
CopyLongFilePath ( GenSecInputFile , FileBeforeStrip )
2009-07-17 09:10:31 +00:00
StrippedFile = os . path . join ( self . OutputPath , ModuleName + '.stipped' )
GenFdsGlobalVariable . GenerateFirmwareImage (
2017-11-22 15:42:25 +08:00
StrippedFile ,
[ GenSecInputFile ],
Strip = True ,
IsMakefile = IsMakefile
)
2009-07-17 09:10:31 +00:00
GenSecInputFile = StrippedFile
2018-04-27 00:57:56 +08:00
if SectionType == BINARY_FILE_TYPE_TE :
2009-07-17 09:10:31 +00:00
TeFile = os . path . join ( self . OutputPath , self . ModuleGuid + 'Te.raw' )
GenFdsGlobalVariable . GenerateFirmwareImage (
2017-11-22 15:42:25 +08:00
TeFile ,
[ GenSecInputFile ],
Type = 'te' ,
IsMakefile = IsMakefile
)
2009-07-17 09:10:31 +00:00
GenSecInputFile = TeFile
2017-11-22 15:42:25 +08:00
GenFdsGlobalVariable . GenerateSection ( OutputFile , [ GenSecInputFile ], Section . Section . SectionType [ SectionType ], IsMakefile = IsMakefile )
2009-07-17 09:10:31 +00:00
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
#
2017-11-22 15:42:25 +08:00
def __GenSimpleFileFfs__ ( self , Rule , InputFileList , MakefilePath = None ):
2009-07-17 09:10:31 +00:00
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-02-28 23:39:39 +00:00
SectionAlignments . append ( Rule . SectAlignment )
2009-07-17 09:10:31 +00:00
2018-03-27 04:25:43 +08:00
if Rule . NameGuid is not None and Rule . NameGuid . startswith ( 'PCD(' ):
2009-07-17 09:10:31 +00:00
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
2017-11-22 15:42:25 +08:00
GenFdsGlobalVariable . GenerateFfs ( FfsOutput , InputSection ,
2018-10-24 01:29:19 +08:00
FdfFvFileTypeToFileType [ Rule . FvFileType ],
2017-11-22 15:42:25 +08:00
self . ModuleGuid , Fixed = Rule . Fixed ,
CheckSum = Rule . CheckSum , Align = Rule . Alignment ,
SectionAlign = SectionAlignments ,
MakefilePath = MakefilePath
)
2009-07-17 09:10:31 +00:00
return FfsOutput
## __GenComplexFileSection__() method
#
# Generate section by sections in Rule
#
2010-02-28 23:39:39 +00: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 09:10:31 +00:00
#
2017-11-22 15:42:25 +08:00
def __GenComplexFileSection__ ( self , Rule , FvChildAddr , FvParentAddr , IsMakefile = False ):
2019-01-03 13:06:17 +01:00
if self . ModuleType in ( SUP_MODULE_SEC , SUP_MODULE_PEI_CORE , SUP_MODULE_PEIM , SUP_MODULE_MM_CORE_STANDALONE ):
2018-03-27 04:25:43 +08:00
if Rule . KeepReloc is not None :
2009-07-17 09:10:31 +00:00
self . KeepRelocFromRule = Rule . KeepReloc
SectFiles = []
SectAlignments = []
Index = 1
2017-11-22 15:42:25 +08:00
HasGeneratedFlag = False
2013-11-18 07:41:21 +00:00
if self . PcdIsDriver == 'PEI_PCD_DRIVER' :
if self . IsBinaryModule :
PcdExDbFileName = os . path . join ( GenFdsGlobalVariable . FvDir , "PEIPcdDataBase.raw" )
else :
PcdExDbFileName = os . path . join ( self . EfiOutputPath , "PEIPcdDataBase.raw" )
PcdExDbSecName = os . path . join ( self . OutputPath , "PEIPcdDataBaseSec.raw" )
GenFdsGlobalVariable . GenerateSection ( PcdExDbSecName ,
[ PcdExDbFileName ],
"EFI_SECTION_RAW" ,
2017-11-22 15:42:25 +08:00
IsMakefile = IsMakefile
2013-11-18 07:41:21 +00:00
)
SectFiles . append ( PcdExDbSecName )
SectAlignments . append ( None )
elif self . PcdIsDriver == 'DXE_PCD_DRIVER' :
if self . IsBinaryModule :
PcdExDbFileName = os . path . join ( GenFdsGlobalVariable . FvDir , "DXEPcdDataBase.raw" )
else :
PcdExDbFileName = os . path . join ( self . EfiOutputPath , "DXEPcdDataBase.raw" )
PcdExDbSecName = os . path . join ( self . OutputPath , "DXEPcdDataBaseSec.raw" )
GenFdsGlobalVariable . GenerateSection ( PcdExDbSecName ,
2017-11-22 15:42:25 +08:00
[ PcdExDbFileName ],
"EFI_SECTION_RAW" ,
IsMakefile = IsMakefile
)
2013-11-18 07:41:21 +00:00
SectFiles . append ( PcdExDbSecName )
SectAlignments . append ( None )
2009-07-17 09:10:31 +00:00
for Sect in Rule . SectionList :
SecIndex = ' %d ' % Index
SectList = []
2009-11-09 11:47:35 +00:00
#
# Convert Fv Section Type for PI1.1 SMM driver.
#
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int ( self . PiSpecVersion , 16 ) >= 0x0001000A :
2018-04-27 00:57:56 +08:00
if Sect . SectionType == BINARY_FILE_TYPE_DXE_DEPEX :
Sect . SectionType = BINARY_FILE_TYPE_SMM_DEPEX
2009-11-09 11:47:35 +00:00
#
# Framework SMM Driver has no SMM_DEPEX section type
#
2018-04-27 00:57:53 +08:00
if self . ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int ( self . PiSpecVersion , 16 ) < 0x0001000A :
2018-04-27 00:57:56 +08:00
if Sect . SectionType == BINARY_FILE_TYPE_SMM_DEPEX :
2009-11-09 11:47:35 +00:00
EdkLogger . error ( "GenFds" , FORMAT_NOT_SUPPORTED , "Framework SMM module doesn't support SMM_DEPEX section type" , File = self . InfFileName )
2010-02-28 23:39:39 +00: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
2018-03-27 04:25:43 +08:00
if FvParentAddr is not None and isinstance ( Sect , GuidSection ):
2010-02-28 23:39:39 +00:00
Sect . FvParentAddr = FvParentAddr
2018-07-05 17:40:04 +08:00
2009-07-17 09:10:31 +00:00
if Rule . KeyStringList != []:
2018-06-25 18:31:33 +08:00
SectList , Align = Sect . GenSection ( self . OutputPath , self . ModuleGuid , SecIndex , Rule . KeyStringList , self , IsMakefile = IsMakefile )
2009-07-17 09:10:31 +00:00
else :
2018-06-25 18:31:33 +08:00
SectList , Align = Sect . GenSection ( self . OutputPath , self . ModuleGuid , SecIndex , self . KeyStringList , self , IsMakefile = IsMakefile )
2018-07-05 17:40:04 +08:00
2017-11-22 15:42:25 +08:00
if not HasGeneratedFlag :
2018-07-05 17:40:04 +08:00
UniVfrOffsetFileSection = ""
2015-10-08 09:27:14 +00:00
ModuleFileName = mws . join ( GenFdsGlobalVariable . WorkSpaceDir , self . InfFileName )
2011-05-11 10:26:49 +00:00
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" :
#
2018-07-05 17:40:04 +08:00
# search the .map file to find the offset of vfr binary in the PE32+/TE file.
2011-05-11 10:26:49 +00:00
#
VfrUniBaseName [ SourceFile . BaseName ] = ( SourceFile . BaseName + "Bin" )
if SourceFile . Type . upper () == ".UNI" :
#
2018-07-05 17:40:04 +08:00
# search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
2011-05-11 10:26:49 +00:00
#
VfrUniBaseName [ "UniOffsetName" ] = ( self . BaseName + "Strings" )
2018-07-05 17:40:04 +08:00
2011-05-11 10:26:49 +00:00
if len ( VfrUniBaseName ) > 0 :
2017-11-22 15:42:25 +08:00
if IsMakefile :
if InfData . BuildType != 'UEFI_HII' :
UniVfrOffsetFileName = os . path . join ( self . OutputPath , self . BaseName + '.offset' )
UniVfrOffsetFileSection = os . path . join ( self . OutputPath , self . BaseName + 'Offset' + '.raw' )
UniVfrOffsetFileNameList = []
UniVfrOffsetFileNameList . append ( UniVfrOffsetFileName )
TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName= %s --DebugDir= %s " % ( UniVfrOffsetFileName , self . BaseName , self . EfiDebugPath )
GenFdsGlobalVariable . SecCmdList . append ( TrimCmd )
GenFdsGlobalVariable . GenerateSection ( UniVfrOffsetFileSection ,
[ UniVfrOffsetFileName ],
"EFI_SECTION_RAW" ,
IsMakefile = True
)
else :
VfrUniOffsetList = self . __GetBuildOutputMapFileVfrUniInfo ( VfrUniBaseName )
#
# Generate the Raw data of raw section
#
if VfrUniOffsetList :
UniVfrOffsetFileName = os . path . join ( self . OutputPath , self . BaseName + '.offset' )
UniVfrOffsetFileSection = os . path . join ( self . OutputPath , self . BaseName + 'Offset' + '.raw' )
2018-04-14 04:51:35 +08:00
FfsInfStatement . __GenUniVfrOffsetFile ( VfrUniOffsetList , UniVfrOffsetFileName )
2017-11-22 15:42:25 +08:00
UniVfrOffsetFileNameList = []
UniVfrOffsetFileNameList . append ( UniVfrOffsetFileName )
"""Call GenSection"""
2016-09-22 09:48:46 +08:00
2017-11-22 15:42:25 +08:00
GenFdsGlobalVariable . GenerateSection ( UniVfrOffsetFileSection ,
UniVfrOffsetFileNameList ,
"EFI_SECTION_RAW"
)
#os.remove(UniVfrOffsetFileName)
if UniVfrOffsetFileSection :
2016-09-22 09:48:46 +08:00
SectList . append ( UniVfrOffsetFileSection )
2017-11-22 15:42:25 +08:00
HasGeneratedFlag = True
2018-07-05 17:40:04 +08:00
2009-07-17 09:10:31 +00: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
#
2017-11-22 15:42:25 +08:00
def __GenComplexFileFfs__ ( self , Rule , InputFile , Alignments , MakefilePath = None ):
2009-07-17 09:10:31 +00:00
2018-03-27 04:25:43 +08:00
if Rule . NameGuid is not None and Rule . NameGuid . startswith ( 'PCD(' ):
2009-07-17 09:10:31 +00:00
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 ,
2018-10-24 01:29:19 +08:00
FdfFvFileTypeToFileType [ Rule . FvFileType ],
2017-11-22 15:42:25 +08:00
self . ModuleGuid , Fixed = Rule . Fixed ,
CheckSum = Rule . CheckSum , Align = Rule . Alignment ,
SectionAlign = Alignments ,
MakefilePath = MakefilePath
)
2009-07-17 09:10:31 +00:00
return FfsOutput
2011-05-11 10:26:49 +00: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.
2018-07-05 17:40:04 +08:00
#
2011-05-11 10:26:49 +00:00
def __GetBuildOutputMapFileVfrUniInfo ( self , VfrUniBaseName ):
MapFileName = os . path . join ( self . EfiOutputPath , self . BaseName + ".map" )
2015-02-06 03:40:27 +00:00
EfiFileName = os . path . join ( self . EfiOutputPath , self . BaseName + ".efi" )
2019-01-28 15:06:30 +08:00
return GetVariableOffset ( MapFileName , EfiFileName , list ( VfrUniBaseName . values ()))
2018-07-05 17:40:04 +08:00
2011-05-11 10:26:49 +00:00
## __GenUniVfrOffsetFile() method
#
# Generate the offset file for the module which contain VFR or UNI file.
#
# @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file.
# @param UniVfrOffsetFileName The output offset file name.
#
2018-04-14 04:51:35 +08:00
@staticmethod
def __GenUniVfrOffsetFile ( VfrUniOffsetList , UniVfrOffsetFileName ):
2017-11-22 15:42:25 +08:00
2011-05-11 10:26:49 +00:00
# Use a instance of StringIO to cache data
2019-01-23 10:16:00 +08:00
fStringIO = BytesIO ()
2018-07-05 17:40:04 +08:00
2011-05-11 10:26:49 +00:00
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 } }
#
2019-01-23 10:16:00 +08:00
UniGuid = b ' \xe0\xc5\x13\x89\xf6 3 \x86 M \x9b\xf1 C \xef\x89\xfc\x06 f'
fStringIO . write ( UniGuid )
2011-05-11 10:26:49 +00:00
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 } };
#
2019-01-23 10:16:00 +08:00
VfrGuid = b ' \xb4 | \xbc\xd0 Gj_I \xaa\x11 q \x07 F \xda\x06\xa2 '
fStringIO . write ( VfrGuid )
2018-07-05 17:40:04 +08:00
type ( Item [ 1 ])
2011-05-11 10:26:49 +00:00
VfrValue = pack ( 'Q' , int ( Item [ 1 ], 16 ))
fStringIO . write ( VfrValue )
2018-07-05 17:40:04 +08:00
2011-05-11 10:26:49 +00:00
#
# write data into file.
#
2017-11-22 15:42:25 +08:00
try :
SaveFileOnChange ( UniVfrOffsetFileName , fStringIO . getvalue ())
2011-05-11 10:26:49 +00:00
except :
2018-06-25 18:31:33 +08:00
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 )
2018-07-05 17:40:04 +08:00
2011-05-11 10:26:49 +00:00
fStringIO . close ()