2018-09-13 16:11:07 -07:00
## @file
# Generate AutoGen.h, AutoGen.c and *.depex files
#
2019-06-11 10:40:54 -07:00
# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
# Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
# SPDX-License-Identifier: BSD-2-Clause-Patent
2018-09-13 16:11:07 -07:00
#
## Import Modules
#
2019-06-11 10:40:54 -07:00
from __future__ import print_function
from __future__ import absolute_import
2018-09-13 16:11:07 -07:00
import Common . LongFilePathOs as os
import re
import os . path as path
import copy
import uuid
2019-06-11 10:40:54 -07:00
from . import GenC
from . import GenMake
from . import GenDepex
from io import BytesIO
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
from . StrGather import *
from . BuildEngine import BuildRule
import shutil
2018-09-13 16:11:07 -07:00
from Common . LongFilePathSupport import CopyLongFilePath
from Common . BuildToolError import *
from Common . DataType import *
from Common . Misc import *
2019-06-11 10:40:54 -07:00
from Common . StringUtils import *
2018-09-13 16:11:07 -07:00
import Common . GlobalData as GlobalData
from GenFds . FdfParser import *
from CommonDataClass . CommonClass import SkuInfoClass
from GenPatchPcdTable . GenPatchPcdTable import parsePcdInfoFromMapFile
import Common . VpdInfoFile as VpdInfoFile
2019-06-11 10:40:54 -07:00
from . GenPcdDb import CreatePcdDatabaseCode
2018-09-13 16:11:07 -07:00
from Workspace . MetaFileCommentParser import UsageList
2019-06-11 10:40:54 -07:00
from Workspace . WorkspaceCommon import GetModuleLibInstances
2018-09-13 16:11:07 -07:00
from Common . MultipleWorkspace import MultipleWorkspace as mws
2019-06-11 10:40:54 -07:00
from . import InfSectionParser
2018-09-13 16:11:07 -07:00
import datetime
import hashlib
2019-06-11 10:40:54 -07:00
from . GenVar import VariableMgr , var_info
from collections import OrderedDict
from collections import defaultdict
from Workspace . WorkspaceCommon import OrderedListDict
from Common . ToolDefClassObject import gDefaultToolsDefFile
from Common . caching import cached_property , cached_class_function
2018-09-13 16:11:07 -07:00
## Regular expression for splitting Dependency Expression string into tokens
gDepexTokenPattern = re . compile ( " ( \ (| \ )| \ w+| \ S+ \ .inf) " )
2019-06-11 10:40:54 -07:00
## Regular expression for match: PCD(xxxx.yyy)
gPCDAsGuidPattern = re . compile ( r " ^PCD \ (.+ \ ..+ \ )$ " )
#
# Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
# is the former use /I , the Latter used -I to specify include directories
#
gBuildOptIncludePatternMsft = re . compile ( r " (?:.*?)/I[ \ t]*([^ ]*) " , re . MULTILINE | re . DOTALL )
gBuildOptIncludePatternOther = re . compile ( r " (?:.*?)-I[ \ t]*([^ ]*) " , re . MULTILINE | re . DOTALL )
2018-09-13 16:11:07 -07:00
#
# Match name = variable
#
gEfiVarStoreNamePattern = re . compile ( " \ s*name \ s*= \ s*( \ w+) " )
#
# The format of guid in efivarstore statement likes following and must be correct:
# guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
#
gEfiVarStoreGuidPattern = re . compile ( " \ s*guid \ s*= \ s*( { .*? { .*?} \ s*}) " )
## Mapping Makefile type
2019-06-11 10:40:54 -07:00
gMakeTypeMap = { TAB_COMPILER_MSFT : " nmake " , " GCC " : " gmake " }
2018-09-13 16:11:07 -07:00
## Build rule configuration file
gDefaultBuildRuleFile = ' build_rule.txt '
## Build rule default version
AutoGenReqBuildRuleVerNum = " 0.1 "
## default file name for AutoGen
gAutoGenCodeFileName = " AutoGen.c "
gAutoGenHeaderFileName = " AutoGen.h "
gAutoGenStringFileName = " %(module_name)s StrDefs.h "
gAutoGenStringFormFileName = " %(module_name)s StrDefs.hpk "
gAutoGenDepexFileName = " %(module_name)s .depex "
gAutoGenImageDefFileName = " %(module_name)s ImgDefs.h "
gAutoGenIdfFileName = " %(module_name)s Idf.hpk "
gInfSpecVersion = " 0x00010017 "
#
# Template string to generic AsBuilt INF
#
gAsBuiltInfHeaderString = TemplateString ( """ $ {header_comments}
# DO NOT EDIT
# FILE auto-generated
[Defines]
INF_VERSION = $ {module_inf_version}
BASE_NAME = $ {module_name}
FILE_GUID = $ {module_guid}
MODULE_TYPE = $ {module_module_type} $ {BEGIN}
VERSION_STRING = $ {module_version_string} $ {END} $ {BEGIN}
PCD_IS_DRIVER = $ {pcd_is_driver_string} $ {END} $ {BEGIN}
UEFI_SPECIFICATION_VERSION = $ {module_uefi_specification_version} $ {END} $ {BEGIN}
PI_SPECIFICATION_VERSION = $ {module_pi_specification_version} $ {END} $ {BEGIN}
ENTRY_POINT = $ {module_entry_point} $ {END} $ {BEGIN}
UNLOAD_IMAGE = $ {module_unload_image} $ {END} $ {BEGIN}
CONSTRUCTOR = $ {module_constructor} $ {END} $ {BEGIN}
DESTRUCTOR = $ {module_destructor} $ {END} $ {BEGIN}
SHADOW = $ {module_shadow} $ {END} $ {BEGIN}
PCI_VENDOR_ID = $ {module_pci_vendor_id} $ {END} $ {BEGIN}
PCI_DEVICE_ID = $ {module_pci_device_id} $ {END} $ {BEGIN}
PCI_CLASS_CODE = $ {module_pci_class_code} $ {END} $ {BEGIN}
PCI_REVISION = $ {module_pci_revision} $ {END} $ {BEGIN}
BUILD_NUMBER = $ {module_build_number} $ {END} $ {BEGIN}
SPEC = $ {module_spec} $ {END} $ {BEGIN}
UEFI_HII_RESOURCE_SECTION = $ {module_uefi_hii_resource_section} $ {END} $ {BEGIN}
MODULE_UNI_FILE = $ {module_uni_file} $ {END}
[Packages.$ {module_arch} ]$ {BEGIN}
$ {package_item} $ {END}
[Binaries.$ {module_arch} ]$ {BEGIN}
$ {binary_item} $ {END}
[PatchPcd.$ {module_arch} ]$ {BEGIN}
$ {patchablepcd_item}
$ {END}
[Protocols.$ {module_arch} ]$ {BEGIN}
$ {protocol_item}
$ {END}
[Ppis.$ {module_arch} ]$ {BEGIN}
$ {ppi_item}
$ {END}
[Guids.$ {module_arch} ]$ {BEGIN}
$ {guid_item}
$ {END}
[PcdEx.$ {module_arch} ]$ {BEGIN}
$ {pcd_item}
$ {END}
[LibraryClasses.$ {module_arch} ]
## @LIB_INSTANCES$ {BEGIN}
# $ {libraryclasses_item} $ {END}
$ {depexsection_item}
$ {userextension_tianocore_item}
$ {tail_comments}
[BuildOptions.$ {module_arch} ]
## @AsBuilt$ {BEGIN}
## $ {flags_item} $ {END}
""" )
2019-06-11 10:40:54 -07:00
## Split command line option string to list
#
# subprocess.Popen needs the args to be a sequence. Otherwise there's problem
# in non-windows platform to launch command
#
def _SplitOption ( OptionString ) :
OptionList = [ ]
LastChar = " "
OptionStart = 0
QuotationMark = " "
for Index in range ( 0 , len ( OptionString ) ) :
CurrentChar = OptionString [ Index ]
if CurrentChar in [ ' " ' , " ' " ] :
if QuotationMark == CurrentChar :
QuotationMark = " "
elif QuotationMark == " " :
QuotationMark = CurrentChar
continue
elif QuotationMark :
continue
if CurrentChar in [ " / " , " - " ] and LastChar in [ " " , " \t " , " \r " , " \n " ] :
if Index > OptionStart :
OptionList . append ( OptionString [ OptionStart : Index - 1 ] )
OptionStart = Index
LastChar = CurrentChar
OptionList . append ( OptionString [ OptionStart : ] )
return OptionList
#
# Convert string to C format array
#
def _ConvertStringToByteArray ( Value ) :
Value = Value . strip ( )
if not Value :
return None
if Value [ 0 ] == ' { ' :
if not Value . endswith ( ' } ' ) :
return None
Value = Value . replace ( ' ' , ' ' ) . replace ( ' { ' , ' ' ) . replace ( ' } ' , ' ' )
ValFields = Value . split ( ' , ' )
try :
for Index in range ( len ( ValFields ) ) :
ValFields [ Index ] = str ( int ( ValFields [ Index ] , 0 ) )
except ValueError :
return None
Value = ' { ' + ' , ' . join ( ValFields ) + ' } '
return Value
Unicode = False
if Value . startswith ( ' L " ' ) :
if not Value . endswith ( ' " ' ) :
return None
Value = Value [ 1 : ]
Unicode = True
elif not Value . startswith ( ' " ' ) or not Value . endswith ( ' " ' ) :
return None
Value = eval ( Value ) # translate escape character
NewValue = ' { '
for Index in range ( 0 , len ( Value ) ) :
if Unicode :
NewValue = NewValue + str ( ord ( Value [ Index ] ) % 0x10000 ) + ' , '
else :
NewValue = NewValue + str ( ord ( Value [ Index ] ) % 0x100 ) + ' , '
Value = NewValue + ' 0} '
return Value
2018-09-13 16:11:07 -07:00
## Base class for AutoGen
#
# This class just implements the cache mechanism of AutoGen objects.
#
class AutoGen ( object ) :
2019-06-11 10:40:54 -07:00
# database to maintain the objects in each child class
__ObjectCache = { } # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
2018-09-13 16:11:07 -07:00
## Factory method
#
# @param Class class object of real AutoGen class
# (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
# @param Workspace Workspace directory or WorkspaceAutoGen object
# @param MetaFile The path of meta file
# @param Target Build target
# @param Toolchain Tool chain name
# @param Arch Target arch
# @param *args The specific class related parameters
# @param **kwargs The specific class related dict parameters
#
2019-06-11 10:40:54 -07:00
def __new__ ( cls , Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs ) :
2018-09-13 16:11:07 -07:00
# check if the object has been created
2019-06-11 10:40:54 -07:00
Key = ( Target , Toolchain , Arch , MetaFile )
if Key in cls . __ObjectCache :
# if it exists, just return it directly
return cls . __ObjectCache [ Key ]
# it didnt exist. create it, cache it, then return it
RetVal = cls . __ObjectCache [ Key ] = super ( AutoGen , cls ) . __new__ ( cls )
return RetVal
2018-09-13 16:11:07 -07:00
## hash() operator
#
# The file path of platform file will be used to represent hash value of this object
#
# @retval int Hash value of the file path of platform file
#
def __hash__ ( self ) :
return hash ( self . MetaFile )
## str() operator
#
# The file path of platform file will be used to represent this object
#
# @retval string String of platform file path
#
def __str__ ( self ) :
return str ( self . MetaFile )
## "==" operator
def __eq__ ( self , Other ) :
return Other and self . MetaFile == Other
## Workspace AutoGen class
#
# This class is used mainly to control the whole platform build for different
# architecture. This class will generate top level makefile.
#
class WorkspaceAutoGen ( AutoGen ) :
2019-06-11 10:40:54 -07:00
# call super().__init__ then call the worker function with different parameter count
def __init__ ( self , Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs ) :
if not hasattr ( self , " _Init " ) :
self . _InitWorker ( Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs )
self . _Init = True
## Initialize WorkspaceAutoGen
2018-09-13 16:11:07 -07:00
#
# @param WorkspaceDir Root directory of workspace
# @param ActivePlatform Meta-file of active platform
# @param Target Build target
# @param Toolchain Tool chain name
# @param ArchList List of architecture of current build
# @param MetaFileDb Database containing meta-files
# @param BuildConfig Configuration of build
# @param ToolDefinition Tool chain definitions
# @param FlashDefinitionFile File of flash definition
# @param Fds FD list to be generated
# @param Fvs FV list to be generated
# @param Caps Capsule list to be generated
# @param SkuId SKU id from command line
#
2019-06-11 10:40:54 -07:00
def _InitWorker ( self , WorkspaceDir , ActivePlatform , Target , Toolchain , ArchList , MetaFileDb ,
2018-09-13 16:11:07 -07:00
BuildConfig , ToolDefinition , FlashDefinitionFile = ' ' , Fds = None , Fvs = None , Caps = None , SkuId = ' ' , UniFlag = None ,
Progress = None , BuildModule = None ) :
self . BuildDatabase = MetaFileDb
self . MetaFile = ActivePlatform
self . WorkspaceDir = WorkspaceDir
2019-06-11 10:40:54 -07:00
self . Platform = self . BuildDatabase [ self . MetaFile , TAB_ARCH_COMMON , Target , Toolchain ]
2018-09-13 16:11:07 -07:00
GlobalData . gActivePlatform = self . Platform
self . BuildTarget = Target
self . ToolChain = Toolchain
self . ArchList = ArchList
self . SkuId = SkuId
self . UniFlag = UniFlag
self . TargetTxt = BuildConfig
self . ToolDef = ToolDefinition
self . FdfFile = FlashDefinitionFile
2019-06-11 10:40:54 -07:00
self . FdTargetList = Fds if Fds else [ ]
self . FvTargetList = Fvs if Fvs else [ ]
self . CapTargetList = Caps if Caps else [ ]
2018-09-13 16:11:07 -07:00
self . AutoGenObjectList = [ ]
self . _GuidDict = { }
# there's many relative directory operations, so ...
os . chdir ( self . WorkspaceDir )
#
# Merge Arch
#
if not self . ArchList :
ArchList = set ( self . Platform . SupArchList )
else :
ArchList = set ( self . ArchList ) & set ( self . Platform . SupArchList )
if not ArchList :
EdkLogger . error ( " build " , PARAMETER_INVALID ,
ExtraData = " Invalid ARCH specified. [Valid ARCH: %s ] " % ( " " . join ( self . Platform . SupArchList ) ) )
elif self . ArchList and len ( ArchList ) != len ( self . ArchList ) :
SkippedArchList = set ( self . ArchList ) . symmetric_difference ( set ( self . Platform . SupArchList ) )
EdkLogger . verbose ( " \n Arch [ %s ] is ignored because the platform supports [ %s ] only! "
% ( " " . join ( SkippedArchList ) , " " . join ( self . Platform . SupArchList ) ) )
self . ArchList = tuple ( ArchList )
# Validate build target
if self . BuildTarget not in self . Platform . BuildTargets :
EdkLogger . error ( " build " , PARAMETER_INVALID ,
ExtraData = " Build target [ %s ] is not supported by the platform. [Valid target: %s ] "
% ( self . BuildTarget , " " . join ( self . Platform . BuildTargets ) ) )
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
# parse FDF file to get PCDs in it, if any
if not self . FdfFile :
self . FdfFile = self . Platform . FlashDefinition
EdkLogger . info ( " " )
if self . ArchList :
EdkLogger . info ( ' %-16s = %s ' % ( " Architecture(s) " , ' ' . join ( self . ArchList ) ) )
EdkLogger . info ( ' %-16s = %s ' % ( " Build target " , self . BuildTarget ) )
EdkLogger . info ( ' %-16s = %s ' % ( " Toolchain " , self . ToolChain ) )
EdkLogger . info ( ' \n %-24s = %s ' % ( " Active Platform " , self . Platform ) )
if BuildModule :
EdkLogger . info ( ' %-24s = %s ' % ( " Active Module " , BuildModule ) )
if self . FdfFile :
EdkLogger . info ( ' %-24s = %s ' % ( " Flash Image Definition " , self . FdfFile ) )
EdkLogger . verbose ( " \n FLASH_DEFINITION = %s " % self . FdfFile )
if Progress :
Progress . Start ( " \n Processing meta-data " )
if self . FdfFile :
#
# Mark now build in AutoGen Phase
#
GlobalData . gAutoGenPhase = True
Fdf = FdfParser ( self . FdfFile . Path )
Fdf . ParseFile ( )
GlobalData . gFdfParser = Fdf
GlobalData . gAutoGenPhase = False
PcdSet = Fdf . Profile . PcdDict
if Fdf . CurrentFdName and Fdf . CurrentFdName in Fdf . Profile . FdDict :
FdDict = Fdf . Profile . FdDict [ Fdf . CurrentFdName ]
for FdRegion in FdDict . RegionList :
if str ( FdRegion . RegionType ) is ' FILE ' and self . Platform . VpdToolGuid in str ( FdRegion . RegionDataList ) :
if int ( FdRegion . Offset ) % 8 != 0 :
EdkLogger . error ( " build " , FORMAT_INVALID , ' The VPD Base Address %s must be 8-byte aligned. ' % ( FdRegion . Offset ) )
ModuleList = Fdf . Profile . InfList
self . FdfProfile = Fdf . Profile
for fvname in self . FvTargetList :
if fvname . upper ( ) not in self . FdfProfile . FvDict :
EdkLogger . error ( " build " , OPTION_VALUE_INVALID ,
" No such an FV in FDF file: %s " % fvname )
# In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
# but the path (self.MetaFile.Path) is the real path
for key in self . FdfProfile . InfDict :
if key == ' ArchTBD ' :
2019-06-11 10:40:54 -07:00
MetaFile_cache = defaultdict ( set )
2018-09-13 16:11:07 -07:00
for Arch in self . ArchList :
2019-06-11 10:40:54 -07:00
Current_Platform_cache = self . BuildDatabase [ self . MetaFile , Arch , Target , Toolchain ]
for Pkey in Current_Platform_cache . Modules :
MetaFile_cache [ Arch ] . add ( Current_Platform_cache . Modules [ Pkey ] . MetaFile )
2018-09-13 16:11:07 -07:00
for Inf in self . FdfProfile . InfDict [ key ] :
ModuleFile = PathClass ( NormPath ( Inf ) , GlobalData . gWorkspace , Arch )
for Arch in self . ArchList :
if ModuleFile in MetaFile_cache [ Arch ] :
break
else :
ModuleData = self . BuildDatabase [ ModuleFile , Arch , Target , Toolchain ]
if not ModuleData . IsBinaryModule :
EdkLogger . error ( ' build ' , PARSER_ERROR , " Module %s NOT found in DSC file; Is it really a binary module? " % ModuleFile )
else :
for Arch in self . ArchList :
if Arch == key :
Platform = self . BuildDatabase [ self . MetaFile , Arch , Target , Toolchain ]
2019-06-11 10:40:54 -07:00
MetaFileList = set ( )
for Pkey in Platform . Modules :
MetaFileList . add ( Platform . Modules [ Pkey ] . MetaFile )
2018-09-13 16:11:07 -07:00
for Inf in self . FdfProfile . InfDict [ key ] :
ModuleFile = PathClass ( NormPath ( Inf ) , GlobalData . gWorkspace , Arch )
if ModuleFile in MetaFileList :
continue
ModuleData = self . BuildDatabase [ ModuleFile , Arch , Target , Toolchain ]
if not ModuleData . IsBinaryModule :
EdkLogger . error ( ' build ' , PARSER_ERROR , " Module %s NOT found in DSC file; Is it really a binary module? " % ModuleFile )
else :
PcdSet = { }
ModuleList = [ ]
self . FdfProfile = None
if self . FdTargetList :
EdkLogger . info ( " No flash definition file found. FD [ %s ] will be ignored. " % " " . join ( self . FdTargetList ) )
self . FdTargetList = [ ]
if self . FvTargetList :
EdkLogger . info ( " No flash definition file found. FV [ %s ] will be ignored. " % " " . join ( self . FvTargetList ) )
self . FvTargetList = [ ]
if self . CapTargetList :
EdkLogger . info ( " No flash definition file found. Capsule [ %s ] will be ignored. " % " " . join ( self . CapTargetList ) )
self . CapTargetList = [ ]
# apply SKU and inject PCDs from Flash Definition file
for Arch in self . ArchList :
Platform = self . BuildDatabase [ self . MetaFile , Arch , Target , Toolchain ]
2019-06-11 10:40:54 -07:00
PlatformPcds = Platform . Pcds
self . _GuidDict = Platform . _GuidDict
SourcePcdDict = { TAB_PCDS_DYNAMIC_EX : set ( ) , TAB_PCDS_PATCHABLE_IN_MODULE : set ( ) , TAB_PCDS_DYNAMIC : set ( ) , TAB_PCDS_FIXED_AT_BUILD : set ( ) }
BinaryPcdDict = { TAB_PCDS_DYNAMIC_EX : set ( ) , TAB_PCDS_PATCHABLE_IN_MODULE : set ( ) }
2018-09-13 16:11:07 -07:00
SourcePcdDict_Keys = SourcePcdDict . keys ( )
BinaryPcdDict_Keys = BinaryPcdDict . keys ( )
# generate the SourcePcdDict and BinaryPcdDict
PGen = PlatformAutoGen ( self , self . MetaFile , Target , Toolchain , Arch )
2019-06-11 10:40:54 -07:00
for BuildData in list ( PGen . BuildDatabase . _CACHE_ . values ( ) ) :
2018-09-13 16:11:07 -07:00
if BuildData . Arch != Arch :
continue
if BuildData . MetaFile . Ext == ' .inf ' :
for key in BuildData . Pcds :
if BuildData . Pcds [ key ] . Pending :
if key in Platform . Pcds :
PcdInPlatform = Platform . Pcds [ key ]
2019-06-11 10:40:54 -07:00
if PcdInPlatform . Type :
2018-09-13 16:11:07 -07:00
BuildData . Pcds [ key ] . Type = PcdInPlatform . Type
2019-06-11 10:40:54 -07:00
BuildData . Pcds [ key ] . Pending = False
2018-09-13 16:11:07 -07:00
if BuildData . MetaFile in Platform . Modules :
PlatformModule = Platform . Modules [ str ( BuildData . MetaFile ) ]
if key in PlatformModule . Pcds :
PcdInPlatform = PlatformModule . Pcds [ key ]
2019-06-11 10:40:54 -07:00
if PcdInPlatform . Type :
2018-09-13 16:11:07 -07:00
BuildData . Pcds [ key ] . Type = PcdInPlatform . Type
2019-06-11 10:40:54 -07:00
BuildData . Pcds [ key ] . Pending = False
2018-09-13 16:11:07 -07:00
else :
2019-06-11 10:40:54 -07:00
#Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
if BuildData . Pcds [ key ] . Pending :
MGen = ModuleAutoGen ( self , BuildData . MetaFile , Target , Toolchain , Arch , self . MetaFile )
if MGen and MGen . IsLibrary :
if MGen in PGen . LibraryAutoGenList :
ReferenceModules = MGen . ReferenceModules
for ReferenceModule in ReferenceModules :
if ReferenceModule . MetaFile in Platform . Modules :
RefPlatformModule = Platform . Modules [ str ( ReferenceModule . MetaFile ) ]
if key in RefPlatformModule . Pcds :
PcdInReferenceModule = RefPlatformModule . Pcds [ key ]
if PcdInReferenceModule . Type :
BuildData . Pcds [ key ] . Type = PcdInReferenceModule . Type
BuildData . Pcds [ key ] . Pending = False
break
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
if TAB_PCDS_DYNAMIC_EX in BuildData . Pcds [ key ] . Type :
if BuildData . IsBinaryModule :
BinaryPcdDict [ TAB_PCDS_DYNAMIC_EX ] . add ( ( BuildData . Pcds [ key ] . TokenCName , BuildData . Pcds [ key ] . TokenSpaceGuidCName ) )
else :
SourcePcdDict [ TAB_PCDS_DYNAMIC_EX ] . add ( ( BuildData . Pcds [ key ] . TokenCName , BuildData . Pcds [ key ] . TokenSpaceGuidCName ) )
elif TAB_PCDS_PATCHABLE_IN_MODULE in BuildData . Pcds [ key ] . Type :
2018-09-13 16:11:07 -07:00
if BuildData . MetaFile . Ext == ' .inf ' :
if BuildData . IsBinaryModule :
2019-06-11 10:40:54 -07:00
BinaryPcdDict [ TAB_PCDS_PATCHABLE_IN_MODULE ] . add ( ( BuildData . Pcds [ key ] . TokenCName , BuildData . Pcds [ key ] . TokenSpaceGuidCName ) )
2018-09-13 16:11:07 -07:00
else :
2019-06-11 10:40:54 -07:00
SourcePcdDict [ TAB_PCDS_PATCHABLE_IN_MODULE ] . add ( ( BuildData . Pcds [ key ] . TokenCName , BuildData . Pcds [ key ] . TokenSpaceGuidCName ) )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
elif TAB_PCDS_DYNAMIC in BuildData . Pcds [ key ] . Type :
SourcePcdDict [ TAB_PCDS_DYNAMIC ] . add ( ( BuildData . Pcds [ key ] . TokenCName , BuildData . Pcds [ key ] . TokenSpaceGuidCName ) )
elif TAB_PCDS_FIXED_AT_BUILD in BuildData . Pcds [ key ] . Type :
SourcePcdDict [ TAB_PCDS_FIXED_AT_BUILD ] . add ( ( BuildData . Pcds [ key ] . TokenCName , BuildData . Pcds [ key ] . TokenSpaceGuidCName ) )
2018-09-13 16:11:07 -07:00
else :
pass
#
# A PCD can only use one type for all source modules
#
for i in SourcePcdDict_Keys :
for j in SourcePcdDict_Keys :
if i != j :
2019-06-11 10:40:54 -07:00
Intersections = SourcePcdDict [ i ] . intersection ( SourcePcdDict [ j ] )
if len ( Intersections ) > 0 :
2018-09-13 16:11:07 -07:00
EdkLogger . error (
' build ' ,
FORMAT_INVALID ,
" Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method. " % ( i , j ) ,
2019-06-11 10:40:54 -07:00
ExtraData = ' \n \t ' . join ( str ( P [ 1 ] + ' . ' + P [ 0 ] ) for P in Intersections )
2018-09-13 16:11:07 -07:00
)
#
# intersection the BinaryPCD for Mixed PCD
#
for i in BinaryPcdDict_Keys :
for j in BinaryPcdDict_Keys :
if i != j :
2019-06-11 10:40:54 -07:00
Intersections = BinaryPcdDict [ i ] . intersection ( BinaryPcdDict [ j ] )
for item in Intersections :
2018-09-13 16:11:07 -07:00
NewPcd1 = ( item [ 0 ] + ' _ ' + i , item [ 1 ] )
NewPcd2 = ( item [ 0 ] + ' _ ' + j , item [ 1 ] )
if item not in GlobalData . MixedPcd :
GlobalData . MixedPcd [ item ] = [ NewPcd1 , NewPcd2 ]
else :
if NewPcd1 not in GlobalData . MixedPcd [ item ] :
GlobalData . MixedPcd [ item ] . append ( NewPcd1 )
if NewPcd2 not in GlobalData . MixedPcd [ item ] :
GlobalData . MixedPcd [ item ] . append ( NewPcd2 )
#
# intersection the SourcePCD and BinaryPCD for Mixed PCD
#
for i in SourcePcdDict_Keys :
for j in BinaryPcdDict_Keys :
if i != j :
2019-06-11 10:40:54 -07:00
Intersections = SourcePcdDict [ i ] . intersection ( BinaryPcdDict [ j ] )
for item in Intersections :
2018-09-13 16:11:07 -07:00
NewPcd1 = ( item [ 0 ] + ' _ ' + i , item [ 1 ] )
NewPcd2 = ( item [ 0 ] + ' _ ' + j , item [ 1 ] )
if item not in GlobalData . MixedPcd :
GlobalData . MixedPcd [ item ] = [ NewPcd1 , NewPcd2 ]
else :
if NewPcd1 not in GlobalData . MixedPcd [ item ] :
GlobalData . MixedPcd [ item ] . append ( NewPcd1 )
if NewPcd2 not in GlobalData . MixedPcd [ item ] :
GlobalData . MixedPcd [ item ] . append ( NewPcd2 )
2019-06-11 10:40:54 -07:00
for BuildData in list ( PGen . BuildDatabase . _CACHE_ . values ( ) ) :
2018-09-13 16:11:07 -07:00
if BuildData . Arch != Arch :
continue
for key in BuildData . Pcds :
for SinglePcd in GlobalData . MixedPcd :
if ( BuildData . Pcds [ key ] . TokenCName , BuildData . Pcds [ key ] . TokenSpaceGuidCName ) == SinglePcd :
for item in GlobalData . MixedPcd [ SinglePcd ] :
Pcd_Type = item [ 0 ] . split ( ' _ ' ) [ - 1 ]
2019-06-11 10:40:54 -07:00
if ( Pcd_Type == BuildData . Pcds [ key ] . Type ) or ( Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData . Pcds [ key ] . Type in PCD_DYNAMIC_EX_TYPE_SET ) or \
( Pcd_Type == TAB_PCDS_DYNAMIC and BuildData . Pcds [ key ] . Type in PCD_DYNAMIC_TYPE_SET ) :
2018-09-13 16:11:07 -07:00
Value = BuildData . Pcds [ key ]
Value . TokenCName = BuildData . Pcds [ key ] . TokenCName + ' _ ' + Pcd_Type
if len ( key ) == 2 :
newkey = ( Value . TokenCName , key [ 1 ] )
elif len ( key ) == 3 :
newkey = ( Value . TokenCName , key [ 1 ] , key [ 2 ] )
del BuildData . Pcds [ key ]
BuildData . Pcds [ newkey ] = Value
break
break
# handle the mixed pcd in FDF file
for key in PcdSet :
if key in GlobalData . MixedPcd :
Value = PcdSet [ key ]
del PcdSet [ key ]
for item in GlobalData . MixedPcd [ key ] :
PcdSet [ item ] = Value
#Collect package set information from INF of FDF
PkgSet = set ( )
for Inf in ModuleList :
ModuleFile = PathClass ( NormPath ( Inf ) , GlobalData . gWorkspace , Arch )
if ModuleFile in Platform . Modules :
continue
ModuleData = self . BuildDatabase [ ModuleFile , Arch , Target , Toolchain ]
PkgSet . update ( ModuleData . Packages )
Pkgs = list ( PkgSet ) + list ( PGen . PackageList )
2019-06-11 10:40:54 -07:00
DecPcds = set ( )
2018-09-13 16:11:07 -07:00
DecPcdsKey = set ( )
for Pkg in Pkgs :
for Pcd in Pkg . Pcds :
2019-06-11 10:40:54 -07:00
DecPcds . add ( ( Pcd [ 0 ] , Pcd [ 1 ] ) )
2018-09-13 16:11:07 -07:00
DecPcdsKey . add ( ( Pcd [ 0 ] , Pcd [ 1 ] , Pcd [ 2 ] ) )
Platform . SkuName = self . SkuId
2019-06-11 10:40:54 -07:00
for Name , Guid , Fileds in PcdSet :
2018-09-13 16:11:07 -07:00
if ( Name , Guid ) not in DecPcds :
EdkLogger . error (
' build ' ,
PARSER_ERROR ,
" PCD ( %s . %s ) used in FDF is not declared in DEC files. " % ( Guid , Name ) ,
2019-06-11 10:40:54 -07:00
File = self . FdfProfile . PcdFileLineDict [ Name , Guid , Fileds ] [ 0 ] ,
Line = self . FdfProfile . PcdFileLineDict [ Name , Guid , Fileds ] [ 1 ]
2018-09-13 16:11:07 -07:00
)
else :
# Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
if ( Name , Guid , TAB_PCDS_FIXED_AT_BUILD ) in DecPcdsKey \
or ( Name , Guid , TAB_PCDS_PATCHABLE_IN_MODULE ) in DecPcdsKey \
or ( Name , Guid , TAB_PCDS_FEATURE_FLAG ) in DecPcdsKey :
continue
elif ( Name , Guid , TAB_PCDS_DYNAMIC ) in DecPcdsKey or ( Name , Guid , TAB_PCDS_DYNAMIC_EX ) in DecPcdsKey :
EdkLogger . error (
' build ' ,
PARSER_ERROR ,
" Using Dynamic or DynamicEx type of PCD [ %s . %s ] in FDF file is not allowed. " % ( Guid , Name ) ,
2019-06-11 10:40:54 -07:00
File = self . FdfProfile . PcdFileLineDict [ Name , Guid , Fileds ] [ 0 ] ,
Line = self . FdfProfile . PcdFileLineDict [ Name , Guid , Fileds ] [ 1 ]
2018-09-13 16:11:07 -07:00
)
Pa = PlatformAutoGen ( self , self . MetaFile , Target , Toolchain , Arch )
#
# Explicitly collect platform's dynamic PCDs
#
Pa . CollectPlatformDynamicPcds ( )
Pa . CollectFixedAtBuildPcds ( )
self . AutoGenObjectList . append ( Pa )
#
# Generate Package level hash value
#
2019-06-11 10:40:54 -07:00
GlobalData . gPackageHash = { }
2018-09-13 16:11:07 -07:00
if GlobalData . gUseHashCache :
for Pkg in Pkgs :
self . _GenPkgLevelHash ( Pkg )
#
# Check PCDs token value conflict in each DEC file.
#
self . _CheckAllPcdsTokenValueConflict ( )
#
# Check PCD type and definition between DSC and DEC
#
self . _CheckPcdDefineAndType ( )
#
# Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
#
content = ' gCommandLineDefines: '
content + = str ( GlobalData . gCommandLineDefines )
2019-06-11 10:40:54 -07:00
content + = TAB_LINE_BREAK
2018-09-13 16:11:07 -07:00
content + = ' BuildOptionPcd: '
content + = str ( GlobalData . BuildOptionPcd )
2019-06-11 10:40:54 -07:00
content + = TAB_LINE_BREAK
2018-09-13 16:11:07 -07:00
content + = ' Active Platform: '
content + = str ( self . Platform )
2019-06-11 10:40:54 -07:00
content + = TAB_LINE_BREAK
2018-09-13 16:11:07 -07:00
if self . FdfFile :
content + = ' Flash Image Definition: '
content + = str ( self . FdfFile )
2019-06-11 10:40:54 -07:00
content + = TAB_LINE_BREAK
2018-09-13 16:11:07 -07:00
SaveFileOnChange ( os . path . join ( self . BuildDir , ' BuildOptions ' ) , content , False )
#
# Create PcdToken Number file for Dynamic/DynamicEx Pcd.
#
PcdTokenNumber = ' PcdTokenNumber: '
if Pa . PcdTokenNumber :
if Pa . DynamicPcdList :
for Pcd in Pa . DynamicPcdList :
2019-06-11 10:40:54 -07:00
PcdTokenNumber + = TAB_LINE_BREAK
2018-09-13 16:11:07 -07:00
PcdTokenNumber + = str ( ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) )
PcdTokenNumber + = ' : '
PcdTokenNumber + = str ( Pa . PcdTokenNumber [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] )
SaveFileOnChange ( os . path . join ( self . BuildDir , ' PcdTokenNumber ' ) , PcdTokenNumber , False )
#
# Get set of workspace metafiles
#
AllWorkSpaceMetaFiles = self . _GetMetaFiles ( Target , Toolchain , Arch )
#
# Retrieve latest modified time of all metafiles
#
SrcTimeStamp = 0
for f in AllWorkSpaceMetaFiles :
if os . stat ( f ) [ 8 ] > SrcTimeStamp :
SrcTimeStamp = os . stat ( f ) [ 8 ]
self . _SrcTimeStamp = SrcTimeStamp
if GlobalData . gUseHashCache :
m = hashlib . md5 ( )
for files in AllWorkSpaceMetaFiles :
if files . endswith ( ' .dec ' ) :
continue
2019-06-11 10:40:54 -07:00
f = open ( files , ' rb ' )
2018-09-13 16:11:07 -07:00
Content = f . read ( )
f . close ( )
m . update ( Content )
2019-06-11 10:40:54 -07:00
SaveFileOnChange ( os . path . join ( self . BuildDir , ' AutoGen.hash ' ) , m . hexdigest ( ) , False )
2018-09-13 16:11:07 -07:00
GlobalData . gPlatformHash = m . hexdigest ( )
#
# Write metafile list to build directory
#
AutoGenFilePath = os . path . join ( self . BuildDir , ' AutoGen ' )
if os . path . exists ( AutoGenFilePath ) :
os . remove ( AutoGenFilePath )
if not os . path . exists ( self . BuildDir ) :
os . makedirs ( self . BuildDir )
with open ( os . path . join ( self . BuildDir , ' AutoGen ' ) , ' w+ ' ) as file :
for f in AllWorkSpaceMetaFiles :
2019-06-11 10:40:54 -07:00
print ( f , file = file )
2018-09-13 16:11:07 -07:00
return True
def _GenPkgLevelHash ( self , Pkg ) :
2019-06-11 10:40:54 -07:00
if Pkg . PackageName in GlobalData . gPackageHash :
return
2018-09-13 16:11:07 -07:00
PkgDir = os . path . join ( self . BuildDir , Pkg . Arch , Pkg . PackageName )
CreateDirectory ( PkgDir )
HashFile = os . path . join ( PkgDir , Pkg . PackageName + ' .hash ' )
m = hashlib . md5 ( )
# Get .dec file's hash value
2019-06-11 10:40:54 -07:00
f = open ( Pkg . MetaFile . Path , ' rb ' )
2018-09-13 16:11:07 -07:00
Content = f . read ( )
f . close ( )
m . update ( Content )
# Get include files hash value
if Pkg . Includes :
2019-06-11 10:40:54 -07:00
for inc in sorted ( Pkg . Includes , key = lambda x : str ( x ) ) :
2018-09-13 16:11:07 -07:00
for Root , Dirs , Files in os . walk ( str ( inc ) ) :
2019-06-11 10:40:54 -07:00
for File in sorted ( Files ) :
2018-09-13 16:11:07 -07:00
File_Path = os . path . join ( Root , File )
2019-06-11 10:40:54 -07:00
f = open ( File_Path , ' rb ' )
2018-09-13 16:11:07 -07:00
Content = f . read ( )
f . close ( )
m . update ( Content )
2019-06-11 10:40:54 -07:00
SaveFileOnChange ( HashFile , m . hexdigest ( ) , False )
GlobalData . gPackageHash [ Pkg . PackageName ] = m . hexdigest ( )
2018-09-13 16:11:07 -07:00
def _GetMetaFiles ( self , Target , Toolchain , Arch ) :
AllWorkSpaceMetaFiles = set ( )
#
# add fdf
#
if self . FdfFile :
AllWorkSpaceMetaFiles . add ( self . FdfFile . Path )
2019-06-11 10:40:54 -07:00
for f in GlobalData . gFdfParser . GetAllIncludedFile ( ) :
AllWorkSpaceMetaFiles . add ( f . FileName )
2018-09-13 16:11:07 -07:00
#
# add dsc
#
AllWorkSpaceMetaFiles . add ( self . MetaFile . Path )
#
# add build_rule.txt & tools_def.txt
#
AllWorkSpaceMetaFiles . add ( os . path . join ( GlobalData . gConfDirectory , gDefaultBuildRuleFile ) )
AllWorkSpaceMetaFiles . add ( os . path . join ( GlobalData . gConfDirectory , gDefaultToolsDefFile ) )
# add BuildOption metafile
#
AllWorkSpaceMetaFiles . add ( os . path . join ( self . BuildDir , ' BuildOptions ' ) )
# add PcdToken Number file for Dynamic/DynamicEx Pcd
#
AllWorkSpaceMetaFiles . add ( os . path . join ( self . BuildDir , ' PcdTokenNumber ' ) )
for Arch in self . ArchList :
#
# add dec
#
2019-06-11 10:40:54 -07:00
for Package in PlatformAutoGen ( self , self . MetaFile , Target , Toolchain , Arch ) . PackageList :
2018-09-13 16:11:07 -07:00
AllWorkSpaceMetaFiles . add ( Package . MetaFile . Path )
#
# add included dsc
#
2019-06-11 10:40:54 -07:00
for filePath in self . BuildDatabase [ self . MetaFile , Arch , Target , Toolchain ] . _RawData . IncludedFiles :
2018-09-13 16:11:07 -07:00
AllWorkSpaceMetaFiles . add ( filePath . Path )
return AllWorkSpaceMetaFiles
def _CheckPcdDefineAndType ( self ) :
2019-06-11 10:40:54 -07:00
PcdTypeSet = { TAB_PCDS_FIXED_AT_BUILD ,
TAB_PCDS_PATCHABLE_IN_MODULE ,
TAB_PCDS_FEATURE_FLAG ,
TAB_PCDS_DYNAMIC ,
TAB_PCDS_DYNAMIC_EX }
2018-09-13 16:11:07 -07:00
# This dict store PCDs which are not used by any modules with specified arches
2019-06-11 10:40:54 -07:00
UnusedPcd = OrderedDict ( )
2018-09-13 16:11:07 -07:00
for Pa in self . AutoGenObjectList :
# Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
for Pcd in Pa . Platform . Pcds :
PcdType = Pa . Platform . Pcds [ Pcd ] . Type
2019-06-11 10:40:54 -07:00
# If no PCD type, this PCD comes from FDF
2018-09-13 16:11:07 -07:00
if not PcdType :
continue
# Try to remove Hii and Vpd suffix
2019-06-11 10:40:54 -07:00
if PcdType . startswith ( TAB_PCDS_DYNAMIC_EX ) :
PcdType = TAB_PCDS_DYNAMIC_EX
elif PcdType . startswith ( TAB_PCDS_DYNAMIC ) :
PcdType = TAB_PCDS_DYNAMIC
2018-09-13 16:11:07 -07:00
for Package in Pa . PackageList :
# Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
if ( Pcd [ 0 ] , Pcd [ 1 ] , PcdType ) in Package . Pcds :
break
2019-06-11 10:40:54 -07:00
for Type in PcdTypeSet :
2018-09-13 16:11:07 -07:00
if ( Pcd [ 0 ] , Pcd [ 1 ] , Type ) in Package . Pcds :
EdkLogger . error (
' build ' ,
FORMAT_INVALID ,
" Type [ %s ] of PCD [ %s . %s ] in DSC file doesn ' t match the type [ %s ] defined in DEC file. " \
% ( Pa . Platform . Pcds [ Pcd ] . Type , Pcd [ 1 ] , Pcd [ 0 ] , Type ) ,
ExtraData = None
)
return
else :
UnusedPcd . setdefault ( Pcd , [ ] ) . append ( Pa . Arch )
for Pcd in UnusedPcd :
EdkLogger . warn (
' build ' ,
" The PCD was not specified by any INF module in the platform for the given architecture. \n "
" \t PCD: [ %s . %s ] \n \t Platform: [ %s ] \n \t Arch: %s "
% ( Pcd [ 1 ] , Pcd [ 0 ] , os . path . basename ( str ( self . MetaFile ) ) , str ( UnusedPcd [ Pcd ] ) ) ,
ExtraData = None
)
def __repr__ ( self ) :
return " %s [ %s ] " % ( self . MetaFile , " , " . join ( self . ArchList ) )
## Return the directory to store FV files
2019-06-11 10:40:54 -07:00
@cached_property
def FvDir ( self ) :
return path . join ( self . BuildDir , TAB_FV_DIRECTORY )
2018-09-13 16:11:07 -07:00
## Return the directory to store all intermediate and final files built
2019-06-11 10:40:54 -07:00
@cached_property
def BuildDir ( self ) :
return self . AutoGenObjectList [ 0 ] . BuildDir
2018-09-13 16:11:07 -07:00
## Return the build output directory platform specifies
2019-06-11 10:40:54 -07:00
@cached_property
def OutputDir ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . OutputDirectory
## Return platform name
2019-06-11 10:40:54 -07:00
@cached_property
def Name ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . PlatformName
## Return meta-file GUID
2019-06-11 10:40:54 -07:00
@cached_property
def Guid ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . Guid
## Return platform version
2019-06-11 10:40:54 -07:00
@cached_property
def Version ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . Version
## Return paths of tools
2019-06-11 10:40:54 -07:00
@cached_property
def ToolDefinition ( self ) :
2018-09-13 16:11:07 -07:00
return self . AutoGenObjectList [ 0 ] . ToolDefinition
## Return directory of platform makefile
#
# @retval string Makefile directory
#
2019-06-11 10:40:54 -07:00
@cached_property
def MakeFileDir ( self ) :
return self . BuildDir
2018-09-13 16:11:07 -07:00
## Return build command string
#
# @retval string Build command string
#
2019-06-11 10:40:54 -07:00
@cached_property
def BuildCommand ( self ) :
# BuildCommand should be all the same. So just get one from platform AutoGen
return self . AutoGenObjectList [ 0 ] . BuildCommand
2018-09-13 16:11:07 -07:00
## Check the PCDs token value conflict in each DEC file.
#
# Will cause build break and raise error message while two PCDs conflict.
2019-06-11 10:40:54 -07:00
#
2018-09-13 16:11:07 -07:00
# @return None
#
def _CheckAllPcdsTokenValueConflict ( self ) :
for Pa in self . AutoGenObjectList :
for Package in Pa . PackageList :
2019-06-11 10:40:54 -07:00
PcdList = list ( Package . Pcds . values ( ) )
PcdList . sort ( key = lambda x : int ( x . TokenValue , 0 ) )
2018-09-13 16:11:07 -07:00
Count = 0
while ( Count < len ( PcdList ) - 1 ) :
Item = PcdList [ Count ]
ItemNext = PcdList [ Count + 1 ]
#
# Make sure in the same token space the TokenValue should be unique
#
if ( int ( Item . TokenValue , 0 ) == int ( ItemNext . TokenValue , 0 ) ) :
SameTokenValuePcdList = [ ]
SameTokenValuePcdList . append ( Item )
SameTokenValuePcdList . append ( ItemNext )
RemainPcdListLength = len ( PcdList ) - Count - 2
for ValueSameCount in range ( RemainPcdListLength ) :
if int ( PcdList [ len ( PcdList ) - RemainPcdListLength + ValueSameCount ] . TokenValue , 0 ) == int ( Item . TokenValue , 0 ) :
SameTokenValuePcdList . append ( PcdList [ len ( PcdList ) - RemainPcdListLength + ValueSameCount ] )
else :
break ;
#
# Sort same token value PCD list with TokenGuid and TokenCName
#
2019-06-11 10:40:54 -07:00
SameTokenValuePcdList . sort ( key = lambda x : " %s . %s " % ( x . TokenSpaceGuidCName , x . TokenCName ) )
2018-09-13 16:11:07 -07:00
SameTokenValuePcdListCount = 0
while ( SameTokenValuePcdListCount < len ( SameTokenValuePcdList ) - 1 ) :
Flag = False
TemListItem = SameTokenValuePcdList [ SameTokenValuePcdListCount ]
TemListItemNext = SameTokenValuePcdList [ SameTokenValuePcdListCount + 1 ]
if ( TemListItem . TokenSpaceGuidCName == TemListItemNext . TokenSpaceGuidCName ) and ( TemListItem . TokenCName != TemListItemNext . TokenCName ) :
for PcdItem in GlobalData . MixedPcd :
if ( TemListItem . TokenCName , TemListItem . TokenSpaceGuidCName ) in GlobalData . MixedPcd [ PcdItem ] or \
( TemListItemNext . TokenCName , TemListItemNext . TokenSpaceGuidCName ) in GlobalData . MixedPcd [ PcdItem ] :
Flag = True
if not Flag :
EdkLogger . error (
' build ' ,
FORMAT_INVALID ,
" The TokenValue [ %s ] of PCD [ %s . %s ] is conflict with: [ %s . %s ] in %s " \
% ( TemListItem . TokenValue , TemListItem . TokenSpaceGuidCName , TemListItem . TokenCName , TemListItemNext . TokenSpaceGuidCName , TemListItemNext . TokenCName , Package ) ,
ExtraData = None
)
SameTokenValuePcdListCount + = 1
Count + = SameTokenValuePcdListCount
Count + = 1
2019-06-11 10:40:54 -07:00
PcdList = list ( Package . Pcds . values ( ) )
PcdList . sort ( key = lambda x : " %s . %s " % ( x . TokenSpaceGuidCName , x . TokenCName ) )
2018-09-13 16:11:07 -07:00
Count = 0
while ( Count < len ( PcdList ) - 1 ) :
Item = PcdList [ Count ]
ItemNext = PcdList [ Count + 1 ]
#
# Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
#
if ( Item . TokenSpaceGuidCName == ItemNext . TokenSpaceGuidCName ) and ( Item . TokenCName == ItemNext . TokenCName ) and ( int ( Item . TokenValue , 0 ) != int ( ItemNext . TokenValue , 0 ) ) :
EdkLogger . error (
' build ' ,
FORMAT_INVALID ,
" The TokenValue [ %s ] of PCD [ %s . %s ] in %s defined in two places should be same as well. " \
% ( Item . TokenValue , Item . TokenSpaceGuidCName , Item . TokenCName , Package ) ,
ExtraData = None
)
Count + = 1
## Generate fds command
2019-06-11 10:40:54 -07:00
@property
def GenFdsCommand ( self ) :
2018-09-13 16:11:07 -07:00
return ( GenMake . TopLevelMakefile ( self ) . _TEMPLATE_ . Replace ( GenMake . TopLevelMakefile ( self ) . _TemplateDict ) ) . strip ( )
2019-06-11 10:40:54 -07:00
@property
def GenFdsCommandDict ( self ) :
FdsCommandDict = { }
LogLevel = EdkLogger . GetLevel ( )
if LogLevel == EdkLogger . VERBOSE :
FdsCommandDict [ " verbose " ] = True
elif LogLevel < = EdkLogger . DEBUG_9 :
FdsCommandDict [ " debug " ] = LogLevel - 1
elif LogLevel == EdkLogger . QUIET :
FdsCommandDict [ " quiet " ] = True
if GlobalData . gEnableGenfdsMultiThread :
FdsCommandDict [ " GenfdsMultiThread " ] = True
if GlobalData . gIgnoreSource :
FdsCommandDict [ " IgnoreSources " ] = True
FdsCommandDict [ " OptionPcd " ] = [ ]
for pcd in GlobalData . BuildOptionPcd :
if pcd [ 2 ] :
pcdname = ' . ' . join ( pcd [ 0 : 3 ] )
else :
pcdname = ' . ' . join ( pcd [ 0 : 2 ] )
if pcd [ 3 ] . startswith ( ' { ' ) :
FdsCommandDict [ " OptionPcd " ] . append ( pcdname + ' = ' + ' H ' + ' " ' + pcd [ 3 ] + ' " ' )
else :
FdsCommandDict [ " OptionPcd " ] . append ( pcdname + ' = ' + pcd [ 3 ] )
MacroList = [ ]
# macros passed to GenFds
MacroDict = { }
MacroDict . update ( GlobalData . gGlobalDefines )
MacroDict . update ( GlobalData . gCommandLineDefines )
for MacroName in MacroDict :
if MacroDict [ MacroName ] != " " :
MacroList . append ( ' " %s = %s " ' % ( MacroName , MacroDict [ MacroName ] . replace ( ' \\ ' , ' \\ \\ ' ) ) )
else :
MacroList . append ( ' " %s " ' % MacroName )
FdsCommandDict [ " macro " ] = MacroList
FdsCommandDict [ " fdf_file " ] = [ self . FdfFile ]
FdsCommandDict [ " build_target " ] = self . BuildTarget
FdsCommandDict [ " toolchain_tag " ] = self . ToolChain
FdsCommandDict [ " active_platform " ] = str ( self )
FdsCommandDict [ " conf_directory " ] = GlobalData . gConfDirectory
FdsCommandDict [ " build_architecture_list " ] = ' , ' . join ( self . ArchList )
FdsCommandDict [ " platform_build_directory " ] = self . BuildDir
FdsCommandDict [ " fd " ] = self . FdTargetList
FdsCommandDict [ " fv " ] = self . FvTargetList
FdsCommandDict [ " cap " ] = self . CapTargetList
return FdsCommandDict
2018-09-13 16:11:07 -07:00
## Create makefile for the platform and modules in it
#
# @param CreateDepsMakeFile Flag indicating if the makefile for
# modules will be created as well
#
def CreateMakeFile ( self , CreateDepsMakeFile = False ) :
2019-06-11 10:40:54 -07:00
if not CreateDepsMakeFile :
return
for Pa in self . AutoGenObjectList :
Pa . CreateMakeFile ( True )
2018-09-13 16:11:07 -07:00
## Create autogen code for platform and modules
#
# Since there's no autogen code for platform, this method will do nothing
# if CreateModuleCodeFile is set to False.
#
# @param CreateDepsCodeFile Flag indicating if creating module's
# autogen code file or not
#
def CreateCodeFile ( self , CreateDepsCodeFile = False ) :
if not CreateDepsCodeFile :
return
for Pa in self . AutoGenObjectList :
2019-06-11 10:40:54 -07:00
Pa . CreateCodeFile ( True )
2018-09-13 16:11:07 -07:00
## Create AsBuilt INF file the platform
#
def CreateAsBuiltInf ( self ) :
return
## AutoGen class for platform
#
# PlatformAutoGen class will process the original information in platform
# file in order to generate makefile for platform.
#
class PlatformAutoGen ( AutoGen ) :
2019-06-11 10:40:54 -07:00
# call super().__init__ then call the worker function with different parameter count
def __init__ ( self , Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs ) :
if not hasattr ( self , " _Init " ) :
self . _InitWorker ( Workspace , MetaFile , Target , Toolchain , Arch )
self . _Init = True
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
# Used to store all PCDs for both PEI and DXE phase, in order to generate
2018-09-13 16:11:07 -07:00
# correct PCD database
2019-06-11 10:40:54 -07:00
#
2018-09-13 16:11:07 -07:00
_DynaPcdList_ = [ ]
_NonDynaPcdList_ = [ ]
_PlatformPcds = { }
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
# The priority list while override build option
2018-09-13 16:11:07 -07:00
#
PrioList = { " 0x11111 " : 16 , # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
" 0x01111 " : 15 , # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
" 0x10111 " : 14 , # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
2019-06-11 10:40:54 -07:00
" 0x00111 " : 13 , # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
2018-09-13 16:11:07 -07:00
" 0x11011 " : 12 , # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
" 0x01011 " : 11 , # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
" 0x10011 " : 10 , # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
" 0x00011 " : 9 , # ******_*********_****_COMMANDTYPE_ATTRIBUTE
" 0x11101 " : 8 , # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
" 0x01101 " : 7 , # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
" 0x10101 " : 6 , # TARGET_*********_ARCH_***********_ATTRIBUTE
" 0x00101 " : 5 , # ******_*********_ARCH_***********_ATTRIBUTE
" 0x11001 " : 4 , # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
" 0x01001 " : 3 , # ******_TOOLCHAIN_****_***********_ATTRIBUTE
" 0x10001 " : 2 , # TARGET_*********_****_***********_ATTRIBUTE
" 0x00001 " : 1 } # ******_*********_****_***********_ATTRIBUTE (Lowest)
2019-06-11 10:40:54 -07:00
## Initialize PlatformAutoGen
2018-09-13 16:11:07 -07:00
#
#
# @param Workspace WorkspaceAutoGen object
# @param PlatformFile Platform file (DSC file)
# @param Target Build target (DEBUG, RELEASE)
# @param Toolchain Name of tool chain
# @param Arch arch of the platform supports
#
2019-06-11 10:40:54 -07:00
def _InitWorker ( self , Workspace , PlatformFile , Target , Toolchain , Arch ) :
2018-09-13 16:11:07 -07:00
EdkLogger . debug ( EdkLogger . DEBUG_9 , " AutoGen platform [ %s ] [ %s ] " % ( PlatformFile , Arch ) )
GlobalData . gProcessingFile = " %s [ %s , %s , %s ] " % ( PlatformFile , Arch , Toolchain , Target )
self . MetaFile = PlatformFile
self . Workspace = Workspace
self . WorkspaceDir = Workspace . WorkspaceDir
self . ToolChain = Toolchain
self . BuildTarget = Target
self . Arch = Arch
self . SourceDir = PlatformFile . SubDir
self . FdTargetList = self . Workspace . FdTargetList
self . FvTargetList = self . Workspace . FvTargetList
# get the original module/package/platform objects
self . BuildDatabase = Workspace . BuildDatabase
self . DscBuildDataObj = Workspace . Platform
# flag indicating if the makefile/C-code file has been created or not
self . IsMakeFileCreated = False
self . _DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
self . _NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
self . _AsBuildInfList = [ ]
self . _AsBuildModuleList = [ ]
self . VariableInfo = None
2019-06-11 10:40:54 -07:00
if GlobalData . gFdfParser is not None :
2018-09-13 16:11:07 -07:00
self . _AsBuildInfList = GlobalData . gFdfParser . Profile . InfList
for Inf in self . _AsBuildInfList :
InfClass = PathClass ( NormPath ( Inf ) , GlobalData . gWorkspace , self . Arch )
M = self . BuildDatabase [ InfClass , self . Arch , self . BuildTarget , self . ToolChain ]
2019-06-11 10:40:54 -07:00
if not M . IsBinaryModule :
2018-09-13 16:11:07 -07:00
continue
self . _AsBuildModuleList . append ( InfClass )
# get library/modules for build
self . LibraryBuildDirectoryList = [ ]
self . ModuleBuildDirectoryList = [ ]
return True
2019-06-11 10:40:54 -07:00
@cached_class_function
2018-09-13 16:11:07 -07:00
def __repr__ ( self ) :
return " %s [ %s ] " % ( self . MetaFile , self . Arch )
## Create autogen code for platform and modules
#
# Since there's no autogen code for platform, this method will do nothing
# if CreateModuleCodeFile is set to False.
#
# @param CreateModuleCodeFile Flag indicating if creating module's
# autogen code file or not
#
2019-06-11 10:40:54 -07:00
@cached_class_function
2018-09-13 16:11:07 -07:00
def CreateCodeFile ( self , CreateModuleCodeFile = False ) :
2019-06-11 10:40:54 -07:00
# only module has code to be created, so do nothing if CreateModuleCodeFile is False
if not CreateModuleCodeFile :
2018-09-13 16:11:07 -07:00
return
for Ma in self . ModuleAutoGenList :
Ma . CreateCodeFile ( True )
## Generate Fds Command
2019-06-11 10:40:54 -07:00
@cached_property
def GenFdsCommand ( self ) :
2018-09-13 16:11:07 -07:00
return self . Workspace . GenFdsCommand
2019-06-11 10:40:54 -07:00
## Create makefile for the platform and modules in it
2018-09-13 16:11:07 -07:00
#
# @param CreateModuleMakeFile Flag indicating if the makefile for
# modules will be created as well
#
def CreateMakeFile ( self , CreateModuleMakeFile = False , FfsCommand = { } ) :
if CreateModuleMakeFile :
2019-06-11 10:40:54 -07:00
for Ma in self . _MaList :
key = ( Ma . MetaFile . File , self . Arch )
if key in FfsCommand :
Ma . CreateMakeFile ( True , FfsCommand [ key ] )
2018-09-13 16:11:07 -07:00
else :
Ma . CreateMakeFile ( True )
# no need to create makefile for the platform more than once
if self . IsMakeFileCreated :
return
# create library/module build dirs for platform
Makefile = GenMake . PlatformMakefile ( self )
self . LibraryBuildDirectoryList = Makefile . GetLibraryBuildDirectoryList ( )
self . ModuleBuildDirectoryList = Makefile . GetModuleBuildDirectoryList ( )
self . IsMakeFileCreated = True
2019-06-11 10:40:54 -07:00
@property
def AllPcdList ( self ) :
return self . DynamicPcdList + self . NonDynamicPcdList
2018-09-13 16:11:07 -07:00
## Deal with Shared FixedAtBuild Pcds
#
def CollectFixedAtBuildPcds ( self ) :
for LibAuto in self . LibraryAutoGenList :
2019-06-11 10:40:54 -07:00
FixedAtBuildPcds = { }
ShareFixedAtBuildPcdsSameValue = { }
for Module in LibAuto . ReferenceModules :
for Pcd in set ( Module . FixedAtBuildPcds + LibAuto . FixedAtBuildPcds ) :
DefaultValue = Pcd . DefaultValue
# Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
if Pcd in Module . LibraryPcdList :
Index = Module . LibraryPcdList . index ( Pcd )
DefaultValue = Module . LibraryPcdList [ Index ] . DefaultValue
key = " . " . join ( ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
2018-09-13 16:11:07 -07:00
if key not in FixedAtBuildPcds :
ShareFixedAtBuildPcdsSameValue [ key ] = True
2019-06-11 10:40:54 -07:00
FixedAtBuildPcds [ key ] = DefaultValue
2018-09-13 16:11:07 -07:00
else :
2019-06-11 10:40:54 -07:00
if FixedAtBuildPcds [ key ] != DefaultValue :
ShareFixedAtBuildPcdsSameValue [ key ] = False
2018-09-13 16:11:07 -07:00
for Pcd in LibAuto . FixedAtBuildPcds :
2019-06-11 10:40:54 -07:00
key = " . " . join ( ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
if ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) not in self . NonDynamicPcdDict :
2018-09-13 16:11:07 -07:00
continue
else :
2019-06-11 10:40:54 -07:00
DscPcd = self . NonDynamicPcdDict [ ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) ]
if DscPcd . Type != TAB_PCDS_FIXED_AT_BUILD :
2018-09-13 16:11:07 -07:00
continue
2019-06-11 10:40:54 -07:00
if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue [ key ] :
LibAuto . ConstPcd [ key ] = FixedAtBuildPcds [ key ]
2018-09-13 16:11:07 -07:00
def CollectVariables ( self , DynamicPcdSet ) :
VpdRegionSize = 0
VpdRegionBase = 0
if self . Workspace . FdfFile :
FdDict = self . Workspace . FdfProfile . FdDict [ GlobalData . gFdfParser . CurrentFdName ]
for FdRegion in FdDict . RegionList :
for item in FdRegion . RegionDataList :
if self . Platform . VpdToolGuid . strip ( ) and self . Platform . VpdToolGuid in item :
VpdRegionSize = FdRegion . Size
VpdRegionBase = FdRegion . Offset
break
2019-06-11 10:40:54 -07:00
VariableInfo = VariableMgr ( self . DscBuildDataObj . _GetDefaultStores ( ) , self . DscBuildDataObj . SkuIds )
2018-09-13 16:11:07 -07:00
VariableInfo . SetVpdRegionMaxSize ( VpdRegionSize )
VariableInfo . SetVpdRegionOffset ( VpdRegionBase )
Index = 0
for Pcd in DynamicPcdSet :
2019-06-11 10:40:54 -07:00
pcdname = " . " . join ( ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
2018-09-13 16:11:07 -07:00
for SkuName in Pcd . SkuInfoList :
Sku = Pcd . SkuInfoList [ SkuName ]
SkuId = Sku . SkuId
2019-06-11 10:40:54 -07:00
if SkuId is None or SkuId == ' ' :
2018-09-13 16:11:07 -07:00
continue
if len ( Sku . VariableName ) > 0 :
2019-06-11 10:40:54 -07:00
if Sku . VariableAttribute and ' NV ' not in Sku . VariableAttribute :
continue
2018-09-13 16:11:07 -07:00
VariableGuidStructure = Sku . VariableGuidValue
VariableGuid = GuidStructureStringToGuidString ( VariableGuidStructure )
for StorageName in Sku . DefaultStoreDict :
2019-06-11 10:40:54 -07:00
VariableInfo . append_variable ( var_info ( Index , pcdname , StorageName , SkuName , StringToArray ( Sku . VariableName ) , VariableGuid , Sku . VariableOffset , Sku . VariableAttribute , Sku . HiiDefaultValue , Sku . DefaultStoreDict [ StorageName ] if Pcd . DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray ( Sku . DefaultStoreDict [ StorageName ] ) , Pcd . DatumType , Pcd . CustomAttribute [ ' DscPosition ' ] , Pcd . CustomAttribute . get ( ' IsStru ' , False ) ) )
2018-09-13 16:11:07 -07:00
Index + = 1
return VariableInfo
2019-06-11 10:40:54 -07:00
def UpdateNVStoreMaxSize ( self , OrgVpdFile ) :
2018-09-13 16:11:07 -07:00
if self . VariableInfo :
2019-06-11 10:40:54 -07:00
VpdMapFilePath = os . path . join ( self . BuildDir , TAB_FV_DIRECTORY , " %s .map " % self . Platform . VpdToolGuid )
2018-09-13 16:11:07 -07:00
PcdNvStoreDfBuffer = [ item for item in self . _DynamicPcdList if item . TokenCName == " PcdNvStoreDefaultValueBuffer " and item . TokenSpaceGuidCName == " gEfiMdeModulePkgTokenSpaceGuid " ]
if PcdNvStoreDfBuffer :
if os . path . exists ( VpdMapFilePath ) :
OrgVpdFile . Read ( VpdMapFilePath )
PcdItems = OrgVpdFile . GetOffset ( PcdNvStoreDfBuffer [ 0 ] )
2019-06-11 10:40:54 -07:00
NvStoreOffset = list ( PcdItems . values ( ) ) [ 0 ] . strip ( ) if PcdItems else ' 0 '
2018-09-13 16:11:07 -07:00
else :
EdkLogger . error ( " build " , FILE_READ_FAILURE , " Can not find VPD map file %s to fix up VPD offset. " % VpdMapFilePath )
2019-06-11 10:40:54 -07:00
NvStoreOffset = int ( NvStoreOffset , 16 ) if NvStoreOffset . upper ( ) . startswith ( " 0X " ) else int ( NvStoreOffset )
default_skuobj = PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . get ( TAB_DEFAULT )
2018-09-13 16:11:07 -07:00
maxsize = self . VariableInfo . VpdRegionSize - NvStoreOffset if self . VariableInfo . VpdRegionSize else len ( default_skuobj . DefaultValue . split ( " , " ) )
var_data = self . VariableInfo . PatchNVStoreDefaultMaxSize ( maxsize )
if var_data and default_skuobj :
default_skuobj . DefaultValue = var_data
PcdNvStoreDfBuffer [ 0 ] . DefaultValue = var_data
PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . clear ( )
2019-06-11 10:40:54 -07:00
PcdNvStoreDfBuffer [ 0 ] . SkuInfoList [ TAB_DEFAULT ] = default_skuobj
2018-09-13 16:11:07 -07:00
PcdNvStoreDfBuffer [ 0 ] . MaxDatumSize = str ( len ( default_skuobj . DefaultValue . split ( " , " ) ) )
return OrgVpdFile
## Collect dynamic PCDs
#
# Gather dynamic PCDs list from each module and their settings from platform
# This interface should be invoked explicitly when platform action is created.
#
def CollectPlatformDynamicPcds ( self ) :
for key in self . Platform . Pcds :
for SinglePcd in GlobalData . MixedPcd :
if ( self . Platform . Pcds [ key ] . TokenCName , self . Platform . Pcds [ key ] . TokenSpaceGuidCName ) == SinglePcd :
for item in GlobalData . MixedPcd [ SinglePcd ] :
Pcd_Type = item [ 0 ] . split ( ' _ ' ) [ - 1 ]
2019-06-11 10:40:54 -07:00
if ( Pcd_Type == self . Platform . Pcds [ key ] . Type ) or ( Pcd_Type == TAB_PCDS_DYNAMIC_EX and self . Platform . Pcds [ key ] . Type in PCD_DYNAMIC_EX_TYPE_SET ) or \
( Pcd_Type == TAB_PCDS_DYNAMIC and self . Platform . Pcds [ key ] . Type in PCD_DYNAMIC_TYPE_SET ) :
2018-09-13 16:11:07 -07:00
Value = self . Platform . Pcds [ key ]
Value . TokenCName = self . Platform . Pcds [ key ] . TokenCName + ' _ ' + Pcd_Type
if len ( key ) == 2 :
newkey = ( Value . TokenCName , key [ 1 ] )
elif len ( key ) == 3 :
newkey = ( Value . TokenCName , key [ 1 ] , key [ 2 ] )
del self . Platform . Pcds [ key ]
self . Platform . Pcds [ newkey ] = Value
break
break
# for gathering error information
NoDatumTypePcdList = set ( )
FdfModuleList = [ ]
for InfName in self . _AsBuildInfList :
InfName = mws . join ( self . WorkspaceDir , InfName )
FdfModuleList . append ( os . path . normpath ( InfName ) )
2019-06-11 10:40:54 -07:00
for M in self . _MaList :
# F is the Module for which M is the module autogen
2018-09-13 16:11:07 -07:00
for PcdFromModule in M . ModulePcdList + M . LibraryPcdList :
# make sure that the "VOID*" kind of datum has MaxDatumSize set
2019-06-11 10:40:54 -07:00
if PcdFromModule . DatumType == TAB_VOID and not PcdFromModule . MaxDatumSize :
NoDatumTypePcdList . add ( " %s . %s [ %s ] " % ( PcdFromModule . TokenSpaceGuidCName , PcdFromModule . TokenCName , M . MetaFile ) )
2018-09-13 16:11:07 -07:00
# Check the PCD from Binary INF or Source INF
if M . IsBinaryModule == True :
PcdFromModule . IsFromBinaryInf = True
2019-06-11 10:40:54 -07:00
# Check the PCD from DSC or not
PcdFromModule . IsFromDsc = ( PcdFromModule . TokenCName , PcdFromModule . TokenSpaceGuidCName ) in self . Platform . Pcds
if PcdFromModule . Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
if M . MetaFile . Path not in FdfModuleList :
# If one of the Source built modules listed in the DSC is not listed
# in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
# access method (it is only listed in the DEC file that declares the
2018-09-13 16:11:07 -07:00
# PCD as PcdsDynamic), then build tool will report warning message
2019-06-11 10:40:54 -07:00
# notify the PI that they are attempting to build a module that must
# be included in a flash image in order to be functional. These Dynamic
# PCD will not be added into the Database unless it is used by other
2018-09-13 16:11:07 -07:00
# modules that are included in the FDF file.
2019-06-11 10:40:54 -07:00
if PcdFromModule . Type in PCD_DYNAMIC_TYPE_SET and \
2018-09-13 16:11:07 -07:00
PcdFromModule . IsFromBinaryInf == False :
# Print warning message to let the developer make a determine.
continue
2019-06-11 10:40:54 -07:00
# If one of the Source built modules listed in the DSC is not listed in
# FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
# access method (it is only listed in the DEC file that declares the
# PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
2018-09-13 16:11:07 -07:00
# PCD to the Platform's PCD Database.
2019-06-11 10:40:54 -07:00
if PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
2018-09-13 16:11:07 -07:00
continue
#
# If a dynamic PCD used by a PEM module/PEI module & DXE module,
# it should be stored in Pcd PEI database, If a dynamic only
# used by DXE module, it should be stored in DXE PCD database.
# The default Phase is DXE
#
2019-06-11 10:40:54 -07:00
if M . ModuleType in SUP_MODULE_SET_PEI :
2018-09-13 16:11:07 -07:00
PcdFromModule . Phase = " PEI "
if PcdFromModule not in self . _DynaPcdList_ :
self . _DynaPcdList_ . append ( PcdFromModule )
elif PcdFromModule . Phase == ' PEI ' :
# overwrite any the same PCD existing, if Phase is PEI
Index = self . _DynaPcdList_ . index ( PcdFromModule )
self . _DynaPcdList_ [ Index ] = PcdFromModule
elif PcdFromModule not in self . _NonDynaPcdList_ :
self . _NonDynaPcdList_ . append ( PcdFromModule )
elif PcdFromModule in self . _NonDynaPcdList_ and PcdFromModule . IsFromBinaryInf == True :
Index = self . _NonDynaPcdList_ . index ( PcdFromModule )
if self . _NonDynaPcdList_ [ Index ] . IsFromBinaryInf == False :
#The PCD from Binary INF will override the same one from source INF
self . _NonDynaPcdList_ . remove ( self . _NonDynaPcdList_ [ Index ] )
PcdFromModule . Pending = False
self . _NonDynaPcdList_ . append ( PcdFromModule )
2019-06-11 10:40:54 -07:00
DscModuleSet = { os . path . normpath ( ModuleInf . Path ) for ModuleInf in self . Platform . Modules }
# add the PCD from modules that listed in FDF but not in DSC to Database
2018-09-13 16:11:07 -07:00
for InfName in FdfModuleList :
2019-06-11 10:40:54 -07:00
if InfName not in DscModuleSet :
2018-09-13 16:11:07 -07:00
InfClass = PathClass ( InfName )
M = self . BuildDatabase [ InfClass , self . Arch , self . BuildTarget , self . ToolChain ]
2019-06-11 10:40:54 -07:00
# If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
# for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
# For binary module, if in current arch, we need to list the PCDs into database.
if not M . IsBinaryModule :
2018-09-13 16:11:07 -07:00
continue
# Override the module PCD setting by platform setting
ModulePcdList = self . ApplyPcdSetting ( M , M . Pcds )
for PcdFromModule in ModulePcdList :
PcdFromModule . IsFromBinaryInf = True
PcdFromModule . IsFromDsc = False
# Only allow the DynamicEx and Patchable PCD in AsBuild INF
2019-06-11 10:40:54 -07:00
if PcdFromModule . Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule . Type not in TAB_PCDS_PATCHABLE_IN_MODULE :
2018-09-13 16:11:07 -07:00
EdkLogger . error ( " build " , AUTOGEN_ERROR , " PCD setting error " ,
File = self . MetaFile ,
ExtraData = " \n \t Existed %s PCD %s in: \n \t \t %s \n "
% ( PcdFromModule . Type , PcdFromModule . TokenCName , InfName ) )
# make sure that the "VOID*" kind of datum has MaxDatumSize set
2019-06-11 10:40:54 -07:00
if PcdFromModule . DatumType == TAB_VOID and not PcdFromModule . MaxDatumSize :
2018-09-13 16:11:07 -07:00
NoDatumTypePcdList . add ( " %s . %s [ %s ] " % ( PcdFromModule . TokenSpaceGuidCName , PcdFromModule . TokenCName , InfName ) )
2019-06-11 10:40:54 -07:00
if M . ModuleType in SUP_MODULE_SET_PEI :
2018-09-13 16:11:07 -07:00
PcdFromModule . Phase = " PEI "
2019-06-11 10:40:54 -07:00
if PcdFromModule not in self . _DynaPcdList_ and PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
2018-09-13 16:11:07 -07:00
self . _DynaPcdList_ . append ( PcdFromModule )
elif PcdFromModule not in self . _NonDynaPcdList_ and PcdFromModule . Type in TAB_PCDS_PATCHABLE_IN_MODULE :
self . _NonDynaPcdList_ . append ( PcdFromModule )
2019-06-11 10:40:54 -07:00
if PcdFromModule in self . _DynaPcdList_ and PcdFromModule . Phase == ' PEI ' and PcdFromModule . Type in PCD_DYNAMIC_EX_TYPE_SET :
2018-09-13 16:11:07 -07:00
# Overwrite the phase of any the same PCD existing, if Phase is PEI.
2019-06-11 10:40:54 -07:00
# It is to solve the case that a dynamic PCD used by a PEM module/PEI
2018-09-13 16:11:07 -07:00
# module & DXE module at a same time.
# Overwrite the type of the PCDs in source INF by the type of AsBuild
2019-06-11 10:40:54 -07:00
# INF file as DynamicEx.
2018-09-13 16:11:07 -07:00
Index = self . _DynaPcdList_ . index ( PcdFromModule )
self . _DynaPcdList_ [ Index ] . Phase = PcdFromModule . Phase
self . _DynaPcdList_ [ Index ] . Type = PcdFromModule . Type
for PcdFromModule in self . _NonDynaPcdList_ :
2019-06-11 10:40:54 -07:00
# If a PCD is not listed in the DSC file, but binary INF files used by
# this platform all (that use this PCD) list the PCD in a [PatchPcds]
# section, AND all source INF files used by this platform the build
# that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
2018-09-13 16:11:07 -07:00
# section, then the tools must NOT add the PCD to the Platform's PCD
2019-06-11 10:40:54 -07:00
# Database; the build must assign the access method for this PCD as
2018-09-13 16:11:07 -07:00
# PcdsPatchableInModule.
if PcdFromModule not in self . _DynaPcdList_ :
continue
Index = self . _DynaPcdList_ . index ( PcdFromModule )
if PcdFromModule . IsFromDsc == False and \
PcdFromModule . Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
PcdFromModule . IsFromBinaryInf == True and \
self . _DynaPcdList_ [ Index ] . IsFromBinaryInf == False :
Index = self . _DynaPcdList_ . index ( PcdFromModule )
self . _DynaPcdList_ . remove ( self . _DynaPcdList_ [ Index ] )
# print out error information and break the build, if error found
if len ( NoDatumTypePcdList ) > 0 :
NoDatumTypePcdListString = " \n \t \t " . join ( NoDatumTypePcdList )
EdkLogger . error ( " build " , AUTOGEN_ERROR , " PCD setting error " ,
File = self . MetaFile ,
ExtraData = " \n \t PCD(s) without MaxDatumSize: \n \t \t %s \n "
% NoDatumTypePcdListString )
self . _NonDynamicPcdList = self . _NonDynaPcdList_
self . _DynamicPcdList = self . _DynaPcdList_
#
# Sort dynamic PCD list to:
2019-06-11 10:40:54 -07:00
# 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
2018-09-13 16:11:07 -07:00
# try to be put header of dynamicd List
# 2) If PCD is HII type, the PCD item should be put after unicode type PCD
#
# The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
#
UnicodePcdArray = set ( )
HiiPcdArray = set ( )
OtherPcdArray = set ( )
VpdPcdDict = { }
VpdFile = VpdInfoFile . VpdInfoFile ( )
NeedProcessVpdMapFile = False
2019-06-11 10:40:54 -07:00
for pcd in self . Platform . Pcds :
if pcd not in self . _PlatformPcds :
2018-09-13 16:11:07 -07:00
self . _PlatformPcds [ pcd ] = self . Platform . Pcds [ pcd ]
for item in self . _PlatformPcds :
if self . _PlatformPcds [ item ] . DatumType and self . _PlatformPcds [ item ] . DatumType not in [ TAB_UINT8 , TAB_UINT16 , TAB_UINT32 , TAB_UINT64 , TAB_VOID , " BOOLEAN " ] :
2019-06-11 10:40:54 -07:00
self . _PlatformPcds [ item ] . DatumType = TAB_VOID
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
if ( self . Workspace . ArchList [ - 1 ] == self . Arch ) :
2018-09-13 16:11:07 -07:00
for Pcd in self . _DynamicPcdList :
# just pick the a value to determine whether is unicode string type
2019-06-11 10:40:54 -07:00
Sku = Pcd . SkuInfoList . get ( TAB_DEFAULT )
2018-09-13 16:11:07 -07:00
Sku . VpdOffset = Sku . VpdOffset . strip ( )
if Pcd . DatumType not in [ TAB_UINT8 , TAB_UINT16 , TAB_UINT32 , TAB_UINT64 , TAB_VOID , " BOOLEAN " ] :
2019-06-11 10:40:54 -07:00
Pcd . DatumType = TAB_VOID
2018-09-13 16:11:07 -07:00
# if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
# if found HII type PCD then insert to right of UnicodeIndex
if Pcd . Type in [ TAB_PCDS_DYNAMIC_VPD , TAB_PCDS_DYNAMIC_EX_VPD ] :
VpdPcdDict [ ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) ] = Pcd
#Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
2019-06-11 10:40:54 -07:00
PcdNvStoreDfBuffer = VpdPcdDict . get ( ( " PcdNvStoreDefaultValueBuffer " , " gEfiMdeModulePkgTokenSpaceGuid " ) )
2018-09-13 16:11:07 -07:00
if PcdNvStoreDfBuffer :
self . VariableInfo = self . CollectVariables ( self . _DynamicPcdList )
vardump = self . VariableInfo . dump ( )
if vardump :
2019-06-11 10:40:54 -07:00
#
#According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
#the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
#typedef UINT16 SIZE_INFO;
#//SIZE_INFO SizeTable[];
if len ( vardump . split ( " , " ) ) > 0xffff :
EdkLogger . error ( " build " , RESOURCE_OVERFLOW , ' The current length of PCD %s value is %d , it exceeds to the max size of String PCD. ' % ( " . " . join ( [ PcdNvStoreDfBuffer . TokenSpaceGuidCName , PcdNvStoreDfBuffer . TokenCName ] ) , len ( vardump . split ( " , " ) ) ) )
2018-09-13 16:11:07 -07:00
PcdNvStoreDfBuffer . DefaultValue = vardump
for skuname in PcdNvStoreDfBuffer . SkuInfoList :
PcdNvStoreDfBuffer . SkuInfoList [ skuname ] . DefaultValue = vardump
PcdNvStoreDfBuffer . MaxDatumSize = str ( len ( vardump . split ( " , " ) ) )
2019-06-11 10:40:54 -07:00
else :
#If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
if [ Pcd for Pcd in self . _DynamicPcdList if Pcd . UserDefinedDefaultStoresFlag ] :
EdkLogger . warn ( " build " , " PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform. \n %s " % self . Platform . MetaFile . Path )
PlatformPcds = sorted ( self . _PlatformPcds . keys ( ) )
2018-09-13 16:11:07 -07:00
#
# Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
#
VpdSkuMap = { }
for PcdKey in PlatformPcds :
Pcd = self . _PlatformPcds [ PcdKey ]
if Pcd . Type in [ TAB_PCDS_DYNAMIC_VPD , TAB_PCDS_DYNAMIC_EX_VPD ] and \
PcdKey in VpdPcdDict :
Pcd = VpdPcdDict [ PcdKey ]
SkuValueMap = { }
2019-06-11 10:40:54 -07:00
DefaultSku = Pcd . SkuInfoList . get ( TAB_DEFAULT )
2018-09-13 16:11:07 -07:00
if DefaultSku :
PcdValue = DefaultSku . DefaultValue
if PcdValue not in SkuValueMap :
SkuValueMap [ PcdValue ] = [ ]
2019-06-11 10:40:54 -07:00
VpdFile . Add ( Pcd , TAB_DEFAULT , DefaultSku . VpdOffset )
2018-09-13 16:11:07 -07:00
SkuValueMap [ PcdValue ] . append ( DefaultSku )
2019-06-11 10:40:54 -07:00
for ( SkuName , Sku ) in Pcd . SkuInfoList . items ( ) :
2018-09-13 16:11:07 -07:00
Sku . VpdOffset = Sku . VpdOffset . strip ( )
PcdValue = Sku . DefaultValue
if PcdValue == " " :
PcdValue = Pcd . DefaultValue
2019-06-11 10:40:54 -07:00
if Sku . VpdOffset != TAB_STAR :
2018-09-13 16:11:07 -07:00
if PcdValue . startswith ( " { " ) :
Alignment = 8
elif PcdValue . startswith ( " L " ) :
Alignment = 2
else :
Alignment = 1
try :
VpdOffset = int ( Sku . VpdOffset )
except :
try :
VpdOffset = int ( Sku . VpdOffset , 16 )
except :
EdkLogger . error ( " build " , FORMAT_INVALID , " Invalid offset value %s for PCD %s . %s . " % ( Sku . VpdOffset , Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) )
if VpdOffset % Alignment != 0 :
if PcdValue . startswith ( " { " ) :
EdkLogger . warn ( " build " , " The offset value of PCD %s . %s is not 8-byte aligned! " % ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) , File = self . MetaFile )
else :
EdkLogger . error ( " build " , FORMAT_INVALID , ' The offset value of PCD %s . %s should be %s -byte aligned. ' % ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName , Alignment ) )
if PcdValue not in SkuValueMap :
SkuValueMap [ PcdValue ] = [ ]
2019-06-11 10:40:54 -07:00
VpdFile . Add ( Pcd , SkuName , Sku . VpdOffset )
2018-09-13 16:11:07 -07:00
SkuValueMap [ PcdValue ] . append ( Sku )
# if the offset of a VPD is *, then it need to be fixed up by third party tool.
2019-06-11 10:40:54 -07:00
if not NeedProcessVpdMapFile and Sku . VpdOffset == TAB_STAR :
2018-09-13 16:11:07 -07:00
NeedProcessVpdMapFile = True
2019-06-11 10:40:54 -07:00
if self . Platform . VpdToolGuid is None or self . Platform . VpdToolGuid == ' ' :
2018-09-13 16:11:07 -07:00
EdkLogger . error ( " Build " , FILE_NOT_FOUND , \
" Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file. " )
VpdSkuMap [ PcdKey ] = SkuValueMap
#
# Fix the PCDs define in VPD PCD section that never referenced by module.
# An example is PCD for signature usage.
2019-06-11 10:40:54 -07:00
#
2018-09-13 16:11:07 -07:00
for DscPcd in PlatformPcds :
DscPcdEntry = self . _PlatformPcds [ DscPcd ]
if DscPcdEntry . Type in [ TAB_PCDS_DYNAMIC_VPD , TAB_PCDS_DYNAMIC_EX_VPD ] :
2019-06-11 10:40:54 -07:00
if not ( self . Platform . VpdToolGuid is None or self . Platform . VpdToolGuid == ' ' ) :
2018-09-13 16:11:07 -07:00
FoundFlag = False
2019-06-11 10:40:54 -07:00
for VpdPcd in VpdFile . _VpdArray :
2018-09-13 16:11:07 -07:00
# This PCD has been referenced by module
if ( VpdPcd . TokenSpaceGuidCName == DscPcdEntry . TokenSpaceGuidCName ) and \
( VpdPcd . TokenCName == DscPcdEntry . TokenCName ) :
FoundFlag = True
# Not found, it should be signature
if not FoundFlag :
# just pick the a value to determine whether is unicode string type
SkuValueMap = { }
2019-06-11 10:40:54 -07:00
SkuObjList = list ( DscPcdEntry . SkuInfoList . items ( ) )
DefaultSku = DscPcdEntry . SkuInfoList . get ( TAB_DEFAULT )
2018-09-13 16:11:07 -07:00
if DefaultSku :
2019-06-11 10:40:54 -07:00
defaultindex = SkuObjList . index ( ( TAB_DEFAULT , DefaultSku ) )
SkuObjList [ 0 ] , SkuObjList [ defaultindex ] = SkuObjList [ defaultindex ] , SkuObjList [ 0 ]
for ( SkuName , Sku ) in SkuObjList :
Sku . VpdOffset = Sku . VpdOffset . strip ( )
2018-09-13 16:11:07 -07:00
# Need to iterate DEC pcd information to get the value & datumtype
for eachDec in self . PackageList :
for DecPcd in eachDec . Pcds :
DecPcdEntry = eachDec . Pcds [ DecPcd ]
if ( DecPcdEntry . TokenSpaceGuidCName == DscPcdEntry . TokenSpaceGuidCName ) and \
( DecPcdEntry . TokenCName == DscPcdEntry . TokenCName ) :
# Print warning message to let the developer make a determine.
EdkLogger . warn ( " build " , " Unreferenced vpd pcd used! " ,
File = self . MetaFile , \
ExtraData = " PCD: %s . %s used in the DSC file %s is unreferenced. " \
2019-06-11 10:40:54 -07:00
% ( DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName , self . Platform . MetaFile . Path ) )
2018-09-13 16:11:07 -07:00
DscPcdEntry . DatumType = DecPcdEntry . DatumType
DscPcdEntry . DefaultValue = DecPcdEntry . DefaultValue
DscPcdEntry . TokenValue = DecPcdEntry . TokenValue
DscPcdEntry . TokenSpaceGuidValue = eachDec . Guids [ DecPcdEntry . TokenSpaceGuidCName ]
# Only fix the value while no value provided in DSC file.
2019-06-11 10:40:54 -07:00
if not Sku . DefaultValue :
DscPcdEntry . SkuInfoList [ list ( DscPcdEntry . SkuInfoList . keys ( ) ) [ 0 ] ] . DefaultValue = DecPcdEntry . DefaultValue
2018-09-13 16:11:07 -07:00
if DscPcdEntry not in self . _DynamicPcdList :
self . _DynamicPcdList . append ( DscPcdEntry )
Sku . VpdOffset = Sku . VpdOffset . strip ( )
PcdValue = Sku . DefaultValue
if PcdValue == " " :
PcdValue = DscPcdEntry . DefaultValue
2019-06-11 10:40:54 -07:00
if Sku . VpdOffset != TAB_STAR :
2018-09-13 16:11:07 -07:00
if PcdValue . startswith ( " { " ) :
Alignment = 8
elif PcdValue . startswith ( " L " ) :
Alignment = 2
else :
Alignment = 1
try :
VpdOffset = int ( Sku . VpdOffset )
except :
try :
VpdOffset = int ( Sku . VpdOffset , 16 )
except :
EdkLogger . error ( " build " , FORMAT_INVALID , " Invalid offset value %s for PCD %s . %s . " % ( Sku . VpdOffset , DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName ) )
if VpdOffset % Alignment != 0 :
if PcdValue . startswith ( " { " ) :
EdkLogger . warn ( " build " , " The offset value of PCD %s . %s is not 8-byte aligned! " % ( DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName ) , File = self . MetaFile )
else :
EdkLogger . error ( " build " , FORMAT_INVALID , ' The offset value of PCD %s . %s should be %s -byte aligned. ' % ( DscPcdEntry . TokenSpaceGuidCName , DscPcdEntry . TokenCName , Alignment ) )
if PcdValue not in SkuValueMap :
SkuValueMap [ PcdValue ] = [ ]
2019-06-11 10:40:54 -07:00
VpdFile . Add ( DscPcdEntry , SkuName , Sku . VpdOffset )
2018-09-13 16:11:07 -07:00
SkuValueMap [ PcdValue ] . append ( Sku )
2019-06-11 10:40:54 -07:00
if not NeedProcessVpdMapFile and Sku . VpdOffset == TAB_STAR :
NeedProcessVpdMapFile = True
if DscPcdEntry . DatumType == TAB_VOID and PcdValue . startswith ( " L " ) :
2018-09-13 16:11:07 -07:00
UnicodePcdArray . add ( DscPcdEntry )
elif len ( Sku . VariableName ) > 0 :
HiiPcdArray . add ( DscPcdEntry )
else :
OtherPcdArray . add ( DscPcdEntry )
# if the offset of a VPD is *, then it need to be fixed up by third party tool.
VpdSkuMap [ DscPcd ] = SkuValueMap
2019-06-11 10:40:54 -07:00
if ( self . Platform . FlashDefinition is None or self . Platform . FlashDefinition == ' ' ) and \
2018-09-13 16:11:07 -07:00
VpdFile . GetCount ( ) != 0 :
2019-06-11 10:40:54 -07:00
EdkLogger . error ( " build " , ATTRIBUTE_NOT_AVAILABLE ,
2018-09-13 16:11:07 -07:00
" Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD. " % str ( self . Platform . MetaFile ) )
if VpdFile . GetCount ( ) != 0 :
self . FixVpdOffset ( VpdFile )
self . FixVpdOffset ( self . UpdateNVStoreMaxSize ( VpdFile ) )
2019-06-11 10:40:54 -07:00
PcdNvStoreDfBuffer = [ item for item in self . _DynamicPcdList if item . TokenCName == " PcdNvStoreDefaultValueBuffer " and item . TokenSpaceGuidCName == " gEfiMdeModulePkgTokenSpaceGuid " ]
if PcdNvStoreDfBuffer :
PcdName , PcdGuid = PcdNvStoreDfBuffer [ 0 ] . TokenCName , PcdNvStoreDfBuffer [ 0 ] . TokenSpaceGuidCName
if ( PcdName , PcdGuid ) in VpdSkuMap :
DefaultSku = PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . get ( TAB_DEFAULT )
VpdSkuMap [ ( PcdName , PcdGuid ) ] = { DefaultSku . DefaultValue : [ SkuObj for SkuObj in PcdNvStoreDfBuffer [ 0 ] . SkuInfoList . values ( ) ] }
2018-09-13 16:11:07 -07:00
# Process VPD map file generated by third party BPDG tool
if NeedProcessVpdMapFile :
2019-06-11 10:40:54 -07:00
VpdMapFilePath = os . path . join ( self . BuildDir , TAB_FV_DIRECTORY , " %s .map " % self . Platform . VpdToolGuid )
2018-09-13 16:11:07 -07:00
if os . path . exists ( VpdMapFilePath ) :
VpdFile . Read ( VpdMapFilePath )
2019-06-11 10:40:54 -07:00
# Fixup TAB_STAR offset
2018-09-13 16:11:07 -07:00
for pcd in VpdSkuMap :
vpdinfo = VpdFile . GetVpdInfo ( pcd )
if vpdinfo is None :
# just pick the a value to determine whether is unicode string type
continue
for pcdvalue in VpdSkuMap [ pcd ] :
for sku in VpdSkuMap [ pcd ] [ pcdvalue ] :
for item in vpdinfo :
if item [ 2 ] == pcdvalue :
sku . VpdOffset = item [ 1 ]
else :
EdkLogger . error ( " build " , FILE_READ_FAILURE , " Can not find VPD map file %s to fix up VPD offset. " % VpdMapFilePath )
# Delete the DynamicPcdList At the last time enter into this function
for Pcd in self . _DynamicPcdList :
# just pick the a value to determine whether is unicode string type
2019-06-11 10:40:54 -07:00
Sku = Pcd . SkuInfoList . get ( TAB_DEFAULT )
2018-09-13 16:11:07 -07:00
Sku . VpdOffset = Sku . VpdOffset . strip ( )
if Pcd . DatumType not in [ TAB_UINT8 , TAB_UINT16 , TAB_UINT32 , TAB_UINT64 , TAB_VOID , " BOOLEAN " ] :
2019-06-11 10:40:54 -07:00
Pcd . DatumType = TAB_VOID
2018-09-13 16:11:07 -07:00
PcdValue = Sku . DefaultValue
2019-06-11 10:40:54 -07:00
if Pcd . DatumType == TAB_VOID and PcdValue . startswith ( " L " ) :
2018-09-13 16:11:07 -07:00
# if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
UnicodePcdArray . add ( Pcd )
elif len ( Sku . VariableName ) > 0 :
# if found HII type PCD then insert to right of UnicodeIndex
HiiPcdArray . add ( Pcd )
else :
OtherPcdArray . add ( Pcd )
del self . _DynamicPcdList [ : ]
self . _DynamicPcdList . extend ( list ( UnicodePcdArray ) )
self . _DynamicPcdList . extend ( list ( HiiPcdArray ) )
self . _DynamicPcdList . extend ( list ( OtherPcdArray ) )
2019-06-11 10:40:54 -07:00
allskuset = [ ( SkuName , Sku . SkuId ) for pcd in self . _DynamicPcdList for ( SkuName , Sku ) in pcd . SkuInfoList . items ( ) ]
2018-09-13 16:11:07 -07:00
for pcd in self . _DynamicPcdList :
if len ( pcd . SkuInfoList ) == 1 :
2019-06-11 10:40:54 -07:00
for ( SkuName , SkuId ) in allskuset :
if isinstance ( SkuId , str ) and eval ( SkuId ) == 0 or SkuId == 0 :
2018-09-13 16:11:07 -07:00
continue
2019-06-11 10:40:54 -07:00
pcd . SkuInfoList [ SkuName ] = copy . deepcopy ( pcd . SkuInfoList [ TAB_DEFAULT ] )
2018-09-13 16:11:07 -07:00
pcd . SkuInfoList [ SkuName ] . SkuId = SkuId
2019-06-11 10:40:54 -07:00
pcd . SkuInfoList [ SkuName ] . SkuIdName = SkuName
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
def FixVpdOffset ( self , VpdFile ) :
FvPath = os . path . join ( self . BuildDir , TAB_FV_DIRECTORY )
2018-09-13 16:11:07 -07:00
if not os . path . exists ( FvPath ) :
try :
os . makedirs ( FvPath )
except :
EdkLogger . error ( " build " , FILE_WRITE_FAILURE , " Fail to create FV folder under %s " % self . BuildDir )
VpdFilePath = os . path . join ( FvPath , " %s .txt " % self . Platform . VpdToolGuid )
if VpdFile . Write ( VpdFilePath ) :
# retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
BPDGToolName = None
for ToolDef in self . ToolDefinition . values ( ) :
2019-06-11 10:40:54 -07:00
if TAB_GUID in ToolDef and ToolDef [ TAB_GUID ] == self . Platform . VpdToolGuid :
if " PATH " not in ToolDef :
2018-09-13 16:11:07 -07:00
EdkLogger . error ( " build " , ATTRIBUTE_NOT_AVAILABLE , " PATH attribute was not provided for BPDG guid tool %s in tools_def.txt " % self . Platform . VpdToolGuid )
BPDGToolName = ToolDef [ " PATH " ]
break
# Call third party GUID BPDG tool.
2019-06-11 10:40:54 -07:00
if BPDGToolName is not None :
2018-09-13 16:11:07 -07:00
VpdInfoFile . CallExtenalBPDGTool ( BPDGToolName , VpdFilePath )
else :
EdkLogger . error ( " Build " , FILE_NOT_FOUND , " Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file. " )
## Return the platform build data object
2019-06-11 10:40:54 -07:00
@cached_property
def Platform ( self ) :
return self . BuildDatabase [ self . MetaFile , self . Arch , self . BuildTarget , self . ToolChain ]
2018-09-13 16:11:07 -07:00
## Return platform name
2019-06-11 10:40:54 -07:00
@cached_property
def Name ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . PlatformName
## Return the meta file GUID
2019-06-11 10:40:54 -07:00
@cached_property
def Guid ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . Guid
## Return the platform version
2019-06-11 10:40:54 -07:00
@cached_property
def Version ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . Version
## Return the FDF file name
2019-06-11 10:40:54 -07:00
@cached_property
def FdfFile ( self ) :
if self . Workspace . FdfFile :
RetVal = mws . join ( self . WorkspaceDir , self . Workspace . FdfFile )
else :
RetVal = ' '
return RetVal
2018-09-13 16:11:07 -07:00
## Return the build output directory platform specifies
2019-06-11 10:40:54 -07:00
@cached_property
def OutputDir ( self ) :
2018-09-13 16:11:07 -07:00
return self . Platform . OutputDirectory
## Return the directory to store all intermediate and final files built
2019-06-11 10:40:54 -07:00
@cached_property
def BuildDir ( self ) :
if os . path . isabs ( self . OutputDir ) :
GlobalData . gBuildDirectory = RetVal = path . join (
path . abspath ( self . OutputDir ) ,
self . BuildTarget + " _ " + self . ToolChain ,
)
else :
GlobalData . gBuildDirectory = RetVal = path . join (
self . WorkspaceDir ,
self . OutputDir ,
self . BuildTarget + " _ " + self . ToolChain ,
)
return RetVal
2018-09-13 16:11:07 -07:00
## Return directory of platform makefile
#
# @retval string Makefile directory
#
2019-06-11 10:40:54 -07:00
@cached_property
def MakeFileDir ( self ) :
return path . join ( self . BuildDir , self . Arch )
2018-09-13 16:11:07 -07:00
## Return build command string
#
# @retval string Build command string
#
2019-06-11 10:40:54 -07:00
@cached_property
def BuildCommand ( self ) :
RetVal = [ ]
if " MAKE " in self . ToolDefinition and " PATH " in self . ToolDefinition [ " MAKE " ] :
RetVal + = _SplitOption ( self . ToolDefinition [ " MAKE " ] [ " PATH " ] )
if " FLAGS " in self . ToolDefinition [ " MAKE " ] :
NewOption = self . ToolDefinition [ " MAKE " ] [ " FLAGS " ] . strip ( )
if NewOption != ' ' :
RetVal + = _SplitOption ( NewOption )
if " MAKE " in self . EdkIIBuildOption :
if " FLAGS " in self . EdkIIBuildOption [ " MAKE " ] :
Flags = self . EdkIIBuildOption [ " MAKE " ] [ " FLAGS " ]
if Flags . startswith ( ' = ' ) :
RetVal = [ RetVal [ 0 ] ] + [ Flags [ 1 : ] ]
else :
RetVal . append ( Flags )
return RetVal
2018-09-13 16:11:07 -07:00
## Get tool chain definition
#
2019-06-11 10:40:54 -07:00
# Get each tool definition for given tool chain from tools_def.txt and platform
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
@cached_property
def ToolDefinition ( self ) :
ToolDefinition = self . Workspace . ToolDef . ToolsDefTxtDictionary
if TAB_TOD_DEFINES_COMMAND_TYPE not in self . Workspace . ToolDef . ToolsDefTxtDatabase :
EdkLogger . error ( ' build ' , RESOURCE_NOT_AVAILABLE , " No tools found in configuration " ,
ExtraData = " [ %s ] " % self . MetaFile )
RetVal = { }
DllPathList = set ( )
for Def in ToolDefinition :
Target , Tag , Arch , Tool , Attr = Def . split ( " _ " )
if Target != self . BuildTarget or Tag != self . ToolChain or Arch != self . Arch :
continue
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
Value = ToolDefinition [ Def ]
# don't record the DLL
if Attr == " DLL " :
DllPathList . add ( Value )
continue
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
if Tool not in RetVal :
RetVal [ Tool ] = { }
RetVal [ Tool ] [ Attr ] = Value
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
ToolsDef = ' '
if GlobalData . gOptions . SilentMode and " MAKE " in RetVal :
if " FLAGS " not in RetVal [ " MAKE " ] :
RetVal [ " MAKE " ] [ " FLAGS " ] = " "
RetVal [ " MAKE " ] [ " FLAGS " ] + = " -s "
MakeFlags = ' '
for Tool in RetVal :
for Attr in RetVal [ Tool ] :
Value = RetVal [ Tool ] [ Attr ]
if Tool in self . _BuildOptionWithToolDef ( RetVal ) and Attr in self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] :
# check if override is indicated
if self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ] . startswith ( ' = ' ) :
Value = self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ] [ 1 : ]
else :
if Attr != ' PATH ' :
Value + = " " + self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ]
2018-09-13 16:11:07 -07:00
else :
2019-06-11 10:40:54 -07:00
Value = self . _BuildOptionWithToolDef ( RetVal ) [ Tool ] [ Attr ]
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
if Attr == " PATH " :
# Don't put MAKE definition in the file
if Tool != " MAKE " :
ToolsDef + = " %s = %s \n " % ( Tool , Value )
elif Attr != " DLL " :
# Don't put MAKE definition in the file
if Tool == " MAKE " :
if Attr == " FLAGS " :
MakeFlags = Value
else :
ToolsDef + = " %s _ %s = %s \n " % ( Tool , Attr , Value )
ToolsDef + = " \n "
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
SaveFileOnChange ( self . ToolDefinitionFile , ToolsDef , False )
for DllPath in DllPathList :
os . environ [ " PATH " ] = DllPath + os . pathsep + os . environ [ " PATH " ]
os . environ [ " MAKE_FLAGS " ] = MakeFlags
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
return RetVal
2018-09-13 16:11:07 -07:00
## Return the paths of tools
2019-06-11 10:40:54 -07:00
@cached_property
def ToolDefinitionFile ( self ) :
return os . path . join ( self . MakeFileDir , " TOOLS_DEF. " + self . Arch )
2018-09-13 16:11:07 -07:00
## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
2019-06-11 10:40:54 -07:00
@cached_property
def ToolChainFamily ( self ) :
ToolDefinition = self . Workspace . ToolDef . ToolsDefTxtDatabase
if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
or self . ToolChain not in ToolDefinition [ TAB_TOD_DEFINES_FAMILY ] \
or not ToolDefinition [ TAB_TOD_DEFINES_FAMILY ] [ self . ToolChain ] :
EdkLogger . verbose ( " No tool chain family found in configuration for %s . Default to MSFT. " \
% self . ToolChain )
RetVal = TAB_COMPILER_MSFT
else :
RetVal = ToolDefinition [ TAB_TOD_DEFINES_FAMILY ] [ self . ToolChain ]
return RetVal
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
@cached_property
def BuildRuleFamily ( self ) :
ToolDefinition = self . Workspace . ToolDef . ToolsDefTxtDatabase
if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
or self . ToolChain not in ToolDefinition [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] \
or not ToolDefinition [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] [ self . ToolChain ] :
EdkLogger . verbose ( " No tool chain family found in configuration for %s . Default to MSFT. " \
% self . ToolChain )
return TAB_COMPILER_MSFT
return ToolDefinition [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] [ self . ToolChain ]
2018-09-13 16:11:07 -07:00
## Return the build options specific for all modules in this platform
2019-06-11 10:40:54 -07:00
@cached_property
def BuildOption ( self ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions )
def _BuildOptionWithToolDef ( self , ToolDef ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions , ToolDef = ToolDef )
2018-09-13 16:11:07 -07:00
## Return the build options specific for EDK modules in this platform
2019-06-11 10:40:54 -07:00
@cached_property
def EdkBuildOption ( self ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions , EDK_NAME )
2018-09-13 16:11:07 -07:00
## Return the build options specific for EDKII modules in this platform
2019-06-11 10:40:54 -07:00
@cached_property
def EdkIIBuildOption ( self ) :
return self . _ExpandBuildOption ( self . Platform . BuildOptions , EDKII_NAME )
2018-09-13 16:11:07 -07:00
## Parse build_rule.txt in Conf Directory.
#
# @retval BuildRule object
#
2019-06-11 10:40:54 -07:00
@cached_property
def BuildRule ( self ) :
BuildRuleFile = None
if TAB_TAT_DEFINES_BUILD_RULE_CONF in self . Workspace . TargetTxt . TargetTxtDictionary :
BuildRuleFile = self . Workspace . TargetTxt . TargetTxtDictionary [ TAB_TAT_DEFINES_BUILD_RULE_CONF ]
if not BuildRuleFile :
BuildRuleFile = gDefaultBuildRuleFile
RetVal = BuildRule ( BuildRuleFile )
if RetVal . _FileVersion == " " :
RetVal . _FileVersion = AutoGenReqBuildRuleVerNum
else :
if RetVal . _FileVersion < AutoGenReqBuildRuleVerNum :
# If Build Rule's version is less than the version number required by the tools, halting the build.
EdkLogger . error ( " build " , AUTOGEN_ERROR ,
ExtraData = " The version number [ %s ] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [ %s ]) " \
% ( RetVal . _FileVersion , AutoGenReqBuildRuleVerNum ) )
return RetVal
2018-09-13 16:11:07 -07:00
## Summarize the packages used by modules in this platform
2019-06-11 10:40:54 -07:00
@cached_property
def PackageList ( self ) :
RetVal = set ( )
for La in self . LibraryAutoGenList :
RetVal . update ( La . DependentPackageList )
for Ma in self . ModuleAutoGenList :
RetVal . update ( Ma . DependentPackageList )
#Collect package set information from INF of FDF
for ModuleFile in self . _AsBuildModuleList :
if ModuleFile in self . Platform . Modules :
continue
ModuleData = self . BuildDatabase [ ModuleFile , self . Arch , self . BuildTarget , self . ToolChain ]
RetVal . update ( ModuleData . Packages )
return list ( RetVal )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
@cached_property
def NonDynamicPcdDict ( self ) :
return { ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) : Pcd for Pcd in self . NonDynamicPcdList }
2018-09-13 16:11:07 -07:00
## Get list of non-dynamic PCDs
2019-06-11 10:40:54 -07:00
@property
def NonDynamicPcdList ( self ) :
if not self . _NonDynamicPcdList :
2018-09-13 16:11:07 -07:00
self . CollectPlatformDynamicPcds ( )
return self . _NonDynamicPcdList
## Get list of dynamic PCDs
2019-06-11 10:40:54 -07:00
@property
def DynamicPcdList ( self ) :
if not self . _DynamicPcdList :
2018-09-13 16:11:07 -07:00
self . CollectPlatformDynamicPcds ( )
return self . _DynamicPcdList
## Generate Token Number for all PCD
2019-06-11 10:40:54 -07:00
@cached_property
def PcdTokenNumber ( self ) :
RetVal = OrderedDict ( )
TokenNumber = 1
#
# Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
# Such as:
#
# Dynamic PCD:
# TokenNumber 0 ~ 10
# DynamicEx PCD:
# TokeNumber 11 ~ 20
#
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " PEI " and Pcd . Type in PCD_DYNAMIC_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
2018-09-13 16:11:07 -07:00
TokenNumber + = 1
2019-06-11 10:40:54 -07:00
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " PEI " and Pcd . Type in PCD_DYNAMIC_EX_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " DXE " and Pcd . Type in PCD_DYNAMIC_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
for Pcd in self . DynamicPcdList :
if Pcd . Phase == " DXE " and Pcd . Type in PCD_DYNAMIC_EX_TYPE_SET :
EdkLogger . debug ( EdkLogger . DEBUG_5 , " %s %s ( %s ) -> %d " % ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , Pcd . Phase , TokenNumber ) )
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
for Pcd in self . NonDynamicPcdList :
RetVal [ Pcd . TokenCName , Pcd . TokenSpaceGuidCName ] = TokenNumber
TokenNumber + = 1
return RetVal
@cached_property
def _MaList ( self ) :
2018-09-13 16:11:07 -07:00
for ModuleFile in self . Platform . Modules :
Ma = ModuleAutoGen (
2019-06-11 10:40:54 -07:00
self . Workspace ,
ModuleFile ,
self . BuildTarget ,
self . ToolChain ,
self . Arch ,
self . MetaFile
)
self . Platform . Modules [ ModuleFile ] . M = Ma
return [ x . M for x in self . Platform . Modules . values ( ) ]
2018-09-13 16:11:07 -07:00
## Summarize ModuleAutoGen objects of all modules to be built for this platform
2019-06-11 10:40:54 -07:00
@cached_property
def ModuleAutoGenList ( self ) :
RetVal = [ ]
for Ma in self . _MaList :
if Ma not in RetVal :
RetVal . append ( Ma )
return RetVal
2018-09-13 16:11:07 -07:00
## Summarize ModuleAutoGen objects of all libraries to be built for this platform
2019-06-11 10:40:54 -07:00
@cached_property
def LibraryAutoGenList ( self ) :
RetVal = [ ]
for Ma in self . _MaList :
for La in Ma . LibraryAutoGenList :
if La not in RetVal :
RetVal . append ( La )
if Ma not in La . ReferenceModules :
La . ReferenceModules . append ( Ma )
return RetVal
2018-09-13 16:11:07 -07:00
## Test if a module is supported by the platform
#
# An error will be raised directly if the module or its arch is not supported
# by the platform or current configuration
#
def ValidModule ( self , Module ) :
return Module in self . Platform . Modules or Module in self . Platform . LibraryInstances \
or Module in self . _AsBuildModuleList
## Resolve the library classes in a module to library instances
#
# This method will not only resolve library classes but also sort the library
# instances according to the dependency-ship.
#
# @param Module The module from which the library classes will be resolved
#
# @retval library_list List of library instances sorted
#
def ApplyLibraryInstance ( self , Module ) :
# Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
if str ( Module ) not in self . Platform . Modules :
return [ ]
2019-06-11 10:40:54 -07:00
return GetModuleLibInstances ( Module ,
self . Platform ,
self . BuildDatabase ,
self . Arch ,
self . BuildTarget ,
self . ToolChain ,
self . MetaFile ,
EdkLogger )
2018-09-13 16:11:07 -07:00
## Override PCD setting (type, value, ...)
#
2019-06-11 10:40:54 -07:00
# @param ToPcd The PCD to be overridden
# @param FromPcd The PCD overriding from
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
def _OverridePcd ( self , ToPcd , FromPcd , Module = " " , Msg = " " , Library = " " ) :
2018-09-13 16:11:07 -07:00
#
# in case there's PCDs coming from FDF file, which have no type given.
# at this point, ToPcd.Type has the type found from dependent
# package
#
TokenCName = ToPcd . TokenCName
for PcdItem in GlobalData . MixedPcd :
if ( ToPcd . TokenCName , ToPcd . TokenSpaceGuidCName ) in GlobalData . MixedPcd [ PcdItem ] :
TokenCName = PcdItem [ 0 ]
break
2019-06-11 10:40:54 -07:00
if FromPcd is not None :
if ToPcd . Pending and FromPcd . Type :
2018-09-13 16:11:07 -07:00
ToPcd . Type = FromPcd . Type
2019-06-11 10:40:54 -07:00
elif ToPcd . Type and FromPcd . Type \
and ToPcd . Type != FromPcd . Type and ToPcd . Type in FromPcd . Type :
if ToPcd . Type . strip ( ) == TAB_PCDS_DYNAMIC_EX :
2018-09-13 16:11:07 -07:00
ToPcd . Type = FromPcd . Type
2019-06-11 10:40:54 -07:00
elif ToPcd . Type and FromPcd . Type \
2018-09-13 16:11:07 -07:00
and ToPcd . Type != FromPcd . Type :
2019-06-11 10:40:54 -07:00
if Library :
Module = str ( Module ) + " ' s library file ( " + str ( Library ) + " ) "
2018-09-13 16:11:07 -07:00
EdkLogger . error ( " build " , OPTION_CONFLICT , " Mismatched PCD type " ,
2019-06-11 10:40:54 -07:00
ExtraData = " %s . %s is used as [ %s ] in module %s , but as [ %s ] in %s . " \
2018-09-13 16:11:07 -07:00
% ( ToPcd . TokenSpaceGuidCName , TokenCName ,
2019-06-11 10:40:54 -07:00
ToPcd . Type , Module , FromPcd . Type , Msg ) ,
2018-09-13 16:11:07 -07:00
File = self . MetaFile )
2019-06-11 10:40:54 -07:00
if FromPcd . MaxDatumSize :
2018-09-13 16:11:07 -07:00
ToPcd . MaxDatumSize = FromPcd . MaxDatumSize
2019-06-11 10:40:54 -07:00
ToPcd . MaxSizeUserSet = FromPcd . MaxDatumSize
if FromPcd . DefaultValue :
2018-09-13 16:11:07 -07:00
ToPcd . DefaultValue = FromPcd . DefaultValue
2019-06-11 10:40:54 -07:00
if FromPcd . TokenValue :
2018-09-13 16:11:07 -07:00
ToPcd . TokenValue = FromPcd . TokenValue
2019-06-11 10:40:54 -07:00
if FromPcd . DatumType :
2018-09-13 16:11:07 -07:00
ToPcd . DatumType = FromPcd . DatumType
2019-06-11 10:40:54 -07:00
if FromPcd . SkuInfoList :
2018-09-13 16:11:07 -07:00
ToPcd . SkuInfoList = FromPcd . SkuInfoList
2019-06-11 10:40:54 -07:00
if FromPcd . UserDefinedDefaultStoresFlag :
ToPcd . UserDefinedDefaultStoresFlag = FromPcd . UserDefinedDefaultStoresFlag
2018-09-13 16:11:07 -07:00
# Add Flexible PCD format parse
if ToPcd . DefaultValue :
try :
2019-06-11 10:40:54 -07:00
ToPcd . DefaultValue = ValueExpressionEx ( ToPcd . DefaultValue , ToPcd . DatumType , self . Workspace . _GuidDict ) ( True )
except BadExpression as Value :
2018-09-13 16:11:07 -07:00
EdkLogger . error ( ' Parser ' , FORMAT_INVALID , ' PCD [ %s . %s ] Value " %s " , %s ' % ( ToPcd . TokenSpaceGuidCName , ToPcd . TokenCName , ToPcd . DefaultValue , Value ) ,
File = self . MetaFile )
# check the validation of datum
IsValid , Cause = CheckPcdDatum ( ToPcd . DatumType , ToPcd . DefaultValue )
if not IsValid :
EdkLogger . error ( ' build ' , FORMAT_INVALID , Cause , File = self . MetaFile ,
ExtraData = " %s . %s " % ( ToPcd . TokenSpaceGuidCName , TokenCName ) )
ToPcd . validateranges = FromPcd . validateranges
ToPcd . validlists = FromPcd . validlists
ToPcd . expressions = FromPcd . expressions
2019-06-11 10:40:54 -07:00
ToPcd . CustomAttribute = FromPcd . CustomAttribute
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
if FromPcd is not None and ToPcd . DatumType == TAB_VOID and not ToPcd . MaxDatumSize :
2018-09-13 16:11:07 -07:00
EdkLogger . debug ( EdkLogger . DEBUG_9 , " No MaxDatumSize specified for PCD %s . %s " \
% ( ToPcd . TokenSpaceGuidCName , TokenCName ) )
Value = ToPcd . DefaultValue
2019-06-11 10:40:54 -07:00
if not Value :
2018-09-13 16:11:07 -07:00
ToPcd . MaxDatumSize = ' 1 '
elif Value [ 0 ] == ' L ' :
ToPcd . MaxDatumSize = str ( ( len ( Value ) - 2 ) * 2 )
elif Value [ 0 ] == ' { ' :
ToPcd . MaxDatumSize = str ( len ( Value . split ( ' , ' ) ) )
else :
ToPcd . MaxDatumSize = str ( len ( Value ) - 1 )
# apply default SKU for dynamic PCDS if specified one is not available
2019-06-11 10:40:54 -07:00
if ( ToPcd . Type in PCD_DYNAMIC_TYPE_SET or ToPcd . Type in PCD_DYNAMIC_EX_TYPE_SET ) \
and not ToPcd . SkuInfoList :
2018-09-13 16:11:07 -07:00
if self . Platform . SkuName in self . Platform . SkuIds :
SkuName = self . Platform . SkuName
else :
2019-06-11 10:40:54 -07:00
SkuName = TAB_DEFAULT
2018-09-13 16:11:07 -07:00
ToPcd . SkuInfoList = {
SkuName : SkuInfoClass ( SkuName , self . Platform . SkuIds [ SkuName ] [ 0 ] , ' ' , ' ' , ' ' , ' ' , ' ' , ToPcd . DefaultValue )
}
## Apply PCD setting defined platform to a module
#
2019-06-11 10:40:54 -07:00
# @param Module The module from which the PCD setting will be overridden
2018-09-13 16:11:07 -07:00
#
# @retval PCD_list The list PCDs with settings from platform
#
2019-06-11 10:40:54 -07:00
def ApplyPcdSetting ( self , Module , Pcds , Library = " " ) :
2018-09-13 16:11:07 -07:00
# for each PCD in module
for Name , Guid in Pcds :
PcdInModule = Pcds [ Name , Guid ]
# find out the PCD setting in platform
if ( Name , Guid ) in self . Platform . Pcds :
PcdInPlatform = self . Platform . Pcds [ Name , Guid ]
else :
PcdInPlatform = None
# then override the settings if any
2019-06-11 10:40:54 -07:00
self . _OverridePcd ( PcdInModule , PcdInPlatform , Module , Msg = " DSC PCD sections " , Library = Library )
2018-09-13 16:11:07 -07:00
# resolve the VariableGuid value
for SkuId in PcdInModule . SkuInfoList :
Sku = PcdInModule . SkuInfoList [ SkuId ]
if Sku . VariableGuid == ' ' : continue
Sku . VariableGuidValue = GuidValue ( Sku . VariableGuid , self . PackageList , self . MetaFile . Path )
2019-06-11 10:40:54 -07:00
if Sku . VariableGuidValue is None :
PackageList = " \n \t " . join ( str ( P ) for P in self . PackageList )
2018-09-13 16:11:07 -07:00
EdkLogger . error (
' build ' ,
RESOURCE_NOT_AVAILABLE ,
" Value of GUID [ %s ] is not found in " % Sku . VariableGuid ,
ExtraData = PackageList + " \n \t (used with %s . %s from module %s ) " \
% ( Guid , Name , str ( Module ) ) ,
File = self . MetaFile
)
# override PCD settings with module specific setting
if Module in self . Platform . Modules :
PlatformModule = self . Platform . Modules [ str ( Module ) ]
for Key in PlatformModule . Pcds :
2019-06-11 10:40:54 -07:00
if GlobalData . BuildOptionPcd :
for pcd in GlobalData . BuildOptionPcd :
( TokenSpaceGuidCName , TokenCName , FieldName , pcdvalue , _ ) = pcd
if ( TokenCName , TokenSpaceGuidCName ) == Key and FieldName == " " :
PlatformModule . Pcds [ Key ] . DefaultValue = pcdvalue
PlatformModule . Pcds [ Key ] . PcdValueFromComm = pcdvalue
break
2018-09-13 16:11:07 -07:00
Flag = False
if Key in Pcds :
ToPcd = Pcds [ Key ]
Flag = True
elif Key in GlobalData . MixedPcd :
for PcdItem in GlobalData . MixedPcd [ Key ] :
if PcdItem in Pcds :
ToPcd = Pcds [ PcdItem ]
Flag = True
break
if Flag :
2019-06-11 10:40:54 -07:00
self . _OverridePcd ( ToPcd , PlatformModule . Pcds [ Key ] , Module , Msg = " DSC Components Module scoped PCD section " , Library = Library )
2018-09-13 16:11:07 -07:00
# use PCD value to calculate the MaxDatumSize when it is not specified
for Name , Guid in Pcds :
Pcd = Pcds [ Name , Guid ]
2019-06-11 10:40:54 -07:00
if Pcd . DatumType == TAB_VOID and not Pcd . MaxDatumSize :
Pcd . MaxSizeUserSet = None
2018-09-13 16:11:07 -07:00
Value = Pcd . DefaultValue
2019-06-11 10:40:54 -07:00
if not Value :
2018-09-13 16:11:07 -07:00
Pcd . MaxDatumSize = ' 1 '
elif Value [ 0 ] == ' L ' :
Pcd . MaxDatumSize = str ( ( len ( Value ) - 2 ) * 2 )
elif Value [ 0 ] == ' { ' :
Pcd . MaxDatumSize = str ( len ( Value . split ( ' , ' ) ) )
else :
Pcd . MaxDatumSize = str ( len ( Value ) - 1 )
2019-06-11 10:40:54 -07:00
return list ( Pcds . values ( ) )
2018-09-13 16:11:07 -07:00
## Calculate the priority value of the build option
#
# @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
#
# @retval Value Priority value based on the priority list.
#
def CalculatePriorityValue ( self , Key ) :
Target , ToolChain , Arch , CommandType , Attr = Key . split ( ' _ ' )
PriorityValue = 0x11111
2019-06-11 10:40:54 -07:00
if Target == TAB_STAR :
2018-09-13 16:11:07 -07:00
PriorityValue & = 0x01111
2019-06-11 10:40:54 -07:00
if ToolChain == TAB_STAR :
2018-09-13 16:11:07 -07:00
PriorityValue & = 0x10111
2019-06-11 10:40:54 -07:00
if Arch == TAB_STAR :
2018-09-13 16:11:07 -07:00
PriorityValue & = 0x11011
2019-06-11 10:40:54 -07:00
if CommandType == TAB_STAR :
2018-09-13 16:11:07 -07:00
PriorityValue & = 0x11101
2019-06-11 10:40:54 -07:00
if Attr == TAB_STAR :
2018-09-13 16:11:07 -07:00
PriorityValue & = 0x11110
return self . PrioList [ " 0x %0.5x " % PriorityValue ]
## Expand * in build option key
#
# @param Options Options to be expanded
2019-06-11 10:40:54 -07:00
# @param ToolDef Use specified ToolDef instead of full version.
# This is needed during initialization to prevent
# infinite recursion betweeh BuildOptions,
# ToolDefinition, and this function.
2018-09-13 16:11:07 -07:00
#
# @retval options Options expanded
2019-06-11 10:40:54 -07:00
#
def _ExpandBuildOption ( self , Options , ModuleStyle = None , ToolDef = None ) :
if not ToolDef :
ToolDef = self . ToolDefinition
2018-09-13 16:11:07 -07:00
BuildOptions = { }
FamilyMatch = False
FamilyIsNull = True
OverrideList = { }
#
# Construct a list contain the build options which need override.
#
for Key in Options :
#
# Key[0] -- tool family
# Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
#
if ( Key [ 0 ] == self . BuildRuleFamily and
2019-06-11 10:40:54 -07:00
( ModuleStyle is None or len ( Key ) < 3 or ( len ( Key ) > 2 and Key [ 2 ] == ModuleStyle ) ) ) :
2018-09-13 16:11:07 -07:00
Target , ToolChain , Arch , CommandType , Attr = Key [ 1 ] . split ( ' _ ' )
2019-06-11 10:40:54 -07:00
if ( Target == self . BuildTarget or Target == TAB_STAR ) and \
( ToolChain == self . ToolChain or ToolChain == TAB_STAR ) and \
( Arch == self . Arch or Arch == TAB_STAR ) and \
Options [ Key ] . startswith ( " = " ) :
if OverrideList . get ( Key [ 1 ] ) is not None :
OverrideList . pop ( Key [ 1 ] )
OverrideList [ Key [ 1 ] ] = Options [ Key ]
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
# Use the highest priority value.
2018-09-13 16:11:07 -07:00
#
if ( len ( OverrideList ) > = 2 ) :
2019-06-11 10:40:54 -07:00
KeyList = list ( OverrideList . keys ( ) )
2018-09-13 16:11:07 -07:00
for Index in range ( len ( KeyList ) ) :
NowKey = KeyList [ Index ]
Target1 , ToolChain1 , Arch1 , CommandType1 , Attr1 = NowKey . split ( " _ " )
for Index1 in range ( len ( KeyList ) - Index - 1 ) :
NextKey = KeyList [ Index1 + Index + 1 ]
#
# Compare two Key, if one is included by another, choose the higher priority one
2019-06-11 10:40:54 -07:00
#
2018-09-13 16:11:07 -07:00
Target2 , ToolChain2 , Arch2 , CommandType2 , Attr2 = NextKey . split ( " _ " )
2019-06-11 10:40:54 -07:00
if ( Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR ) and \
( ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR ) and \
( Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR ) and \
( CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR ) and \
( Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR ) :
if self . CalculatePriorityValue ( NowKey ) > self . CalculatePriorityValue ( NextKey ) :
if Options . get ( ( self . BuildRuleFamily , NextKey ) ) is not None :
Options . pop ( ( self . BuildRuleFamily , NextKey ) )
else :
if Options . get ( ( self . BuildRuleFamily , NowKey ) ) is not None :
Options . pop ( ( self . BuildRuleFamily , NowKey ) )
2018-09-13 16:11:07 -07:00
for Key in Options :
2019-06-11 10:40:54 -07:00
if ModuleStyle is not None and len ( Key ) > 2 :
2018-09-13 16:11:07 -07:00
# Check Module style is EDK or EDKII.
# Only append build option for the matched style module.
if ModuleStyle == EDK_NAME and Key [ 2 ] != EDK_NAME :
continue
elif ModuleStyle == EDKII_NAME and Key [ 2 ] != EDKII_NAME :
continue
Family = Key [ 0 ]
Target , Tag , Arch , Tool , Attr = Key [ 1 ] . split ( " _ " )
# if tool chain family doesn't match, skip it
2019-06-11 10:40:54 -07:00
if Tool in ToolDef and Family != " " :
2018-09-13 16:11:07 -07:00
FamilyIsNull = False
2019-06-11 10:40:54 -07:00
if ToolDef [ Tool ] . get ( TAB_TOD_DEFINES_BUILDRULEFAMILY , " " ) != " " :
if Family != ToolDef [ Tool ] [ TAB_TOD_DEFINES_BUILDRULEFAMILY ] :
2018-09-13 16:11:07 -07:00
continue
2019-06-11 10:40:54 -07:00
elif Family != ToolDef [ Tool ] [ TAB_TOD_DEFINES_FAMILY ] :
2018-09-13 16:11:07 -07:00
continue
FamilyMatch = True
# expand any wildcard
2019-06-11 10:40:54 -07:00
if Target == TAB_STAR or Target == self . BuildTarget :
if Tag == TAB_STAR or Tag == self . ToolChain :
if Arch == TAB_STAR or Arch == self . Arch :
2018-09-13 16:11:07 -07:00
if Tool not in BuildOptions :
BuildOptions [ Tool ] = { }
if Attr != " FLAGS " or Attr not in BuildOptions [ Tool ] or Options [ Key ] . startswith ( ' = ' ) :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
else :
# append options for the same tool except PATH
if Attr != ' PATH ' :
BuildOptions [ Tool ] [ Attr ] + = " " + Options [ Key ]
else :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
# Build Option Family has been checked, which need't to be checked again for family.
if FamilyMatch or FamilyIsNull :
return BuildOptions
for Key in Options :
2019-06-11 10:40:54 -07:00
if ModuleStyle is not None and len ( Key ) > 2 :
2018-09-13 16:11:07 -07:00
# Check Module style is EDK or EDKII.
# Only append build option for the matched style module.
if ModuleStyle == EDK_NAME and Key [ 2 ] != EDK_NAME :
continue
elif ModuleStyle == EDKII_NAME and Key [ 2 ] != EDKII_NAME :
continue
Family = Key [ 0 ]
Target , Tag , Arch , Tool , Attr = Key [ 1 ] . split ( " _ " )
# if tool chain family doesn't match, skip it
2019-06-11 10:40:54 -07:00
if Tool not in ToolDef or Family == " " :
2018-09-13 16:11:07 -07:00
continue
# option has been added before
2019-06-11 10:40:54 -07:00
if Family != ToolDef [ Tool ] [ TAB_TOD_DEFINES_FAMILY ] :
2018-09-13 16:11:07 -07:00
continue
# expand any wildcard
2019-06-11 10:40:54 -07:00
if Target == TAB_STAR or Target == self . BuildTarget :
if Tag == TAB_STAR or Tag == self . ToolChain :
if Arch == TAB_STAR or Arch == self . Arch :
2018-09-13 16:11:07 -07:00
if Tool not in BuildOptions :
BuildOptions [ Tool ] = { }
if Attr != " FLAGS " or Attr not in BuildOptions [ Tool ] or Options [ Key ] . startswith ( ' = ' ) :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
else :
# append options for the same tool except PATH
if Attr != ' PATH ' :
BuildOptions [ Tool ] [ Attr ] + = " " + Options [ Key ]
else :
BuildOptions [ Tool ] [ Attr ] = Options [ Key ]
return BuildOptions
## Append build options in platform to a module
#
2019-06-11 10:40:54 -07:00
# @param Module The module to which the build options will be appended
2018-09-13 16:11:07 -07:00
#
# @retval options The options appended with build options in platform
#
def ApplyBuildOption ( self , Module ) :
# Get the different options for the different style module
2019-06-11 10:40:54 -07:00
PlatformOptions = self . EdkIIBuildOption
ModuleTypeOptions = self . Platform . GetBuildOptionsByModuleType ( EDKII_NAME , Module . ModuleType )
2018-09-13 16:11:07 -07:00
ModuleTypeOptions = self . _ExpandBuildOption ( ModuleTypeOptions )
ModuleOptions = self . _ExpandBuildOption ( Module . BuildOptions )
if Module in self . Platform . Modules :
PlatformModule = self . Platform . Modules [ str ( Module ) ]
PlatformModuleOptions = self . _ExpandBuildOption ( PlatformModule . BuildOptions )
else :
PlatformModuleOptions = { }
BuildRuleOrder = None
for Options in [ self . ToolDefinition , ModuleOptions , PlatformOptions , ModuleTypeOptions , PlatformModuleOptions ] :
for Tool in Options :
for Attr in Options [ Tool ] :
if Attr == TAB_TOD_DEFINES_BUILDRULEORDER :
BuildRuleOrder = Options [ Tool ] [ Attr ]
2019-06-11 10:40:54 -07:00
AllTools = set ( list ( ModuleOptions . keys ( ) ) + list ( PlatformOptions . keys ( ) ) +
list ( PlatformModuleOptions . keys ( ) ) + list ( ModuleTypeOptions . keys ( ) ) +
list ( self . ToolDefinition . keys ( ) ) )
BuildOptions = defaultdict ( lambda : defaultdict ( str ) )
2018-09-13 16:11:07 -07:00
for Tool in AllTools :
for Options in [ self . ToolDefinition , ModuleOptions , PlatformOptions , ModuleTypeOptions , PlatformModuleOptions ] :
if Tool not in Options :
continue
for Attr in Options [ Tool ] :
#
# Do not generate it in Makefile
#
if Attr == TAB_TOD_DEFINES_BUILDRULEORDER :
continue
2019-06-11 10:40:54 -07:00
Value = Options [ Tool ] [ Attr ]
2018-09-13 16:11:07 -07:00
# check if override is indicated
if Value . startswith ( ' = ' ) :
2019-06-11 10:40:54 -07:00
BuildOptions [ Tool ] [ Attr ] = mws . handleWsMacro ( Value [ 1 : ] )
2018-09-13 16:11:07 -07:00
else :
if Attr != ' PATH ' :
2019-06-11 10:40:54 -07:00
BuildOptions [ Tool ] [ Attr ] + = " " + mws . handleWsMacro ( Value )
2018-09-13 16:11:07 -07:00
else :
2019-06-11 10:40:54 -07:00
BuildOptions [ Tool ] [ Attr ] = mws . handleWsMacro ( Value )
2018-09-13 16:11:07 -07:00
return BuildOptions , BuildRuleOrder
2019-06-11 10:40:54 -07:00
#
# extend lists contained in a dictionary with lists stored in another dictionary
# if CopyToDict is not derived from DefaultDict(list) then this may raise exception
#
def ExtendCopyDictionaryLists ( CopyToDict , CopyFromDict ) :
for Key in CopyFromDict :
CopyToDict [ Key ] . extend ( CopyFromDict [ Key ] )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
# Create a directory specified by a set of path elements and return the full path
def _MakeDir ( PathList ) :
RetVal = path . join ( * PathList )
CreateDirectory ( RetVal )
return RetVal
2018-09-13 16:11:07 -07:00
## ModuleAutoGen class
#
# This class encapsules the AutoGen behaviors for the build tools. In addition to
# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
# to the [depex] section in module's inf file.
#
class ModuleAutoGen ( AutoGen ) :
2019-06-11 10:40:54 -07:00
# call super().__init__ then call the worker function with different parameter count
def __init__ ( self , Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs ) :
if not hasattr ( self , " _Init " ) :
self . _InitWorker ( Workspace , MetaFile , Target , Toolchain , Arch , * args )
self . _Init = True
## Cache the timestamps of metafiles of every module in a class attribute
2018-09-13 16:11:07 -07:00
#
TimeDict = { }
2019-06-11 10:40:54 -07:00
def __new__ ( cls , Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs ) :
# check if this module is employed by active platform
if not PlatformAutoGen ( Workspace , args [ 0 ] , Target , Toolchain , Arch ) . ValidModule ( MetaFile ) :
EdkLogger . verbose ( " Module [ %s ] for [ %s ] is not employed by active platform \n " \
% ( MetaFile , Arch ) )
return None
return super ( ModuleAutoGen , cls ) . __new__ ( cls , Workspace , MetaFile , Target , Toolchain , Arch , * args , * * kwargs )
## Initialize ModuleAutoGen
2018-09-13 16:11:07 -07:00
#
# @param Workspace EdkIIWorkspaceBuild object
# @param ModuleFile The path of module file
# @param Target Build target (DEBUG, RELEASE)
# @param Toolchain Name of tool chain
# @param Arch The arch the module supports
# @param PlatformFile Platform meta-file
#
2019-06-11 10:40:54 -07:00
def _InitWorker ( self , Workspace , ModuleFile , Target , Toolchain , Arch , PlatformFile ) :
2018-09-13 16:11:07 -07:00
EdkLogger . debug ( EdkLogger . DEBUG_9 , " AutoGen module [ %s ] [ %s ] " % ( ModuleFile , Arch ) )
GlobalData . gProcessingFile = " %s [ %s , %s , %s ] " % ( ModuleFile , Arch , Toolchain , Target )
self . Workspace = Workspace
self . WorkspaceDir = Workspace . WorkspaceDir
self . MetaFile = ModuleFile
self . PlatformInfo = PlatformAutoGen ( Workspace , PlatformFile , Target , Toolchain , Arch )
self . SourceDir = self . MetaFile . SubDir
self . SourceDir = mws . relpath ( self . SourceDir , self . WorkspaceDir )
self . ToolChain = Toolchain
self . BuildTarget = Target
self . Arch = Arch
self . ToolChainFamily = self . PlatformInfo . ToolChainFamily
self . BuildRuleFamily = self . PlatformInfo . BuildRuleFamily
self . IsCodeFileCreated = False
self . IsAsBuiltInfCreated = False
self . DepexGenerated = False
self . BuildDatabase = self . Workspace . BuildDatabase
self . BuildRuleOrder = None
self . BuildTime = 0
2019-06-11 10:40:54 -07:00
self . _PcdComments = OrderedListDict ( )
self . _GuidComments = OrderedListDict ( )
self . _ProtocolComments = OrderedListDict ( )
self . _PpiComments = OrderedListDict ( )
2018-09-13 16:11:07 -07:00
self . _BuildTargets = None
self . _IntroBuildTargetList = None
self . _FinalBuildTargetList = None
self . _FileTypes = None
self . AutoGenDepSet = set ( )
2019-06-11 10:40:54 -07:00
self . ReferenceModules = [ ]
2018-09-13 16:11:07 -07:00
self . ConstPcd = { }
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
def __repr__ ( self ) :
return " %s [ %s ] " % ( self . MetaFile , self . Arch )
# Get FixedAtBuild Pcds of this Module
2019-06-11 10:40:54 -07:00
@cached_property
def FixedAtBuildPcds ( self ) :
RetVal = [ ]
2018-09-13 16:11:07 -07:00
for Pcd in self . ModulePcdList :
2019-06-11 10:40:54 -07:00
if Pcd . Type != TAB_PCDS_FIXED_AT_BUILD :
2018-09-13 16:11:07 -07:00
continue
2019-06-11 10:40:54 -07:00
if Pcd not in RetVal :
RetVal . append ( Pcd )
return RetVal
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
@cached_property
def FixedVoidTypePcds ( self ) :
RetVal = { }
for Pcd in self . FixedAtBuildPcds :
if Pcd . DatumType == TAB_VOID :
if ' {} . {} ' . format ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) not in RetVal :
RetVal [ ' {} . {} ' . format ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) ] = Pcd . DefaultValue
return RetVal
@property
def UniqueBaseName ( self ) :
2018-09-13 16:11:07 -07:00
BaseName = self . Name
for Module in self . PlatformInfo . ModuleAutoGenList :
if Module . MetaFile == self . MetaFile :
continue
if Module . Name == self . Name :
if uuid . UUID ( Module . Guid ) == uuid . UUID ( self . Guid ) :
EdkLogger . error ( " build " , FILE_DUPLICATED , ' Modules have same BaseName and FILE_GUID: \n '
' %s \n %s ' % ( Module . MetaFile , self . MetaFile ) )
BaseName = ' %s _ %s ' % ( self . Name , self . Guid )
return BaseName
# Macros could be used in build_rule.txt (also Makefile)
2019-06-11 10:40:54 -07:00
@cached_property
def Macros ( self ) :
return OrderedDict ( (
( " WORKSPACE " , self . WorkspaceDir ) ,
( " MODULE_NAME " , self . Name ) ,
( " MODULE_NAME_GUID " , self . UniqueBaseName ) ,
( " MODULE_GUID " , self . Guid ) ,
( " MODULE_VERSION " , self . Version ) ,
( " MODULE_TYPE " , self . ModuleType ) ,
( " MODULE_FILE " , str ( self . MetaFile ) ) ,
( " MODULE_FILE_BASE_NAME " , self . MetaFile . BaseName ) ,
( " MODULE_RELATIVE_DIR " , self . SourceDir ) ,
( " MODULE_DIR " , self . SourceDir ) ,
( " BASE_NAME " , self . Name ) ,
( " ARCH " , self . Arch ) ,
( " TOOLCHAIN " , self . ToolChain ) ,
( " TOOLCHAIN_TAG " , self . ToolChain ) ,
( " TOOL_CHAIN_TAG " , self . ToolChain ) ,
( " TARGET " , self . BuildTarget ) ,
( " BUILD_DIR " , self . PlatformInfo . BuildDir ) ,
( " BIN_DIR " , os . path . join ( self . PlatformInfo . BuildDir , self . Arch ) ) ,
( " LIB_DIR " , os . path . join ( self . PlatformInfo . BuildDir , self . Arch ) ) ,
( " MODULE_BUILD_DIR " , self . BuildDir ) ,
( " OUTPUT_DIR " , self . OutputDir ) ,
( " DEBUG_DIR " , self . DebugDir ) ,
( " DEST_DIR_OUTPUT " , self . OutputDir ) ,
( " DEST_DIR_DEBUG " , self . DebugDir ) ,
( " PLATFORM_NAME " , self . PlatformInfo . Name ) ,
( " PLATFORM_GUID " , self . PlatformInfo . Guid ) ,
( " PLATFORM_VERSION " , self . PlatformInfo . Version ) ,
( " PLATFORM_RELATIVE_DIR " , self . PlatformInfo . SourceDir ) ,
( " PLATFORM_DIR " , mws . join ( self . WorkspaceDir , self . PlatformInfo . SourceDir ) ) ,
( " PLATFORM_OUTPUT_DIR " , self . PlatformInfo . OutputDir ) ,
( " FFS_OUTPUT_DIR " , self . FfsOutputDir )
) )
2018-09-13 16:11:07 -07:00
## Return the module build data object
2019-06-11 10:40:54 -07:00
@cached_property
def Module ( self ) :
return self . BuildDatabase [ self . MetaFile , self . Arch , self . BuildTarget , self . ToolChain ]
2018-09-13 16:11:07 -07:00
## Return the module name
2019-06-11 10:40:54 -07:00
@cached_property
def Name ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . BaseName
## Return the module DxsFile if exist
2019-06-11 10:40:54 -07:00
@cached_property
def DxsFile ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . DxsFile
## Return the module meta-file GUID
2019-06-11 10:40:54 -07:00
@cached_property
def Guid ( self ) :
2018-09-13 16:11:07 -07:00
#
# To build same module more than once, the module path with FILE_GUID overridden has
2019-06-11 10:40:54 -07:00
# the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
2018-09-13 16:11:07 -07:00
# in DSC. The overridden GUID can be retrieved from file name
#
if os . path . basename ( self . MetaFile . File ) != os . path . basename ( self . MetaFile . Path ) :
#
# Length of GUID is 36
#
return os . path . basename ( self . MetaFile . Path ) [ : 36 ]
return self . Module . Guid
## Return the module version
2019-06-11 10:40:54 -07:00
@cached_property
def Version ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . Version
## Return the module type
2019-06-11 10:40:54 -07:00
@cached_property
def ModuleType ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . ModuleType
## Return the component type (for Edk.x style of module)
2019-06-11 10:40:54 -07:00
@cached_property
def ComponentType ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . ComponentType
## Return the build type
2019-06-11 10:40:54 -07:00
@cached_property
def BuildType ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . BuildType
## Return the PCD_IS_DRIVER setting
2019-06-11 10:40:54 -07:00
@cached_property
def PcdIsDriver ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . PcdIsDriver
## Return the autogen version, i.e. module meta-file version
2019-06-11 10:40:54 -07:00
@cached_property
def AutoGenVersion ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . AutoGenVersion
## Check if the module is library or not
2019-06-11 10:40:54 -07:00
@cached_property
def IsLibrary ( self ) :
return bool ( self . Module . LibraryClass )
2018-09-13 16:11:07 -07:00
## Check if the module is binary module or not
2019-06-11 10:40:54 -07:00
@cached_property
def IsBinaryModule ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . IsBinaryModule
## Return the directory to store intermediate files of the module
2019-06-11 10:40:54 -07:00
@cached_property
def BuildDir ( self ) :
return _MakeDir ( (
2018-09-13 16:11:07 -07:00
self . PlatformInfo . BuildDir ,
self . Arch ,
self . SourceDir ,
self . MetaFile . BaseName
2019-06-11 10:40:54 -07:00
) )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
## Return the directory to store the intermediate object files of the module
@cached_property
def OutputDir ( self ) :
return _MakeDir ( ( self . BuildDir , " OUTPUT " ) )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
## Return the directory path to store ffs file
@cached_property
def FfsOutputDir ( self ) :
if GlobalData . gFdfParser :
return path . join ( self . PlatformInfo . BuildDir , TAB_FV_DIRECTORY , " Ffs " , self . Guid + self . Name )
return ' '
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
## Return the directory to store auto-gened source files of the module
@cached_property
def DebugDir ( self ) :
return _MakeDir ( ( self . BuildDir , " DEBUG " ) )
2018-09-13 16:11:07 -07:00
## Return the path of custom file
2019-06-11 10:40:54 -07:00
@cached_property
def CustomMakefile ( self ) :
RetVal = { }
for Type in self . Module . CustomMakefile :
MakeType = gMakeTypeMap [ Type ] if Type in gMakeTypeMap else ' nmake '
File = os . path . join ( self . SourceDir , self . Module . CustomMakefile [ Type ] )
RetVal [ MakeType ] = File
return RetVal
2018-09-13 16:11:07 -07:00
## Return the directory of the makefile
#
# @retval string The directory string of module's makefile
#
2019-06-11 10:40:54 -07:00
@cached_property
def MakeFileDir ( self ) :
2018-09-13 16:11:07 -07:00
return self . BuildDir
## Return build command string
#
# @retval string Build command string
#
2019-06-11 10:40:54 -07:00
@cached_property
def BuildCommand ( self ) :
2018-09-13 16:11:07 -07:00
return self . PlatformInfo . BuildCommand
## Get object list of all packages the module and its dependent libraries belong to
#
# @retval list The list of package object
#
2019-06-11 10:40:54 -07:00
@cached_property
def DerivedPackageList ( self ) :
2018-09-13 16:11:07 -07:00
PackageList = [ ]
for M in [ self . Module ] + self . DependentLibraryList :
for Package in M . Packages :
if Package in PackageList :
continue
PackageList . append ( Package )
return PackageList
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
## Get the depex string
#
2019-06-11 10:40:54 -07:00
# @return : a string contain all depex expression.
2018-09-13 16:11:07 -07:00
def _GetDepexExpresionString ( self ) :
DepexStr = ' '
DepexList = [ ]
## DPX_SOURCE IN Define section.
if self . Module . DxsFile :
return DepexStr
for M in [ self . Module ] + self . DependentLibraryList :
Filename = M . MetaFile . Path
InfObj = InfSectionParser . InfSectionParser ( Filename )
2019-06-11 10:40:54 -07:00
DepexExpressionList = InfObj . GetDepexExpresionList ( )
for DepexExpression in DepexExpressionList :
for key in DepexExpression :
2018-09-13 16:11:07 -07:00
Arch , ModuleType = key
2019-06-11 10:40:54 -07:00
DepexExpr = [ x for x in DepexExpression [ key ] if not str ( x ) . startswith ( ' # ' ) ]
2018-09-13 16:11:07 -07:00
# the type of build module is USER_DEFINED.
# All different DEPEX section tags would be copied into the As Built INF file
# and there would be separate DEPEX section tags
if self . ModuleType . upper ( ) == SUP_MODULE_USER_DEFINED :
if ( Arch . upper ( ) == self . Arch . upper ( ) ) and ( ModuleType . upper ( ) != TAB_ARCH_COMMON ) :
DepexList . append ( { ( Arch , ModuleType ) : DepexExpr } )
else :
if Arch . upper ( ) == TAB_ARCH_COMMON or \
( Arch . upper ( ) == self . Arch . upper ( ) and \
ModuleType . upper ( ) in [ TAB_ARCH_COMMON , self . ModuleType . upper ( ) ] ) :
DepexList . append ( { ( Arch , ModuleType ) : DepexExpr } )
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
#the type of build module is USER_DEFINED.
if self . ModuleType . upper ( ) == SUP_MODULE_USER_DEFINED :
for Depex in DepexList :
2019-06-11 10:40:54 -07:00
for key in Depex :
2018-09-13 16:11:07 -07:00
DepexStr + = ' [Depex. %s . %s ] \n ' % key
2019-06-11 10:40:54 -07:00
DepexStr + = ' \n ' . join ( ' # ' + val for val in Depex [ key ] )
2018-09-13 16:11:07 -07:00
DepexStr + = ' \n \n '
if not DepexStr :
return ' [Depex. %s ] \n ' % self . Arch
return DepexStr
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
#the type of build module not is USER_DEFINED.
Count = 0
for Depex in DepexList :
Count + = 1
if DepexStr != ' ' :
DepexStr + = ' AND '
DepexStr + = ' ( '
for D in Depex . values ( ) :
2019-06-11 10:40:54 -07:00
DepexStr + = ' ' . join ( val for val in D )
2018-09-13 16:11:07 -07:00
Index = DepexStr . find ( ' END ' )
if Index > - 1 and Index == len ( DepexStr ) - 3 :
DepexStr = DepexStr [ : - 3 ]
DepexStr = DepexStr . strip ( )
DepexStr + = ' ) '
if Count == 1 :
DepexStr = DepexStr . lstrip ( ' ( ' ) . rstrip ( ' ) ' ) . strip ( )
if not DepexStr :
return ' [Depex. %s ] \n ' % self . Arch
return ' [Depex. %s ] \n # ' % self . Arch + DepexStr
## Merge dependency expression
#
# @retval list The token list of the dependency expression after parsed
#
2019-06-11 10:40:54 -07:00
@cached_property
def DepexList ( self ) :
if self . DxsFile or self . IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self . FileTypes :
return { }
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
DepexList = [ ]
#
# Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
#
for M in [ self . Module ] + self . DependentLibraryList :
Inherited = False
for D in M . Depex [ self . Arch , self . ModuleType ] :
if DepexList != [ ] :
DepexList . append ( ' AND ' )
DepexList . append ( ' ( ' )
#replace D with value if D is FixedAtBuild PCD
NewList = [ ]
for item in D :
if ' . ' not in item :
NewList . append ( item )
else :
FixedVoidTypePcds = { }
if item in self . FixedVoidTypePcds :
FixedVoidTypePcds = self . FixedVoidTypePcds
elif M in self . PlatformInfo . LibraryAutoGenList :
Index = self . PlatformInfo . LibraryAutoGenList . index ( M )
FixedVoidTypePcds = self . PlatformInfo . LibraryAutoGenList [ Index ] . FixedVoidTypePcds
if item not in FixedVoidTypePcds :
EdkLogger . error ( " build " , FORMAT_INVALID , " {} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module. " . format ( item ) )
else :
Value = FixedVoidTypePcds [ item ]
if len ( Value . split ( ' , ' ) ) != 16 :
EdkLogger . error ( " build " , FORMAT_INVALID ,
" {} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module. " . format ( item ) )
NewList . append ( Value )
DepexList . extend ( NewList )
if DepexList [ - 1 ] == ' END ' : # no need of a END at this time
DepexList . pop ( )
DepexList . append ( ' ) ' )
Inherited = True
if Inherited :
EdkLogger . verbose ( " DEPEX[ %s ] (+ %s ) = %s " % ( self . Name , M . BaseName , DepexList ) )
if ' BEFORE ' in DepexList or ' AFTER ' in DepexList :
break
if len ( DepexList ) > 0 :
EdkLogger . verbose ( ' ' )
return { self . ModuleType : DepexList }
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
## Merge dependency expression
#
# @retval list The token list of the dependency expression after parsed
#
@cached_property
def DepexExpressionDict ( self ) :
if self . DxsFile or self . IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self . FileTypes :
return { }
DepexExpressionString = ' '
#
# Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
#
for M in [ self . Module ] + self . DependentLibraryList :
Inherited = False
for D in M . DepexExpression [ self . Arch , self . ModuleType ] :
if DepexExpressionString != ' ' :
DepexExpressionString + = ' AND '
DepexExpressionString + = ' ( '
DepexExpressionString + = D
DepexExpressionString = DepexExpressionString . rstrip ( ' END ' ) . strip ( )
DepexExpressionString + = ' ) '
Inherited = True
if Inherited :
EdkLogger . verbose ( " DEPEX[ %s ] (+ %s ) = %s " % ( self . Name , M . BaseName , DepexExpressionString ) )
if ' BEFORE ' in DepexExpressionString or ' AFTER ' in DepexExpressionString :
break
if len ( DepexExpressionString ) > 0 :
EdkLogger . verbose ( ' ' )
return { self . ModuleType : DepexExpressionString }
2018-09-13 16:11:07 -07:00
# Get the tiano core user extension, it is contain dependent library.
# @retval: a list contain tiano core userextension.
#
def _GetTianoCoreUserExtensionList ( self ) :
TianoCoreUserExtentionList = [ ]
for M in [ self . Module ] + self . DependentLibraryList :
Filename = M . MetaFile . Path
InfObj = InfSectionParser . InfSectionParser ( Filename )
TianoCoreUserExtenList = InfObj . GetUserExtensionTianoCore ( )
for TianoCoreUserExtent in TianoCoreUserExtenList :
2019-06-11 10:40:54 -07:00
for Section in TianoCoreUserExtent :
2018-09-13 16:11:07 -07:00
ItemList = Section . split ( TAB_SPLIT )
Arch = self . Arch
if len ( ItemList ) == 4 :
Arch = ItemList [ 3 ]
if Arch . upper ( ) == TAB_ARCH_COMMON or Arch . upper ( ) == self . Arch . upper ( ) :
TianoCoreList = [ ]
TianoCoreList . extend ( [ TAB_SECTION_START + Section + TAB_SECTION_END ] )
TianoCoreList . extend ( TianoCoreUserExtent [ Section ] [ : ] )
TianoCoreList . append ( ' \n ' )
TianoCoreUserExtentionList . append ( TianoCoreList )
return TianoCoreUserExtentionList
## Return the list of specification version required for the module
#
# @retval list The list of specification defined in module file
#
2019-06-11 10:40:54 -07:00
@cached_property
def Specification ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . Specification
## Tool option for the module build
#
# @param PlatformInfo The object of PlatformBuildInfo
# @retval dict The dict containing valid options
#
2019-06-11 10:40:54 -07:00
@cached_property
def BuildOption ( self ) :
RetVal , self . BuildRuleOrder = self . PlatformInfo . ApplyBuildOption ( self . Module )
if self . BuildRuleOrder :
self . BuildRuleOrder = [ ' . %s ' % Ext for Ext in self . BuildRuleOrder . split ( ) ]
return RetVal
2018-09-13 16:11:07 -07:00
## Get include path list from tool option for the module build
#
# @retval list The include path list
#
2019-06-11 10:40:54 -07:00
@cached_property
def BuildOptionIncPathList ( self ) :
#
# Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
# is the former use /I , the Latter used -I to specify include directories
#
if self . PlatformInfo . ToolChainFamily in ( TAB_COMPILER_MSFT ) :
BuildOptIncludeRegEx = gBuildOptIncludePatternMsft
elif self . PlatformInfo . ToolChainFamily in ( ' INTEL ' , ' GCC ' , ' RVCT ' ) :
BuildOptIncludeRegEx = gBuildOptIncludePatternOther
else :
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
# New ToolChainFamily, don't known whether there is option to specify include directories
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
return [ ]
RetVal = [ ]
for Tool in ( ' CC ' , ' PP ' , ' VFRPP ' , ' ASLPP ' , ' ASLCC ' , ' APP ' , ' ASM ' ) :
try :
FlagOption = self . BuildOption [ Tool ] [ ' FLAGS ' ]
except KeyError :
FlagOption = ' '
if self . ToolChainFamily != ' RVCT ' :
IncPathList = [ NormPath ( Path , self . Macros ) for Path in BuildOptIncludeRegEx . findall ( FlagOption ) ]
2018-09-13 16:11:07 -07:00
else :
#
2019-06-11 10:40:54 -07:00
# RVCT may specify a list of directory seperated by commas
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
IncPathList = [ ]
for Path in BuildOptIncludeRegEx . findall ( FlagOption ) :
PathList = GetSplitList ( Path , TAB_COMMA_SPLIT )
IncPathList . extend ( NormPath ( PathEntry , self . Macros ) for PathEntry in PathList )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
#
# EDK II modules must not reference header files outside of the packages they depend on or
# within the module's directory tree. Report error if violation.
#
if GlobalData . gDisableIncludePathCheck == False :
for Path in IncPathList :
if ( Path not in self . IncludePathList ) and ( CommonPath ( [ Path , self . MetaFile . Dir ] ) != self . MetaFile . Dir ) :
ErrMsg = " The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS ' %s ' " % ( Path , Tool , FlagOption )
EdkLogger . error ( " build " ,
PARAMETER_INVALID ,
ExtraData = ErrMsg ,
File = str ( self . MetaFile ) )
RetVal + = IncPathList
return RetVal
2018-09-13 16:11:07 -07:00
## Return a list of files which can be built from source
#
# What kind of files can be built is determined by build rules in
# $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
#
2019-06-11 10:40:54 -07:00
@cached_property
def SourceFileList ( self ) :
RetVal = [ ]
ToolChainTagSet = { " " , TAB_STAR , self . ToolChain }
ToolChainFamilySet = { " " , TAB_STAR , self . ToolChainFamily , self . BuildRuleFamily }
for F in self . Module . Sources :
# match tool chain
if F . TagName not in ToolChainTagSet :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " The toolchain [ %s ] for processing file [ %s ] is found, "
" but [ %s ] is currently used " % ( F . TagName , str ( F ) , self . ToolChain ) )
continue
# match tool chain family or build rule family
if F . ToolChainFamily not in ToolChainFamilySet :
EdkLogger . debug (
EdkLogger . DEBUG_0 ,
" The file [ %s ] must be built by tools of [ %s ], " \
" but current toolchain family is [ %s ], buildrule family is [ %s ] " \
% ( str ( F ) , F . ToolChainFamily , self . ToolChainFamily , self . BuildRuleFamily ) )
continue
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
# add the file path into search path list for file including
if F . Dir not in self . IncludePathList :
self . IncludePathList . insert ( 0 , F . Dir )
RetVal . append ( F )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
self . _MatchBuildRuleOrder ( RetVal )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
for F in RetVal :
self . _ApplyBuildRule ( F , TAB_UNKNOWN_FILE )
return RetVal
2018-09-13 16:11:07 -07:00
def _MatchBuildRuleOrder ( self , FileList ) :
Order_Dict = { }
2019-06-11 10:40:54 -07:00
self . BuildOption
2018-09-13 16:11:07 -07:00
for SingleFile in FileList :
if self . BuildRuleOrder and SingleFile . Ext in self . BuildRuleOrder and SingleFile . Ext in self . BuildRules :
2019-06-11 10:40:54 -07:00
key = SingleFile . Path . rsplit ( SingleFile . Ext , 1 ) [ 0 ]
2018-09-13 16:11:07 -07:00
if key in Order_Dict :
Order_Dict [ key ] . append ( SingleFile . Ext )
else :
Order_Dict [ key ] = [ SingleFile . Ext ]
RemoveList = [ ]
for F in Order_Dict :
if len ( Order_Dict [ F ] ) > 1 :
Order_Dict [ F ] . sort ( key = lambda i : self . BuildRuleOrder . index ( i ) )
for Ext in Order_Dict [ F ] [ 1 : ] :
RemoveList . append ( F + Ext )
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
for item in RemoveList :
FileList . remove ( item )
return FileList
## Return the list of unicode files
2019-06-11 10:40:54 -07:00
@cached_property
def UnicodeFileList ( self ) :
return self . FileTypes . get ( TAB_UNICODE_FILE , [ ] )
2018-09-13 16:11:07 -07:00
## Return the list of vfr files
2019-06-11 10:40:54 -07:00
@cached_property
def VfrFileList ( self ) :
return self . FileTypes . get ( TAB_VFR_FILE , [ ] )
2018-09-13 16:11:07 -07:00
## Return the list of Image Definition files
2019-06-11 10:40:54 -07:00
@cached_property
def IdfFileList ( self ) :
return self . FileTypes . get ( TAB_IMAGE_FILE , [ ] )
2018-09-13 16:11:07 -07:00
## Return a list of files which can be built from binary
#
# "Build" binary files are just to copy them to build directory.
#
# @retval list The list of files which can be built later
#
2019-06-11 10:40:54 -07:00
@cached_property
def BinaryFileList ( self ) :
RetVal = [ ]
for F in self . Module . Binaries :
if F . Target not in [ TAB_ARCH_COMMON , TAB_STAR ] and F . Target != self . BuildTarget :
continue
RetVal . append ( F )
self . _ApplyBuildRule ( F , F . Type , BinaryFileList = RetVal )
return RetVal
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
@cached_property
def BuildRules ( self ) :
RetVal = { }
BuildRuleDatabase = self . PlatformInfo . BuildRule
for Type in BuildRuleDatabase . FileTypeList :
#first try getting build rule by BuildRuleFamily
RuleObject = BuildRuleDatabase [ Type , self . BuildType , self . Arch , self . BuildRuleFamily ]
if not RuleObject :
# build type is always module type, but ...
if self . ModuleType != self . BuildType :
RuleObject = BuildRuleDatabase [ Type , self . ModuleType , self . Arch , self . BuildRuleFamily ]
#second try getting build rule by ToolChainFamily
if not RuleObject :
RuleObject = BuildRuleDatabase [ Type , self . BuildType , self . Arch , self . ToolChainFamily ]
2018-09-13 16:11:07 -07:00
if not RuleObject :
# build type is always module type, but ...
if self . ModuleType != self . BuildType :
2019-06-11 10:40:54 -07:00
RuleObject = BuildRuleDatabase [ Type , self . ModuleType , self . Arch , self . ToolChainFamily ]
if not RuleObject :
continue
RuleObject = RuleObject . Instantiate ( self . Macros )
RetVal [ Type ] = RuleObject
for Ext in RuleObject . SourceFileExtList :
RetVal [ Ext ] = RuleObject
return RetVal
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
def _ApplyBuildRule ( self , File , FileType , BinaryFileList = None ) :
if self . _BuildTargets is None :
2018-09-13 16:11:07 -07:00
self . _IntroBuildTargetList = set ( )
self . _FinalBuildTargetList = set ( )
2019-06-11 10:40:54 -07:00
self . _BuildTargets = defaultdict ( set )
self . _FileTypes = defaultdict ( set )
if not BinaryFileList :
BinaryFileList = self . BinaryFileList
2018-09-13 16:11:07 -07:00
SubDirectory = os . path . join ( self . OutputDir , File . SubDir )
if not os . path . exists ( SubDirectory ) :
CreateDirectory ( SubDirectory )
LastTarget = None
2019-06-11 10:40:54 -07:00
RuleChain = set ( )
2018-09-13 16:11:07 -07:00
SourceList = [ File ]
Index = 0
#
# Make sure to get build rule order value
#
2019-06-11 10:40:54 -07:00
self . BuildOption
2018-09-13 16:11:07 -07:00
while Index < len ( SourceList ) :
Source = SourceList [ Index ]
Index = Index + 1
if Source != File :
CreateDirectory ( Source . Dir )
2019-06-11 10:40:54 -07:00
if File . IsBinary and File == Source and File in BinaryFileList :
2018-09-13 16:11:07 -07:00
# Skip all files that are not binary libraries
if not self . IsLibrary :
continue
RuleObject = self . BuildRules [ TAB_DEFAULT_BINARY_FILE ]
elif FileType in self . BuildRules :
RuleObject = self . BuildRules [ FileType ]
elif Source . Ext in self . BuildRules :
RuleObject = self . BuildRules [ Source . Ext ]
else :
# stop at no more rules
if LastTarget :
self . _FinalBuildTargetList . add ( LastTarget )
break
FileType = RuleObject . SourceFileType
self . _FileTypes [ FileType ] . add ( Source )
# stop at STATIC_LIBRARY for library
if self . IsLibrary and FileType == TAB_STATIC_LIBRARY :
if LastTarget :
self . _FinalBuildTargetList . add ( LastTarget )
break
Target = RuleObject . Apply ( Source , self . BuildRuleOrder )
if not Target :
if LastTarget :
self . _FinalBuildTargetList . add ( LastTarget )
break
elif not Target . Outputs :
# Only do build for target with outputs
self . _FinalBuildTargetList . add ( Target )
self . _BuildTargets [ FileType ] . add ( Target )
if not Source . IsBinary and Source == File :
self . _IntroBuildTargetList . add ( Target )
# to avoid cyclic rule
if FileType in RuleChain :
break
2019-06-11 10:40:54 -07:00
RuleChain . add ( FileType )
2018-09-13 16:11:07 -07:00
SourceList . extend ( Target . Outputs )
LastTarget = Target
FileType = TAB_UNKNOWN_FILE
2019-06-11 10:40:54 -07:00
@cached_property
def Targets ( self ) :
if self . _BuildTargets is None :
2018-09-13 16:11:07 -07:00
self . _IntroBuildTargetList = set ( )
self . _FinalBuildTargetList = set ( )
2019-06-11 10:40:54 -07:00
self . _BuildTargets = defaultdict ( set )
self . _FileTypes = defaultdict ( set )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
#TRICK: call SourceFileList property to apply build rule for source files
self . SourceFileList
2018-09-13 16:11:07 -07:00
#TRICK: call _GetBinaryFileList to apply build rule for binary files
2019-06-11 10:40:54 -07:00
self . BinaryFileList
2018-09-13 16:11:07 -07:00
return self . _BuildTargets
2019-06-11 10:40:54 -07:00
@cached_property
def IntroTargetList ( self ) :
self . Targets
2018-09-13 16:11:07 -07:00
return self . _IntroBuildTargetList
2019-06-11 10:40:54 -07:00
@cached_property
def CodaTargetList ( self ) :
self . Targets
2018-09-13 16:11:07 -07:00
return self . _FinalBuildTargetList
2019-06-11 10:40:54 -07:00
@cached_property
def FileTypes ( self ) :
self . Targets
2018-09-13 16:11:07 -07:00
return self . _FileTypes
## Get the list of package object the module depends on
#
# @retval list The package object list
#
2019-06-11 10:40:54 -07:00
@cached_property
def DependentPackageList ( self ) :
2018-09-13 16:11:07 -07:00
return self . Module . Packages
## Return the list of auto-generated code file
#
# @retval list The list of auto-generated file
#
2019-06-11 10:40:54 -07:00
@cached_property
def AutoGenFileList ( self ) :
AutoGenUniIdf = self . BuildType != ' UEFI_HII '
UniStringBinBuffer = BytesIO ( )
IdfGenBinBuffer = BytesIO ( )
RetVal = { }
AutoGenC = TemplateString ( )
AutoGenH = TemplateString ( )
StringH = TemplateString ( )
StringIdf = TemplateString ( )
GenC . CreateCode ( self , AutoGenC , AutoGenH , StringH , AutoGenUniIdf , UniStringBinBuffer , StringIdf , AutoGenUniIdf , IdfGenBinBuffer )
#
# AutoGen.c is generated if there are library classes in inf, or there are object files
#
if str ( AutoGenC ) != " " and ( len ( self . Module . LibraryClasses ) > 0
or TAB_OBJECT_FILE in self . FileTypes ) :
AutoFile = PathClass ( gAutoGenCodeFileName , self . DebugDir )
RetVal [ AutoFile ] = str ( AutoGenC )
self . _ApplyBuildRule ( AutoFile , TAB_UNKNOWN_FILE )
if str ( AutoGenH ) != " " :
AutoFile = PathClass ( gAutoGenHeaderFileName , self . DebugDir )
RetVal [ AutoFile ] = str ( AutoGenH )
self . _ApplyBuildRule ( AutoFile , TAB_UNKNOWN_FILE )
if str ( StringH ) != " " :
AutoFile = PathClass ( gAutoGenStringFileName % { " module_name " : self . Name } , self . DebugDir )
RetVal [ AutoFile ] = str ( StringH )
self . _ApplyBuildRule ( AutoFile , TAB_UNKNOWN_FILE )
if UniStringBinBuffer is not None and UniStringBinBuffer . getvalue ( ) != b " " :
AutoFile = PathClass ( gAutoGenStringFormFileName % { " module_name " : self . Name } , self . OutputDir )
RetVal [ AutoFile ] = UniStringBinBuffer . getvalue ( )
AutoFile . IsBinary = True
self . _ApplyBuildRule ( AutoFile , TAB_UNKNOWN_FILE )
if UniStringBinBuffer is not None :
UniStringBinBuffer . close ( )
if str ( StringIdf ) != " " :
AutoFile = PathClass ( gAutoGenImageDefFileName % { " module_name " : self . Name } , self . DebugDir )
RetVal [ AutoFile ] = str ( StringIdf )
self . _ApplyBuildRule ( AutoFile , TAB_UNKNOWN_FILE )
if IdfGenBinBuffer is not None and IdfGenBinBuffer . getvalue ( ) != b " " :
AutoFile = PathClass ( gAutoGenIdfFileName % { " module_name " : self . Name } , self . OutputDir )
RetVal [ AutoFile ] = IdfGenBinBuffer . getvalue ( )
AutoFile . IsBinary = True
self . _ApplyBuildRule ( AutoFile , TAB_UNKNOWN_FILE )
if IdfGenBinBuffer is not None :
IdfGenBinBuffer . close ( )
return RetVal
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
## Return the list of library modules explicitly or implicitly used by this module
@cached_property
def DependentLibraryList ( self ) :
# only merge library classes and PCD for non-library module
if self . IsLibrary :
return [ ]
return self . PlatformInfo . ApplyLibraryInstance ( self . Module )
2018-09-13 16:11:07 -07:00
## Get the list of PCDs from current module
#
# @retval list The list of PCD
#
2019-06-11 10:40:54 -07:00
@cached_property
def ModulePcdList ( self ) :
# apply PCD settings from platform
RetVal = self . PlatformInfo . ApplyPcdSetting ( self . Module , self . Module . Pcds )
ExtendCopyDictionaryLists ( self . _PcdComments , self . Module . PcdComments )
return RetVal
2018-09-13 16:11:07 -07:00
## Get the list of PCDs from dependent libraries
#
# @retval list The list of PCD
#
2019-06-11 10:40:54 -07:00
@cached_property
def LibraryPcdList ( self ) :
if self . IsLibrary :
return [ ]
RetVal = [ ]
Pcds = set ( )
# get PCDs from dependent libraries
for Library in self . DependentLibraryList :
PcdsInLibrary = OrderedDict ( )
ExtendCopyDictionaryLists ( self . _PcdComments , Library . PcdComments )
for Key in Library . Pcds :
# skip duplicated PCDs
if Key in self . Module . Pcds or Key in Pcds :
continue
Pcds . add ( Key )
PcdsInLibrary [ Key ] = copy . copy ( Library . Pcds [ Key ] )
RetVal . extend ( self . PlatformInfo . ApplyPcdSetting ( self . Module , PcdsInLibrary , Library = Library ) )
return RetVal
2018-09-13 16:11:07 -07:00
## Get the GUID value mapping
#
# @retval dict The mapping between GUID cname and its value
#
2019-06-11 10:40:54 -07:00
@cached_property
def GuidList ( self ) :
RetVal = OrderedDict ( self . Module . Guids )
for Library in self . DependentLibraryList :
RetVal . update ( Library . Guids )
ExtendCopyDictionaryLists ( self . _GuidComments , Library . GuidComments )
ExtendCopyDictionaryLists ( self . _GuidComments , self . Module . GuidComments )
return RetVal
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
@cached_property
2018-09-13 16:11:07 -07:00
def GetGuidsUsedByPcd ( self ) :
2019-06-11 10:40:54 -07:00
RetVal = OrderedDict ( self . Module . GetGuidsUsedByPcd ( ) )
for Library in self . DependentLibraryList :
RetVal . update ( Library . GetGuidsUsedByPcd ( ) )
return RetVal
2018-09-13 16:11:07 -07:00
## Get the protocol value mapping
#
# @retval dict The mapping between protocol cname and its value
#
2019-06-11 10:40:54 -07:00
@cached_property
def ProtocolList ( self ) :
RetVal = OrderedDict ( self . Module . Protocols )
for Library in self . DependentLibraryList :
RetVal . update ( Library . Protocols )
ExtendCopyDictionaryLists ( self . _ProtocolComments , Library . ProtocolComments )
ExtendCopyDictionaryLists ( self . _ProtocolComments , self . Module . ProtocolComments )
return RetVal
2018-09-13 16:11:07 -07:00
## Get the PPI value mapping
#
# @retval dict The mapping between PPI cname and its value
#
2019-06-11 10:40:54 -07:00
@cached_property
def PpiList ( self ) :
RetVal = OrderedDict ( self . Module . Ppis )
for Library in self . DependentLibraryList :
RetVal . update ( Library . Ppis )
ExtendCopyDictionaryLists ( self . _PpiComments , Library . PpiComments )
ExtendCopyDictionaryLists ( self . _PpiComments , self . Module . PpiComments )
return RetVal
2018-09-13 16:11:07 -07:00
## Get the list of include search path
#
# @retval list The list path
#
2019-06-11 10:40:54 -07:00
@cached_property
def IncludePathList ( self ) :
RetVal = [ ]
RetVal . append ( self . MetaFile . Dir )
RetVal . append ( self . DebugDir )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
for Package in self . Module . Packages :
PackageDir = mws . join ( self . WorkspaceDir , Package . MetaFile . Dir )
if PackageDir not in RetVal :
RetVal . append ( PackageDir )
IncludesList = Package . Includes
if Package . _PrivateIncludes :
if not self . MetaFile . OriginalPath . Path . startswith ( PackageDir ) :
IncludesList = list ( set ( Package . Includes ) . difference ( set ( Package . _PrivateIncludes ) ) )
for Inc in IncludesList :
if Inc not in RetVal :
RetVal . append ( str ( Inc ) )
return RetVal
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
@cached_property
def IncludePathLength ( self ) :
return sum ( len ( inc ) + 1 for inc in self . IncludePathList )
2018-09-13 16:11:07 -07:00
## Get HII EX PCDs which maybe used by VFR
#
# efivarstore used by VFR may relate with HII EX PCDs
# Get the variable name and GUID from efivarstore and HII EX PCD
# List the HII EX PCDs in As Built INF if both name and GUID match.
#
# @retval list HII EX PCDs
#
def _GetPcdsMaybeUsedByVfr ( self ) :
if not self . SourceFileList :
return [ ]
2019-06-11 10:40:54 -07:00
NameGuids = set ( )
2018-09-13 16:11:07 -07:00
for SrcFile in self . SourceFileList :
if SrcFile . Ext . lower ( ) != ' .vfr ' :
continue
Vfri = os . path . join ( self . OutputDir , SrcFile . BaseName + ' .i ' )
if not os . path . exists ( Vfri ) :
continue
VfriFile = open ( Vfri , ' r ' )
Content = VfriFile . read ( )
VfriFile . close ( )
Pos = Content . find ( ' efivarstore ' )
while Pos != - 1 :
#
# Make sure 'efivarstore' is the start of efivarstore statement
# In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
#
Index = Pos - 1
while Index > = 0 and Content [ Index ] in ' \t \r \n ' :
Index - = 1
if Index > = 0 and Content [ Index ] != ' ; ' :
Pos = Content . find ( ' efivarstore ' , Pos + len ( ' efivarstore ' ) )
continue
#
# 'efivarstore' must be followed by name and guid
#
Name = gEfiVarStoreNamePattern . search ( Content , Pos )
if not Name :
break
Guid = gEfiVarStoreGuidPattern . search ( Content , Pos )
if not Guid :
break
2019-06-11 10:40:54 -07:00
NameArray = _ConvertStringToByteArray ( ' L " ' + Name . group ( 1 ) + ' " ' )
NameGuids . add ( ( NameArray , GuidStructureStringToGuidString ( Guid . group ( 1 ) ) ) )
2018-09-13 16:11:07 -07:00
Pos = Content . find ( ' efivarstore ' , Name . end ( ) )
if not NameGuids :
return [ ]
HiiExPcds = [ ]
for Pcd in self . PlatformInfo . Platform . Pcds . values ( ) :
if Pcd . Type != TAB_PCDS_DYNAMIC_EX_HII :
continue
2019-06-11 10:40:54 -07:00
for SkuInfo in Pcd . SkuInfoList . values ( ) :
2018-09-13 16:11:07 -07:00
Value = GuidValue ( SkuInfo . VariableGuid , self . PlatformInfo . PackageList , self . MetaFile . Path )
if not Value :
continue
2019-06-11 10:40:54 -07:00
Name = _ConvertStringToByteArray ( SkuInfo . VariableName )
2018-09-13 16:11:07 -07:00
Guid = GuidStructureStringToGuidString ( Value )
if ( Name , Guid ) in NameGuids and Pcd not in HiiExPcds :
HiiExPcds . append ( Pcd )
break
return HiiExPcds
def _GenOffsetBin ( self ) :
VfrUniBaseName = { }
for SourceFile in self . Module . Sources :
if SourceFile . Type . upper ( ) == " .VFR " :
#
2019-06-11 10:40:54 -07:00
# search the .map file to find the offset of vfr binary in the PE32+/TE file.
2018-09-13 16:11:07 -07:00
#
VfrUniBaseName [ SourceFile . BaseName ] = ( SourceFile . BaseName + " Bin " )
2019-06-11 10:40:54 -07:00
elif SourceFile . Type . upper ( ) == " .UNI " :
2018-09-13 16:11:07 -07:00
#
2019-06-11 10:40:54 -07:00
# search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
2018-09-13 16:11:07 -07:00
#
VfrUniBaseName [ " UniOffsetName " ] = ( self . Name + " Strings " )
2019-06-11 10:40:54 -07:00
if not VfrUniBaseName :
2018-09-13 16:11:07 -07:00
return None
MapFileName = os . path . join ( self . OutputDir , self . Name + " .map " )
EfiFileName = os . path . join ( self . OutputDir , self . Name + " .efi " )
2019-06-11 10:40:54 -07:00
VfrUniOffsetList = GetVariableOffset ( MapFileName , EfiFileName , list ( VfrUniBaseName . values ( ) ) )
2018-09-13 16:11:07 -07:00
if not VfrUniOffsetList :
return None
OutputName = ' %s Offset.bin ' % self . Name
UniVfrOffsetFileName = os . path . join ( self . OutputDir , OutputName )
try :
fInputfile = open ( UniVfrOffsetFileName , " wb+ " , 0 )
except :
2019-06-11 10:40:54 -07:00
EdkLogger . error ( " build " , FILE_OPEN_FAILURE , " File open failed for %s " % UniVfrOffsetFileName , None )
2018-09-13 16:11:07 -07:00
2019-06-11 10:40:54 -07:00
# Use a instance of BytesIO to cache data
fStringIO = BytesIO ( )
2018-09-13 16:11:07 -07: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-06-11 10:40:54 -07:00
UniGuid = b ' \xe0 \xc5 \x13 \x89 \xf6 3 \x86 M \x9b \xf1 C \xef \x89 \xfc \x06 f '
fStringIO . write ( UniGuid )
2018-09-13 16:11:07 -07: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-06-11 10:40:54 -07:00
VfrGuid = b ' \xb4 | \xbc \xd0 Gj_I \xaa \x11 q \x07 F \xda \x06 \xa2 '
fStringIO . write ( VfrGuid )
2018-09-13 16:11:07 -07:00
VfrValue = pack ( ' Q ' , int ( Item [ 1 ] , 16 ) )
fStringIO . write ( VfrValue )
#
# write data into file.
#
2019-06-11 10:40:54 -07:00
try :
2018-09-13 16:11:07 -07:00
fInputfile . write ( fStringIO . getvalue ( ) )
except :
EdkLogger . error ( " build " , FILE_WRITE_FAILURE , " Write data to file %s failed, please check whether the "
2019-06-11 10:40:54 -07:00
" file been locked or using by other applications. " % UniVfrOffsetFileName , None )
2018-09-13 16:11:07 -07:00
fStringIO . close ( )
fInputfile . close ( )
return OutputName
## Create AsBuilt INF file the module
#
def CreateAsBuiltInf ( self , IsOnlyCopy = False ) :
2019-06-11 10:40:54 -07:00
self . OutputFile = set ( )
if IsOnlyCopy and GlobalData . gBinCacheDest :
self . CopyModuleToCache ( )
return
2018-09-13 16:11:07 -07:00
if self . IsAsBuiltInfCreated :
return
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
# Skip the following code for libraries
if self . IsLibrary :
return
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
# Skip the following code for modules with no source files
2019-06-11 10:40:54 -07:00
if not self . SourceFileList :
2018-09-13 16:11:07 -07:00
return
# Skip the following code for modules without any binary files
2019-06-11 10:40:54 -07:00
if self . BinaryFileList :
2018-09-13 16:11:07 -07:00
return
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
### TODO: How to handles mixed source and binary modules
# Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
# Also find all packages that the DynamicEx PCDs depend on
Pcds = [ ]
PatchablePcds = [ ]
Packages = [ ]
PcdCheckList = [ ]
PcdTokenSpaceList = [ ]
for Pcd in self . ModulePcdList + self . LibraryPcdList :
if Pcd . Type == TAB_PCDS_PATCHABLE_IN_MODULE :
2019-06-11 10:40:54 -07:00
PatchablePcds . append ( Pcd )
PcdCheckList . append ( ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , TAB_PCDS_PATCHABLE_IN_MODULE ) )
elif Pcd . Type in PCD_DYNAMIC_EX_TYPE_SET :
2018-09-13 16:11:07 -07:00
if Pcd not in Pcds :
2019-06-11 10:40:54 -07:00
Pcds . append ( Pcd )
PcdCheckList . append ( ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , TAB_PCDS_DYNAMIC_EX ) )
PcdCheckList . append ( ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName , TAB_PCDS_DYNAMIC ) )
2018-09-13 16:11:07 -07:00
PcdTokenSpaceList . append ( Pcd . TokenSpaceGuidCName )
2019-06-11 10:40:54 -07:00
GuidList = OrderedDict ( self . GuidList )
for TokenSpace in self . GetGuidsUsedByPcd :
2018-09-13 16:11:07 -07:00
# If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
# The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList :
GuidList . pop ( TokenSpace )
CheckList = ( GuidList , self . PpiList , self . ProtocolList , PcdCheckList )
for Package in self . DerivedPackageList :
if Package in Packages :
continue
BeChecked = ( Package . Guids , Package . Ppis , Package . Protocols , Package . Pcds )
Found = False
for Index in range ( len ( BeChecked ) ) :
for Item in CheckList [ Index ] :
if Item in BeChecked [ Index ] :
2019-06-11 10:40:54 -07:00
Packages . append ( Package )
2018-09-13 16:11:07 -07:00
Found = True
break
2019-06-11 10:40:54 -07:00
if Found :
break
2018-09-13 16:11:07 -07:00
VfrPcds = self . _GetPcdsMaybeUsedByVfr ( )
for Pkg in self . PlatformInfo . PackageList :
if Pkg in Packages :
continue
for VfrPcd in VfrPcds :
2019-06-11 10:40:54 -07:00
if ( ( VfrPcd . TokenCName , VfrPcd . TokenSpaceGuidCName , TAB_PCDS_DYNAMIC_EX ) in Pkg . Pcds or
( VfrPcd . TokenCName , VfrPcd . TokenSpaceGuidCName , TAB_PCDS_DYNAMIC ) in Pkg . Pcds ) :
Packages . append ( Pkg )
2018-09-13 16:11:07 -07:00
break
2019-06-11 10:40:54 -07:00
ModuleType = SUP_MODULE_DXE_DRIVER if self . ModuleType == SUP_MODULE_UEFI_DRIVER and self . DepexGenerated else self . ModuleType
DriverType = self . PcdIsDriver if self . PcdIsDriver else ' '
2018-09-13 16:11:07 -07:00
Guid = self . Guid
MDefs = self . Module . Defines
AsBuiltInfDict = {
' module_name ' : self . Name ,
' module_guid ' : Guid ,
' module_module_type ' : ModuleType ,
' module_version_string ' : [ MDefs [ ' VERSION_STRING ' ] ] if ' VERSION_STRING ' in MDefs else [ ] ,
' pcd_is_driver_string ' : [ ] ,
' module_uefi_specification_version ' : [ ] ,
' module_pi_specification_version ' : [ ] ,
' module_entry_point ' : self . Module . ModuleEntryPointList ,
' module_unload_image ' : self . Module . ModuleUnloadImageList ,
' module_constructor ' : self . Module . ConstructorList ,
' module_destructor ' : self . Module . DestructorList ,
' module_shadow ' : [ MDefs [ ' SHADOW ' ] ] if ' SHADOW ' in MDefs else [ ] ,
' module_pci_vendor_id ' : [ MDefs [ ' PCI_VENDOR_ID ' ] ] if ' PCI_VENDOR_ID ' in MDefs else [ ] ,
' module_pci_device_id ' : [ MDefs [ ' PCI_DEVICE_ID ' ] ] if ' PCI_DEVICE_ID ' in MDefs else [ ] ,
' module_pci_class_code ' : [ MDefs [ ' PCI_CLASS_CODE ' ] ] if ' PCI_CLASS_CODE ' in MDefs else [ ] ,
' module_pci_revision ' : [ MDefs [ ' PCI_REVISION ' ] ] if ' PCI_REVISION ' in MDefs else [ ] ,
' module_build_number ' : [ MDefs [ ' BUILD_NUMBER ' ] ] if ' BUILD_NUMBER ' in MDefs else [ ] ,
' module_spec ' : [ MDefs [ ' SPEC ' ] ] if ' SPEC ' in MDefs else [ ] ,
' module_uefi_hii_resource_section ' : [ MDefs [ ' UEFI_HII_RESOURCE_SECTION ' ] ] if ' UEFI_HII_RESOURCE_SECTION ' in MDefs else [ ] ,
' module_uni_file ' : [ MDefs [ ' MODULE_UNI_FILE ' ] ] if ' MODULE_UNI_FILE ' in MDefs else [ ] ,
' module_arch ' : self . Arch ,
2019-06-11 10:40:54 -07:00
' package_item ' : [ Package . MetaFile . File . replace ( ' \\ ' , ' / ' ) for Package in Packages ] ,
2018-09-13 16:11:07 -07:00
' binary_item ' : [ ] ,
' patchablepcd_item ' : [ ] ,
' pcd_item ' : [ ] ,
' protocol_item ' : [ ] ,
' ppi_item ' : [ ] ,
' guid_item ' : [ ] ,
' flags_item ' : [ ] ,
' libraryclasses_item ' : [ ]
}
if ' MODULE_UNI_FILE ' in MDefs :
UNIFile = os . path . join ( self . MetaFile . Dir , MDefs [ ' MODULE_UNI_FILE ' ] )
if os . path . isfile ( UNIFile ) :
shutil . copy2 ( UNIFile , self . OutputDir )
if self . AutoGenVersion > int ( gInfSpecVersion , 0 ) :
AsBuiltInfDict [ ' module_inf_version ' ] = ' 0x %08x ' % self . AutoGenVersion
else :
AsBuiltInfDict [ ' module_inf_version ' ] = gInfSpecVersion
if DriverType :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' pcd_is_driver_string ' ] . append ( DriverType )
2018-09-13 16:11:07 -07:00
if ' UEFI_SPECIFICATION_VERSION ' in self . Specification :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' module_uefi_specification_version ' ] . append ( self . Specification [ ' UEFI_SPECIFICATION_VERSION ' ] )
2018-09-13 16:11:07 -07:00
if ' PI_SPECIFICATION_VERSION ' in self . Specification :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' module_pi_specification_version ' ] . append ( self . Specification [ ' PI_SPECIFICATION_VERSION ' ] )
2018-09-13 16:11:07 -07:00
OutputDir = self . OutputDir . replace ( ' \\ ' , ' / ' ) . strip ( ' / ' )
DebugDir = self . DebugDir . replace ( ' \\ ' , ' / ' ) . strip ( ' / ' )
for Item in self . CodaTargetList :
File = Item . Target . Path . replace ( ' \\ ' , ' / ' ) . strip ( ' / ' ) . replace ( DebugDir , ' ' ) . replace ( OutputDir , ' ' ) . strip ( ' / ' )
2019-06-11 10:40:54 -07:00
self . OutputFile . add ( File )
2018-09-13 16:11:07 -07:00
if os . path . isabs ( File ) :
File = File . replace ( ' \\ ' , ' / ' ) . strip ( ' / ' ) . replace ( OutputDir , ' ' ) . strip ( ' / ' )
if Item . Target . Ext . lower ( ) == ' .aml ' :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' binary_item ' ] . append ( ' ASL| ' + File )
2018-09-13 16:11:07 -07:00
elif Item . Target . Ext . lower ( ) == ' .acpi ' :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' binary_item ' ] . append ( ' ACPI| ' + File )
2018-09-13 16:11:07 -07:00
elif Item . Target . Ext . lower ( ) == ' .efi ' :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' binary_item ' ] . append ( ' PE32| ' + self . Name + ' .efi ' )
2018-09-13 16:11:07 -07:00
else :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' binary_item ' ] . append ( ' BIN| ' + File )
if not self . DepexGenerated :
DepexFile = os . path . join ( self . OutputDir , self . Name + ' .depex ' )
if os . path . exists ( DepexFile ) :
self . DepexGenerated = True
2018-09-13 16:11:07 -07:00
if self . DepexGenerated :
2019-06-11 10:40:54 -07:00
self . OutputFile . add ( self . Name + ' .depex ' )
if self . ModuleType in [ SUP_MODULE_PEIM ] :
AsBuiltInfDict [ ' binary_item ' ] . append ( ' PEI_DEPEX| ' + self . Name + ' .depex ' )
elif self . ModuleType in [ SUP_MODULE_DXE_DRIVER , SUP_MODULE_DXE_RUNTIME_DRIVER , SUP_MODULE_DXE_SAL_DRIVER , SUP_MODULE_UEFI_DRIVER ] :
AsBuiltInfDict [ ' binary_item ' ] . append ( ' DXE_DEPEX| ' + self . Name + ' .depex ' )
elif self . ModuleType in [ SUP_MODULE_DXE_SMM_DRIVER ] :
AsBuiltInfDict [ ' binary_item ' ] . append ( ' SMM_DEPEX| ' + self . Name + ' .depex ' )
2018-09-13 16:11:07 -07:00
Bin = self . _GenOffsetBin ( )
if Bin :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' binary_item ' ] . append ( ' BIN| %s ' % Bin )
self . OutputFile . add ( Bin )
2018-09-13 16:11:07 -07:00
for Root , Dirs , Files in os . walk ( OutputDir ) :
for File in Files :
if File . lower ( ) . endswith ( ' .pdb ' ) :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' binary_item ' ] . append ( ' DISPOSABLE| ' + File )
self . OutputFile . add ( File )
2018-09-13 16:11:07 -07:00
HeaderComments = self . Module . HeaderComments
StartPos = 0
for Index in range ( len ( HeaderComments ) ) :
if HeaderComments [ Index ] . find ( ' @BinaryHeader ' ) != - 1 :
HeaderComments [ Index ] = HeaderComments [ Index ] . replace ( ' @BinaryHeader ' , ' @file ' )
StartPos = Index
break
AsBuiltInfDict [ ' header_comments ' ] = ' \n ' . join ( HeaderComments [ StartPos : ] ) . replace ( ' :# ' , ' :// ' )
AsBuiltInfDict [ ' tail_comments ' ] = ' \n ' . join ( self . Module . TailComments )
GenList = [
( self . ProtocolList , self . _ProtocolComments , ' protocol_item ' ) ,
( self . PpiList , self . _PpiComments , ' ppi_item ' ) ,
( GuidList , self . _GuidComments , ' guid_item ' )
]
for Item in GenList :
for CName in Item [ 0 ] :
2019-06-11 10:40:54 -07:00
Comments = ' \n ' . join ( Item [ 1 ] [ CName ] ) if CName in Item [ 1 ] else ' '
Entry = Comments + ' \n ' + CName if Comments else CName
2018-09-13 16:11:07 -07:00
AsBuiltInfDict [ Item [ 2 ] ] . append ( Entry )
PatchList = parsePcdInfoFromMapFile (
os . path . join ( self . OutputDir , self . Name + ' .map ' ) ,
os . path . join ( self . OutputDir , self . Name + ' .efi ' )
)
if PatchList :
for Pcd in PatchablePcds :
TokenCName = Pcd . TokenCName
for PcdItem in GlobalData . MixedPcd :
if ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) in GlobalData . MixedPcd [ PcdItem ] :
TokenCName = PcdItem [ 0 ]
break
for PatchPcd in PatchList :
if TokenCName == PatchPcd [ 0 ] :
break
else :
continue
PcdValue = ' '
if Pcd . DatumType == ' BOOLEAN ' :
BoolValue = Pcd . DefaultValue . upper ( )
if BoolValue == ' TRUE ' :
Pcd . DefaultValue = ' 1 '
elif BoolValue == ' FALSE ' :
Pcd . DefaultValue = ' 0 '
2019-06-11 10:40:54 -07:00
if Pcd . DatumType in TAB_PCD_NUMERIC_TYPES :
2018-09-13 16:11:07 -07:00
HexFormat = ' 0x %02x '
2019-06-11 10:40:54 -07:00
if Pcd . DatumType == TAB_UINT16 :
2018-09-13 16:11:07 -07:00
HexFormat = ' 0x %04x '
2019-06-11 10:40:54 -07:00
elif Pcd . DatumType == TAB_UINT32 :
2018-09-13 16:11:07 -07:00
HexFormat = ' 0x %08x '
2019-06-11 10:40:54 -07:00
elif Pcd . DatumType == TAB_UINT64 :
2018-09-13 16:11:07 -07:00
HexFormat = ' 0x %016x '
PcdValue = HexFormat % int ( Pcd . DefaultValue , 0 )
else :
2019-06-11 10:40:54 -07:00
if Pcd . MaxDatumSize is None or Pcd . MaxDatumSize == ' ' :
2018-09-13 16:11:07 -07:00
EdkLogger . error ( " build " , AUTOGEN_ERROR ,
" Unknown [MaxDatumSize] of PCD [ %s . %s ] " % ( Pcd . TokenSpaceGuidCName , TokenCName )
)
ArraySize = int ( Pcd . MaxDatumSize , 0 )
PcdValue = Pcd . DefaultValue
if PcdValue [ 0 ] != ' { ' :
Unicode = False
if PcdValue [ 0 ] == ' L ' :
Unicode = True
PcdValue = PcdValue . lstrip ( ' L ' )
PcdValue = eval ( PcdValue )
NewValue = ' { '
for Index in range ( 0 , len ( PcdValue ) ) :
if Unicode :
CharVal = ord ( PcdValue [ Index ] )
NewValue = NewValue + ' 0x %02x ' % ( CharVal & 0x00FF ) + ' , ' \
+ ' 0x %02x ' % ( CharVal >> 8 ) + ' , '
else :
NewValue = NewValue + ' 0x %02x ' % ( ord ( PcdValue [ Index ] ) % 0x100 ) + ' , '
Padding = ' 0x00, '
if Unicode :
Padding = Padding * 2
2019-06-11 10:40:54 -07:00
ArraySize = ArraySize / / 2
2018-09-13 16:11:07 -07:00
if ArraySize < ( len ( PcdValue ) + 1 ) :
2019-06-11 10:40:54 -07:00
if Pcd . MaxSizeUserSet :
EdkLogger . error ( " build " , AUTOGEN_ERROR ,
2018-09-13 16:11:07 -07:00
" The maximum size of VOID* type PCD ' %s . %s ' is less than its actual size occupied. " % ( Pcd . TokenSpaceGuidCName , TokenCName )
)
2019-06-11 10:40:54 -07:00
else :
ArraySize = len ( PcdValue ) + 1
2018-09-13 16:11:07 -07:00
if ArraySize > len ( PcdValue ) + 1 :
NewValue = NewValue + Padding * ( ArraySize - len ( PcdValue ) - 1 )
PcdValue = NewValue + Padding . strip ( ) . rstrip ( ' , ' ) + ' } '
elif len ( PcdValue . split ( ' , ' ) ) < = ArraySize :
PcdValue = PcdValue . rstrip ( ' } ' ) + ' , 0x00 ' * ( ArraySize - len ( PcdValue . split ( ' , ' ) ) )
PcdValue + = ' } '
else :
2019-06-11 10:40:54 -07:00
if Pcd . MaxSizeUserSet :
EdkLogger . error ( " build " , AUTOGEN_ERROR ,
2018-09-13 16:11:07 -07:00
" The maximum size of VOID* type PCD ' %s . %s ' is less than its actual size occupied. " % ( Pcd . TokenSpaceGuidCName , TokenCName )
)
2019-06-11 10:40:54 -07:00
else :
ArraySize = len ( PcdValue ) + 1
2018-09-13 16:11:07 -07:00
PcdItem = ' %s . %s | %s |0x %X ' % \
( Pcd . TokenSpaceGuidCName , TokenCName , PcdValue , PatchPcd [ 1 ] )
PcdComments = ' '
if ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) in self . _PcdComments :
PcdComments = ' \n ' . join ( self . _PcdComments [ Pcd . TokenSpaceGuidCName , Pcd . TokenCName ] )
if PcdComments :
PcdItem = PcdComments + ' \n ' + PcdItem
AsBuiltInfDict [ ' patchablepcd_item ' ] . append ( PcdItem )
for Pcd in Pcds + VfrPcds :
PcdCommentList = [ ]
HiiInfo = ' '
TokenCName = Pcd . TokenCName
for PcdItem in GlobalData . MixedPcd :
if ( Pcd . TokenCName , Pcd . TokenSpaceGuidCName ) in GlobalData . MixedPcd [ PcdItem ] :
TokenCName = PcdItem [ 0 ]
break
if Pcd . Type == TAB_PCDS_DYNAMIC_EX_HII :
for SkuName in Pcd . SkuInfoList :
SkuInfo = Pcd . SkuInfoList [ SkuName ]
HiiInfo = ' ## %s | %s | %s ' % ( SkuInfo . VariableName , SkuInfo . VariableGuid , SkuInfo . VariableOffset )
break
if ( Pcd . TokenSpaceGuidCName , Pcd . TokenCName ) in self . _PcdComments :
PcdCommentList = self . _PcdComments [ Pcd . TokenSpaceGuidCName , Pcd . TokenCName ] [ : ]
if HiiInfo :
UsageIndex = - 1
UsageStr = ' '
for Index , Comment in enumerate ( PcdCommentList ) :
for Usage in UsageList :
if Comment . find ( Usage ) != - 1 :
UsageStr = Usage
UsageIndex = Index
break
if UsageIndex != - 1 :
2019-06-11 10:40:54 -07:00
PcdCommentList [ UsageIndex ] = ' ## %s %s %s ' % ( UsageStr , HiiInfo , PcdCommentList [ UsageIndex ] . replace ( UsageStr , ' ' ) )
2018-09-13 16:11:07 -07:00
else :
PcdCommentList . append ( ' ## UNDEFINED ' + HiiInfo )
PcdComments = ' \n ' . join ( PcdCommentList )
PcdEntry = Pcd . TokenSpaceGuidCName + ' . ' + TokenCName
if PcdComments :
PcdEntry = PcdComments + ' \n ' + PcdEntry
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' pcd_item ' ] . append ( PcdEntry )
2018-09-13 16:11:07 -07:00
for Item in self . BuildOption :
if ' FLAGS ' in self . BuildOption [ Item ] :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' flags_item ' ] . append ( ' %s : %s _ %s _ %s _ %s _FLAGS = %s ' % ( self . ToolChainFamily , self . BuildTarget , self . ToolChain , self . Arch , Item , self . BuildOption [ Item ] [ ' FLAGS ' ] . strip ( ) ) )
2018-09-13 16:11:07 -07:00
# Generated LibraryClasses section in comments.
for Library in self . LibraryAutoGenList :
2019-06-11 10:40:54 -07:00
AsBuiltInfDict [ ' libraryclasses_item ' ] . append ( Library . MetaFile . File . replace ( ' \\ ' , ' / ' ) )
2018-09-13 16:11:07 -07:00
# Generated UserExtensions TianoCore section.
# All tianocore user extensions are copied.
UserExtStr = ' '
for TianoCore in self . _GetTianoCoreUserExtensionList ( ) :
UserExtStr + = ' \n ' . join ( TianoCore )
ExtensionFile = os . path . join ( self . MetaFile . Dir , TianoCore [ 1 ] )
if os . path . isfile ( ExtensionFile ) :
shutil . copy2 ( ExtensionFile , self . OutputDir )
AsBuiltInfDict [ ' userextension_tianocore_item ' ] = UserExtStr
# Generated depex expression section in comments.
2019-06-11 10:40:54 -07:00
DepexExpression = self . _GetDepexExpresionString ( )
AsBuiltInfDict [ ' depexsection_item ' ] = DepexExpression if DepexExpression else ' '
2018-09-13 16:11:07 -07:00
AsBuiltInf = TemplateString ( )
AsBuiltInf . Append ( gAsBuiltInfHeaderString . Replace ( AsBuiltInfDict ) )
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
SaveFileOnChange ( os . path . join ( self . OutputDir , self . Name + ' .inf ' ) , str ( AsBuiltInf ) , False )
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
self . IsAsBuiltInfCreated = True
if GlobalData . gBinCacheDest :
self . CopyModuleToCache ( )
def CopyModuleToCache ( self ) :
2019-06-11 10:40:54 -07:00
FileDir = path . join ( GlobalData . gBinCacheDest , self . PlatformInfo . OutputDir , self . BuildTarget + " _ " + self . ToolChain , self . Arch , self . SourceDir , self . MetaFile . BaseName )
2018-09-13 16:11:07 -07:00
CreateDirectory ( FileDir )
HashFile = path . join ( self . BuildDir , self . Name + ' .hash ' )
if os . path . exists ( HashFile ) :
shutil . copy2 ( HashFile , FileDir )
2019-06-11 10:40:54 -07:00
if not self . IsLibrary :
ModuleFile = path . join ( self . OutputDir , self . Name + ' .inf ' )
if os . path . exists ( ModuleFile ) :
shutil . copy2 ( ModuleFile , FileDir )
else :
OutputDir = self . OutputDir . replace ( ' \\ ' , ' / ' ) . strip ( ' / ' )
DebugDir = self . DebugDir . replace ( ' \\ ' , ' / ' ) . strip ( ' / ' )
for Item in self . CodaTargetList :
File = Item . Target . Path . replace ( ' \\ ' , ' / ' ) . strip ( ' / ' ) . replace ( DebugDir , ' ' ) . replace ( OutputDir , ' ' ) . strip ( ' / ' )
self . OutputFile . add ( File )
2018-09-13 16:11:07 -07:00
if not self . OutputFile :
2019-06-11 10:40:54 -07:00
Ma = self . BuildDatabase [ self . MetaFile , self . Arch , self . BuildTarget , self . ToolChain ]
2018-09-13 16:11:07 -07:00
self . OutputFile = Ma . Binaries
if self . OutputFile :
for File in self . OutputFile :
File = str ( File )
if not os . path . isabs ( File ) :
File = os . path . join ( self . OutputDir , File )
if os . path . exists ( File ) :
2019-06-11 10:40:54 -07:00
sub_dir = os . path . relpath ( File , self . OutputDir )
destination_file = os . path . join ( FileDir , sub_dir )
destination_dir = os . path . dirname ( destination_file )
CreateDirectory ( destination_dir )
shutil . copy2 ( File , destination_dir )
2018-09-13 16:11:07 -07:00
def AttemptModuleCacheCopy ( self ) :
2019-06-11 10:40:54 -07:00
# If library or Module is binary do not skip by hash
2018-09-13 16:11:07 -07:00
if self . IsBinaryModule :
return False
2019-06-11 10:40:54 -07:00
# .inc is contains binary information so do not skip by hash as well
for f_ext in self . SourceFileList :
if ' .inc ' in str ( f_ext ) :
return False
FileDir = path . join ( GlobalData . gBinCacheSource , self . PlatformInfo . OutputDir , self . BuildTarget + " _ " + self . ToolChain , self . Arch , self . SourceDir , self . MetaFile . BaseName )
2018-09-13 16:11:07 -07:00
HashFile = path . join ( FileDir , self . Name + ' .hash ' )
if os . path . exists ( HashFile ) :
f = open ( HashFile , ' r ' )
CacheHash = f . read ( )
f . close ( )
2019-06-11 10:40:54 -07:00
self . GenModuleHash ( )
2018-09-13 16:11:07 -07:00
if GlobalData . gModuleHash [ self . Arch ] [ self . Name ] :
if CacheHash == GlobalData . gModuleHash [ self . Arch ] [ self . Name ] :
for root , dir , files in os . walk ( FileDir ) :
for f in files :
if self . Name + ' .hash ' in f :
2019-06-11 10:40:54 -07:00
shutil . copy ( HashFile , self . BuildDir )
2018-09-13 16:11:07 -07:00
else :
File = path . join ( root , f )
2019-06-11 10:40:54 -07:00
sub_dir = os . path . relpath ( File , FileDir )
destination_file = os . path . join ( self . OutputDir , sub_dir )
destination_dir = os . path . dirname ( destination_file )
CreateDirectory ( destination_dir )
shutil . copy ( File , destination_dir )
2018-09-13 16:11:07 -07:00
if self . Name == " PcdPeim " or self . Name == " PcdDxe " :
CreatePcdDatabaseCode ( self , TemplateString ( ) , TemplateString ( ) )
return True
return False
## Create makefile for the module and its dependent libraries
#
# @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
# dependent libraries will be created
#
2019-06-11 10:40:54 -07:00
@cached_class_function
2018-09-13 16:11:07 -07:00
def CreateMakeFile ( self , CreateLibraryMakeFile = True , GenFfsList = [ ] ) :
2019-06-11 10:40:54 -07:00
# nest this function inside it's only caller.
def CreateTimeStamp ( ) :
FileSet = { self . MetaFile . Path }
for SourceFile in self . Module . Sources :
FileSet . add ( SourceFile . Path )
for Lib in self . DependentLibraryList :
FileSet . add ( Lib . MetaFile . Path )
for f in self . AutoGenDepSet :
FileSet . add ( f . Path )
if os . path . exists ( self . TimeStampPath ) :
os . remove ( self . TimeStampPath )
with open ( self . TimeStampPath , ' w+ ' ) as file :
for f in FileSet :
print ( f , file = file )
2018-09-13 16:11:07 -07:00
# Ignore generating makefile when it is a binary module
if self . IsBinaryModule :
return
self . GenFfsList = GenFfsList
if not self . IsLibrary and CreateLibraryMakeFile :
for LibraryAutoGen in self . LibraryAutoGenList :
LibraryAutoGen . CreateMakeFile ( )
if self . CanSkip ( ) :
return
if len ( self . CustomMakefile ) == 0 :
Makefile = GenMake . ModuleMakefile ( self )
else :
Makefile = GenMake . CustomMakefile ( self )
if Makefile . Generate ( ) :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " Generated makefile for module %s [ %s ] " %
( self . Name , self . Arch ) )
else :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " Skipped the generation of makefile for module %s [ %s ] " %
( self . Name , self . Arch ) )
2019-06-11 10:40:54 -07:00
CreateTimeStamp ( )
2018-09-13 16:11:07 -07:00
def CopyBinaryFiles ( self ) :
for File in self . Module . Binaries :
SrcPath = File . Path
2019-06-11 10:40:54 -07:00
DstPath = os . path . join ( self . OutputDir , os . path . basename ( SrcPath ) )
2018-09-13 16:11:07 -07:00
CopyLongFilePath ( SrcPath , DstPath )
## Create autogen code for the module and its dependent libraries
#
# @param CreateLibraryCodeFile Flag indicating if or not the code of
# dependent libraries will be created
#
def CreateCodeFile ( self , CreateLibraryCodeFile = True ) :
if self . IsCodeFileCreated :
return
# Need to generate PcdDatabase even PcdDriver is binarymodule
if self . IsBinaryModule and self . PcdIsDriver != ' ' :
CreatePcdDatabaseCode ( self , TemplateString ( ) , TemplateString ( ) )
return
if self . IsBinaryModule :
if self . IsLibrary :
self . CopyBinaryFiles ( )
return
if not self . IsLibrary and CreateLibraryCodeFile :
for LibraryAutoGen in self . LibraryAutoGenList :
LibraryAutoGen . CreateCodeFile ( )
if self . CanSkip ( ) :
return
AutoGenList = [ ]
IgoredAutoGenList = [ ]
for File in self . AutoGenFileList :
if GenC . Generate ( File . Path , self . AutoGenFileList [ File ] , File . IsBinary ) :
AutoGenList . append ( str ( File ) )
else :
IgoredAutoGenList . append ( str ( File ) )
for ModuleType in self . DepexList :
2019-06-11 10:40:54 -07:00
# Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
if len ( self . DepexList [ ModuleType ] ) == 0 or ModuleType == SUP_MODULE_USER_DEFINED :
2018-09-13 16:11:07 -07:00
continue
Dpx = GenDepex . DependencyExpression ( self . DepexList [ ModuleType ] , ModuleType , True )
DpxFile = gAutoGenDepexFileName % { " module_name " : self . Name }
2019-06-11 10:40:54 -07:00
if len ( Dpx . PostfixNotation ) != 0 :
2018-09-13 16:11:07 -07:00
self . DepexGenerated = True
if Dpx . Generate ( path . join ( self . OutputDir , DpxFile ) ) :
AutoGenList . append ( str ( DpxFile ) )
else :
IgoredAutoGenList . append ( str ( DpxFile ) )
if IgoredAutoGenList == [ ] :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " Generated [ %s ] files for module %s [ %s ] " %
( " " . join ( AutoGenList ) , self . Name , self . Arch ) )
elif AutoGenList == [ ] :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " Skipped the generation of [ %s ] files for module %s [ %s ] " %
( " " . join ( IgoredAutoGenList ) , self . Name , self . Arch ) )
else :
EdkLogger . debug ( EdkLogger . DEBUG_9 , " Generated [ %s ] (skipped %s ) files for module %s [ %s ] " %
( " " . join ( AutoGenList ) , " " . join ( IgoredAutoGenList ) , self . Name , self . Arch ) )
self . IsCodeFileCreated = True
return AutoGenList
## Summarize the ModuleAutoGen objects of all libraries used by this module
2019-06-11 10:40:54 -07:00
@cached_property
def LibraryAutoGenList ( self ) :
RetVal = [ ]
for Library in self . DependentLibraryList :
La = ModuleAutoGen (
2018-09-13 16:11:07 -07:00
self . Workspace ,
Library . MetaFile ,
self . BuildTarget ,
self . ToolChain ,
self . Arch ,
self . PlatformInfo . MetaFile
)
2019-06-11 10:40:54 -07:00
if La not in RetVal :
RetVal . append ( La )
for Lib in La . CodaTargetList :
self . _ApplyBuildRule ( Lib . Target , TAB_UNKNOWN_FILE )
return RetVal
2018-09-13 16:11:07 -07:00
def GenModuleHash ( self ) :
2019-06-11 10:40:54 -07:00
# Initialize a dictionary for each arch type
2018-09-13 16:11:07 -07:00
if self . Arch not in GlobalData . gModuleHash :
GlobalData . gModuleHash [ self . Arch ] = { }
2019-06-11 10:40:54 -07:00
# Early exit if module or library has been hashed and is in memory
if self . Name in GlobalData . gModuleHash [ self . Arch ] :
return GlobalData . gModuleHash [ self . Arch ] [ self . Name ] . encode ( ' utf-8 ' )
# Initialze hash object
2018-09-13 16:11:07 -07:00
m = hashlib . md5 ( )
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
# Add Platform level hash
2019-06-11 10:40:54 -07:00
m . update ( GlobalData . gPlatformHash . encode ( ' utf-8 ' ) )
2018-09-13 16:11:07 -07:00
# Add Package level hash
if self . DependentPackageList :
2019-06-11 10:40:54 -07:00
for Pkg in sorted ( self . DependentPackageList , key = lambda x : x . PackageName ) :
if Pkg . PackageName in GlobalData . gPackageHash :
m . update ( GlobalData . gPackageHash [ Pkg . PackageName ] . encode ( ' utf-8 ' ) )
2018-09-13 16:11:07 -07:00
# Add Library hash
if self . LibraryAutoGenList :
2019-06-11 10:40:54 -07:00
for Lib in sorted ( self . LibraryAutoGenList , key = lambda x : x . Name ) :
2018-09-13 16:11:07 -07:00
if Lib . Name not in GlobalData . gModuleHash [ self . Arch ] :
Lib . GenModuleHash ( )
2019-06-11 10:40:54 -07:00
m . update ( GlobalData . gModuleHash [ self . Arch ] [ Lib . Name ] . encode ( ' utf-8 ' ) )
2018-09-13 16:11:07 -07:00
# Add Module self
2019-06-11 10:40:54 -07:00
f = open ( str ( self . MetaFile ) , ' rb ' )
2018-09-13 16:11:07 -07:00
Content = f . read ( )
f . close ( )
m . update ( Content )
2019-06-11 10:40:54 -07:00
2018-09-13 16:11:07 -07:00
# Add Module's source files
if self . SourceFileList :
2019-06-11 10:40:54 -07:00
for File in sorted ( self . SourceFileList , key = lambda x : str ( x ) ) :
f = open ( str ( File ) , ' rb ' )
2018-09-13 16:11:07 -07:00
Content = f . read ( )
f . close ( )
m . update ( Content )
2019-06-11 10:40:54 -07:00
GlobalData . gModuleHash [ self . Arch ] [ self . Name ] = m . hexdigest ( )
return GlobalData . gModuleHash [ self . Arch ] [ self . Name ] . encode ( ' utf-8 ' )
2018-09-13 16:11:07 -07:00
## Decide whether we can skip the ModuleAutoGen process
def CanSkipbyHash ( self ) :
2019-06-11 10:40:54 -07:00
# Hashing feature is off
if not GlobalData . gUseHashCache :
return False
# Initialize a dictionary for each arch type
if self . Arch not in GlobalData . gBuildHashSkipTracking :
GlobalData . gBuildHashSkipTracking [ self . Arch ] = dict ( )
# If library or Module is binary do not skip by hash
if self . IsBinaryModule :
return False
# .inc is contains binary information so do not skip by hash as well
for f_ext in self . SourceFileList :
if ' .inc ' in str ( f_ext ) :
return False
# Use Cache, if exists and if Module has a copy in cache
if GlobalData . gBinCacheSource and self . AttemptModuleCacheCopy ( ) :
return True
# Early exit for libraries that haven't yet finished building
HashFile = path . join ( self . BuildDir , self . Name + " .hash " )
if self . IsLibrary and not os . path . exists ( HashFile ) :
return False
# Return a Boolean based on if can skip by hash, either from memory or from IO.
if self . Name not in GlobalData . gBuildHashSkipTracking [ self . Arch ] :
# If hashes are the same, SaveFileOnChange() will return False.
GlobalData . gBuildHashSkipTracking [ self . Arch ] [ self . Name ] = not SaveFileOnChange ( HashFile , self . GenModuleHash ( ) , True )
return GlobalData . gBuildHashSkipTracking [ self . Arch ] [ self . Name ]
else :
return GlobalData . gBuildHashSkipTracking [ self . Arch ] [ self . Name ]
2018-09-13 16:11:07 -07:00
## Decide whether we can skip the ModuleAutoGen process
# If any source file is newer than the module than we cannot skip
#
def CanSkip ( self ) :
2019-06-11 10:40:54 -07:00
if self . MakeFileDir in GlobalData . gSikpAutoGenCache :
return True
if not os . path . exists ( self . TimeStampPath ) :
2018-09-13 16:11:07 -07:00
return False
#last creation time of the module
2019-06-11 10:40:54 -07:00
DstTimeStamp = os . stat ( self . TimeStampPath ) [ 8 ]
2018-09-13 16:11:07 -07:00
SrcTimeStamp = self . Workspace . _SrcTimeStamp
if SrcTimeStamp > DstTimeStamp :
return False
2019-06-11 10:40:54 -07:00
with open ( self . TimeStampPath , ' r ' ) as f :
2018-09-13 16:11:07 -07:00
for source in f :
source = source . rstrip ( ' \n ' )
if not os . path . exists ( source ) :
return False
if source not in ModuleAutoGen . TimeDict :
ModuleAutoGen . TimeDict [ source ] = os . stat ( source ) [ 8 ]
if ModuleAutoGen . TimeDict [ source ] > DstTimeStamp :
return False
2019-06-11 10:40:54 -07:00
GlobalData . gSikpAutoGenCache . add ( self . MakeFileDir )
2018-09-13 16:11:07 -07:00
return True
2019-06-11 10:40:54 -07:00
@cached_property
def TimeStampPath ( self ) :
return os . path . join ( self . MakeFileDir , ' AutoGenTimeStamp ' )