diff options
Diffstat (limited to 'BaseTools/Source/Python/AutoGen/AutoGen.py')
-rw-r--r-- | BaseTools/Source/Python/AutoGen/AutoGen.py | 4264 |
1 files changed, 46 insertions, 4218 deletions
diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py index bb0da46d74..d9ee699d8f 100644 --- a/BaseTools/Source/Python/AutoGen/AutoGen.py +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py @@ -12,222 +12,7 @@ #
from __future__ import print_function
from __future__ import absolute_import
-import Common.LongFilePathOs as os
-import re
-import os.path as path
-import copy
-import uuid
-
-from . import GenC
-from . import GenMake
-from . import GenDepex
-from io import BytesIO
-
-from .StrGather import *
-from .BuildEngine import BuildRuleObj as BuildRule
-from .BuildEngine import gDefaultBuildRuleFile,AutoGenReqBuildRuleVerNum
-import shutil
-from Common.LongFilePathSupport import CopyLongFilePath
-from Common.BuildToolError import *
-from Common.DataType import *
-from Common.Misc import *
-from Common.StringUtils import *
-import Common.GlobalData as GlobalData
-from GenFds.FdfParser import *
-from CommonDataClass.CommonClass import SkuInfoClass
-from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
-import Common.VpdInfoFile as VpdInfoFile
-from .GenPcdDb import CreatePcdDatabaseCode
-from Workspace.MetaFileCommentParser import UsageList
-from Workspace.WorkspaceCommon import GetModuleLibInstances
-from Common.MultipleWorkspace import MultipleWorkspace as mws
-from . import InfSectionParser
-import datetime
-import hashlib
-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
-
-## Regular expression for splitting Dependency Expression string into tokens
-gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
-
-## 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)
-
-#
-# 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
-gMakeTypeMap = {TAB_COMPILER_MSFT:"nmake", "GCC":"gmake"}
-
-
-## default file name for AutoGen
-gAutoGenCodeFileName = "AutoGen.c"
-gAutoGenHeaderFileName = "AutoGen.h"
-gAutoGenStringFileName = "%(module_name)sStrDefs.h"
-gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
-gAutoGenDepexFileName = "%(module_name)s.depex"
-gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"
-gAutoGenIdfFileName = "%(module_name)sIdf.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}
-""")
-## 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
-
+from Common.DataType import TAB_STAR
## Base class for AutoGen
#
# This class just implements the cache mechanism of AutoGen objects.
@@ -248,6 +33,7 @@ class AutoGen(object): # @param *args The specific class related parameters
# @param **kwargs The specific class related dict parameters
#
+
def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
# check if the object has been created
Key = (Target, Toolchain, Arch, MetaFile)
@@ -281,4005 +67,47 @@ class AutoGen(object): 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):
- # 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
- #
- # @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
- #
- def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
- 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
- self.Platform = self.BuildDatabase[self.MetaFile, TAB_ARCH_COMMON, Target, Toolchain]
- 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
- self.FdTargetList = Fds if Fds else []
- self.FvTargetList = Fvs if Fvs else []
- self.CapTargetList = Caps if Caps else []
- self.AutoGenObjectList = []
- self._GuidDict = {}
-
- # there's many relative directory operations, so ...
- os.chdir(self.WorkspaceDir)
-
- self.MergeArch()
- self.ValidateBuildTarget()
-
- 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("\nFLASH_DEFINITION = %s" % self.FdfFile)
-
- if Progress:
- Progress.Start("\nProcessing meta-data")
- #
- # Mark now build in AutoGen Phase
- #
- GlobalData.gAutoGenPhase = True
- self.ProcessModuleFromPdf()
- self.ProcessPcdType()
- self.ProcessMixedPcd()
- self.GetPcdsFromFDF()
- self.CollectAllPcds()
- self.GeneratePkgLevelHash()
- #
- # Check PCDs token value conflict in each DEC file.
- #
- self._CheckAllPcdsTokenValueConflict()
- #
- # Check PCD type and definition between DSC and DEC
- #
- self._CheckPcdDefineAndType()
-
- self.CreateBuildOptionsFile()
- self.CreatePcdTokenNumberFile()
- self.CreateModuleHashInfo()
- GlobalData.gAutoGenPhase = False
-
- #
- # Merge Arch
- #
- def MergeArch(self):
- 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("\nArch [%s] is ignored because the platform supports [%s] only!"
- % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
- self.ArchList = tuple(ArchList)
-
- # Validate build target
- def ValidateBuildTarget(self):
- 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)))
- @cached_property
- def FdfProfile(self):
- if not self.FdfFile:
- self.FdfFile = self.Platform.FlashDefinition
-
- FdfProfile = None
- if self.FdfFile:
- Fdf = FdfParser(self.FdfFile.Path)
- Fdf.ParseFile()
- GlobalData.gFdfParser = Fdf
- 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))
- FdfProfile = Fdf.Profile
- else:
- 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 = []
-
- return FdfProfile
-
- def ProcessModuleFromPdf(self):
-
- if self.FdfProfile:
- 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':
- MetaFile_cache = defaultdict(set)
- for Arch in self.ArchList:
- Current_Platform_cache = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
- for Pkey in Current_Platform_cache.Modules:
- MetaFile_cache[Arch].add(Current_Platform_cache.Modules[Pkey].MetaFile)
- 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, self.BuildTarget, self.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, self.BuildTarget, self.ToolChain]
- MetaFileList = set()
- for Pkey in Platform.Modules:
- MetaFileList.add(Platform.Modules[Pkey].MetaFile)
- for Inf in self.FdfProfile.InfDict[key]:
- ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
- if ModuleFile in MetaFileList:
- continue
- ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
- if not ModuleData.IsBinaryModule:
- EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
-
-
-
- # parse FDF file to get PCDs in it, if any
- def GetPcdsFromFDF(self):
-
- if self.FdfProfile:
- PcdSet = self.FdfProfile.PcdDict
- # 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
- self.VerifyPcdDeclearation(PcdSet)
-
- def ProcessPcdType(self):
- for Arch in self.ArchList:
- Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
- Platform.Pcds
- # generate the SourcePcdDict and BinaryPcdDict
- PGen = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
- for BuildData in list(PGen.BuildDatabase._CACHE_.values()):
- 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]
- if PcdInPlatform.Type:
- BuildData.Pcds[key].Type = PcdInPlatform.Type
- BuildData.Pcds[key].Pending = False
-
- if BuildData.MetaFile in Platform.Modules:
- PlatformModule = Platform.Modules[str(BuildData.MetaFile)]
- if key in PlatformModule.Pcds:
- PcdInPlatform = PlatformModule.Pcds[key]
- if PcdInPlatform.Type:
- BuildData.Pcds[key].Type = PcdInPlatform.Type
- BuildData.Pcds[key].Pending = False
- else:
- #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
- if BuildData.Pcds[key].Pending:
- MGen = ModuleAutoGen(self, BuildData.MetaFile, self.BuildTarget, self.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
-
- def ProcessMixedPcd(self):
- for Arch in self.ArchList:
- 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()}
- SourcePcdDict_Keys = SourcePcdDict.keys()
- BinaryPcdDict_Keys = BinaryPcdDict.keys()
-
- # generate the SourcePcdDict and BinaryPcdDict
- PGen = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
- for BuildData in list(PGen.BuildDatabase._CACHE_.values()):
- if BuildData.Arch != Arch:
- continue
- if BuildData.MetaFile.Ext == '.inf':
- for key in BuildData.Pcds:
- 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:
- if BuildData.MetaFile.Ext == '.inf':
- if BuildData.IsBinaryModule:
- BinaryPcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
- else:
- SourcePcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
-
- 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))
-
- #
- # A PCD can only use one type for all source modules
- #
- for i in SourcePcdDict_Keys:
- for j in SourcePcdDict_Keys:
- if i != j:
- Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])
- if len(Intersections) > 0:
- 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),
- ExtraData='\n\t'.join(str(P[1]+'.'+P[0]) for P in Intersections)
- )
-
- #
- # intersection the BinaryPCD for Mixed PCD
- #
- for i in BinaryPcdDict_Keys:
- for j in BinaryPcdDict_Keys:
- if i != j:
- Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])
- for item in Intersections:
- 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:
- Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])
- for item in Intersections:
- 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)
-
- for BuildData in list(PGen.BuildDatabase._CACHE_.values()):
- 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]
- 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):
- 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
-
- #Collect package set information from INF of FDF
- @cached_property
- def PkgSet(self):
- if not self.FdfFile:
- self.FdfFile = self.Platform.FlashDefinition
-
- if self.FdfFile:
- ModuleList = self.FdfProfile.InfList
- else:
- ModuleList = []
- Pkgs = {}
- for Arch in self.ArchList:
- Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
- PGen = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
- PkgSet = set()
- for Inf in ModuleList:
- ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
- if ModuleFile in Platform.Modules:
- continue
- ModuleData = self.BuildDatabase[ModuleFile, Arch, self.BuildTarget, self.ToolChain]
- PkgSet.update(ModuleData.Packages)
- Pkgs[Arch] = list(PkgSet) + list(PGen.PackageList)
- return Pkgs
-
- def VerifyPcdDeclearation(self,PcdSet):
- for Arch in self.ArchList:
- Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
- Pkgs = self.PkgSet[Arch]
- DecPcds = set()
- DecPcdsKey = set()
- for Pkg in Pkgs:
- for Pcd in Pkg.Pcds:
- DecPcds.add((Pcd[0], Pcd[1]))
- DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))
-
- Platform.SkuName = self.SkuId
- for Name, Guid,Fileds in PcdSet:
- 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),
- File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
- Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
- )
- 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),
- File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
- Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
- )
- def CollectAllPcds(self):
-
- for Arch in self.ArchList:
- Pa = PlatformAutoGen(self, self.MetaFile, self.BuildTarget, self.ToolChain, Arch)
- #
- # Explicitly collect platform's dynamic PCDs
- #
- Pa.CollectPlatformDynamicPcds()
- Pa.CollectFixedAtBuildPcds()
- self.AutoGenObjectList.append(Pa)
-
- #
- # Generate Package level hash value
- #
- def GeneratePkgLevelHash(self):
- for Arch in self.ArchList:
- GlobalData.gPackageHash = {}
- if GlobalData.gUseHashCache:
- for Pkg in self.PkgSet[Arch]:
- self._GenPkgLevelHash(Pkg)
-
-
- def CreateBuildOptionsFile(self):
- #
- # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
- #
- content = 'gCommandLineDefines: '
- content += str(GlobalData.gCommandLineDefines)
- content += TAB_LINE_BREAK
- content += 'BuildOptionPcd: '
- content += str(GlobalData.BuildOptionPcd)
- content += TAB_LINE_BREAK
- content += 'Active Platform: '
- content += str(self.Platform)
- content += TAB_LINE_BREAK
- if self.FdfFile:
- content += 'Flash Image Definition: '
- content += str(self.FdfFile)
- content += TAB_LINE_BREAK
- SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)
-
- def CreatePcdTokenNumberFile(self):
- #
- # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
- #
- PcdTokenNumber = 'PcdTokenNumber: '
- Pa = self.AutoGenObjectList[0]
- if Pa.PcdTokenNumber:
- if Pa.DynamicPcdList:
- for Pcd in Pa.DynamicPcdList:
- PcdTokenNumber += TAB_LINE_BREAK
- PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
- PcdTokenNumber += ' : '
- PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])
- SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)
-
- def CreateModuleHashInfo(self):
- #
- # Get set of workspace metafiles
- #
- AllWorkSpaceMetaFiles = self._GetMetaFiles(self.BuildTarget, self.ToolChain)
-
- #
- # 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
- f = open(files, 'rb')
- Content = f.read()
- f.close()
- m.update(Content)
- SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False)
- 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:
- print(f, file=file)
- return True
-
- def _GenPkgLevelHash(self, Pkg):
- if Pkg.PackageName in GlobalData.gPackageHash:
- return
-
- 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
- f = open(Pkg.MetaFile.Path, 'rb')
- Content = f.read()
- f.close()
- m.update(Content)
- # Get include files hash value
- if Pkg.Includes:
- for inc in sorted(Pkg.Includes, key=lambda x: str(x)):
- for Root, Dirs, Files in os.walk(str(inc)):
- for File in sorted(Files):
- File_Path = os.path.join(Root, File)
- f = open(File_Path, 'rb')
- Content = f.read()
- f.close()
- m.update(Content)
- SaveFileOnChange(HashFile, m.hexdigest(), False)
- GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest()
-
- def _GetMetaFiles(self, Target, Toolchain):
- AllWorkSpaceMetaFiles = set()
- #
- # add fdf
- #
- if self.FdfFile:
- AllWorkSpaceMetaFiles.add (self.FdfFile.Path)
- for f in GlobalData.gFdfParser.GetAllIncludedFile():
- AllWorkSpaceMetaFiles.add (f.FileName)
- #
- # 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 Pa in self.AutoGenObjectList:
- AllWorkSpaceMetaFiles.add(Pa.ToolDefinitionFile)
-
- for Arch in self.ArchList:
- #
- # add dec
- #
- for Package in PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch).PackageList:
- AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)
-
- #
- # add included dsc
- #
- for filePath in self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]._RawData.IncludedFiles:
- AllWorkSpaceMetaFiles.add(filePath.Path)
-
- return AllWorkSpaceMetaFiles
-
- def _CheckPcdDefineAndType(self):
- PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,
- TAB_PCDS_PATCHABLE_IN_MODULE,
- TAB_PCDS_FEATURE_FLAG,
- TAB_PCDS_DYNAMIC,
- TAB_PCDS_DYNAMIC_EX}
-
- # This dict store PCDs which are not used by any modules with specified arches
- UnusedPcd = OrderedDict()
- 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
-
- # If no PCD type, this PCD comes from FDF
- if not PcdType:
- continue
-
- # Try to remove Hii and Vpd suffix
- if PcdType.startswith(TAB_PCDS_DYNAMIC_EX):
- PcdType = TAB_PCDS_DYNAMIC_EX
- elif PcdType.startswith(TAB_PCDS_DYNAMIC):
- PcdType = TAB_PCDS_DYNAMIC
-
- 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
- for Type in PcdTypeSet:
- 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"
- "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %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
- @cached_property
- def FvDir(self):
- return path.join(self.BuildDir, TAB_FV_DIRECTORY)
-
- ## Return the directory to store all intermediate and final files built
- @cached_property
- def BuildDir(self):
- return self.AutoGenObjectList[0].BuildDir
-
- ## Return the build output directory platform specifies
- @cached_property
- def OutputDir(self):
- return self.Platform.OutputDirectory
-
- ## Return platform name
- @cached_property
- def Name(self):
- return self.Platform.PlatformName
-
- ## Return meta-file GUID
- @cached_property
- def Guid(self):
- return self.Platform.Guid
-
- ## Return platform version
- @cached_property
- def Version(self):
- return self.Platform.Version
-
- ## Return paths of tools
- @cached_property
- def ToolDefinition(self):
- return self.AutoGenObjectList[0].ToolDefinition
-
- ## Return directory of platform makefile
- #
- # @retval string Makefile directory
- #
- @cached_property
- def MakeFileDir(self):
- return self.BuildDir
-
- ## Return build command string
- #
- # @retval string Build command string
- #
- @cached_property
- def BuildCommand(self):
- # BuildCommand should be all the same. So just get one from platform AutoGen
- return self.AutoGenObjectList[0].BuildCommand
-
- ## Check the PCDs token value conflict in each DEC file.
- #
- # Will cause build break and raise error message while two PCDs conflict.
- #
- # @return None
- #
- def _CheckAllPcdsTokenValueConflict(self):
- for Pa in self.AutoGenObjectList:
- for Package in Pa.PackageList:
- PcdList = list(Package.Pcds.values())
- PcdList.sort(key=lambda x: int(x.TokenValue, 0))
- 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
- #
- SameTokenValuePcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
- 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
-
- PcdList = list(Package.Pcds.values())
- PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
- 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
- @property
- def GenFdsCommand(self):
- return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
-
- @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
-
- ## 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):
- if not CreateDepsMakeFile:
- return
- for Pa in self.AutoGenObjectList:
- Pa.CreateMakeFile(True)
-
- ## 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:
- Pa.CreateCodeFile(True)
-
- ## 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):
- # 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
- #
- # Used to store all PCDs for both PEI and DXE phase, in order to generate
- # correct PCD database
- #
- _DynaPcdList_ = []
- _NonDynaPcdList_ = []
- _PlatformPcds = {}
-
- #
- # The priority list while override build option
- #
- PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
- "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
- "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
- "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
- "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)
-
- ## Initialize PlatformAutoGen
- #
- #
- # @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
- #
- def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):
- 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
-
- if GlobalData.gFdfParser is not None:
- 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]
- if not M.IsBinaryModule:
- continue
- self._AsBuildModuleList.append(InfClass)
- # get library/modules for build
- self.LibraryBuildDirectoryList = []
- self.ModuleBuildDirectoryList = []
-
- return True
-
- ## hash() operator of PlatformAutoGen
- #
- # The platform file path and arch string will be used to represent
- # hash value of this object
- #
- # @retval int Hash value of the platform file path and arch
- #
- @cached_class_function
- def __hash__(self):
- return hash((self.MetaFile, self.Arch))
-
- @cached_class_function
- 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
- #
- @cached_class_function
- def CreateCodeFile(self, CreateModuleCodeFile=False):
- # only module has code to be created, so do nothing if CreateModuleCodeFile is False
- if not CreateModuleCodeFile:
- return
-
- for Ma in self.ModuleAutoGenList:
- Ma.CreateCodeFile(True)
-
- ## Generate Fds Command
- @cached_property
- def GenFdsCommand(self):
- return self.Workspace.GenFdsCommand
-
- ## Create makefile for the platform and modules in it
- #
- # @param CreateModuleMakeFile Flag indicating if the makefile for
- # modules will be created as well
- #
- def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):
- if CreateModuleMakeFile:
- for Ma in self._MaList:
- key = (Ma.MetaFile.File, self.Arch)
- if key in FfsCommand:
- Ma.CreateMakeFile(True, FfsCommand[key])
- 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
-
- @property
- def AllPcdList(self):
- return self.DynamicPcdList + self.NonDynamicPcdList
- ## Deal with Shared FixedAtBuild Pcds
- #
- def CollectFixedAtBuildPcds(self):
- for LibAuto in self.LibraryAutoGenList:
- 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))
- if key not in FixedAtBuildPcds:
- ShareFixedAtBuildPcdsSameValue[key] = True
- FixedAtBuildPcds[key] = DefaultValue
- else:
- if FixedAtBuildPcds[key] != DefaultValue:
- ShareFixedAtBuildPcdsSameValue[key] = False
- for Pcd in LibAuto.FixedAtBuildPcds:
- key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
- if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
- continue
- else:
- DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]
- if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:
- continue
- if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
- LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]
-
- 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
-
- VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)
- VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
- VariableInfo.SetVpdRegionOffset(VpdRegionBase)
- Index = 0
- for Pcd in DynamicPcdSet:
- pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
- for SkuName in Pcd.SkuInfoList:
- Sku = Pcd.SkuInfoList[SkuName]
- SkuId = Sku.SkuId
- if SkuId is None or SkuId == '':
- continue
- if len(Sku.VariableName) > 0:
- if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:
- continue
- VariableGuidStructure = Sku.VariableGuidValue
- VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)
- for StorageName in Sku.DefaultStoreDict:
- 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)))
- Index += 1
- return VariableInfo
-
- def UpdateNVStoreMaxSize(self, OrgVpdFile):
- if self.VariableInfo:
- VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
- 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])
- NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'
- else:
- EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
-
- NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)
- default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
- 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()
- PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj
- 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]
- 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):
- 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))
- for M in self._MaList:
-# F is the Module for which M is the module autogen
- for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:
- # make sure that the "VOID*" kind of datum has MaxDatumSize set
- if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
- NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))
-
- # Check the PCD from Binary INF or Source INF
- if M.IsBinaryModule == True:
- PcdFromModule.IsFromBinaryInf = True
-
- # 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
- # PCD as PcdsDynamic), then build tool will report warning message
- # 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
- # modules that are included in the FDF file.
- if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \
- PcdFromModule.IsFromBinaryInf == False:
- # Print warning message to let the developer make a determine.
- continue
- # 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
- # PCD to the Platform's PCD Database.
- if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
- 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
- #
- if M.ModuleType in SUP_MODULE_SET_PEI:
- 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)
- 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
- for InfName in FdfModuleList:
- if InfName not in DscModuleSet:
- InfClass = PathClass(InfName)
- M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
- # 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:
- 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
- if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
- EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
- File=self.MetaFile,
- ExtraData="\n\tExisted %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
- if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
- NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
- if M.ModuleType in SUP_MODULE_SET_PEI:
- PcdFromModule.Phase = "PEI"
- if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
- self._DynaPcdList_.append(PcdFromModule)
- elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
- self._NonDynaPcdList_.append(PcdFromModule)
- if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
- # Overwrite the phase of any the same PCD existing, if Phase is PEI.
- # It is to solve the case that a dynamic PCD used by a PEM module/PEI
- # module & DXE module at a same time.
- # Overwrite the type of the PCDs in source INF by the type of AsBuild
- # INF file as DynamicEx.
- Index = self._DynaPcdList_.index(PcdFromModule)
- self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
- self._DynaPcdList_[Index].Type = PcdFromModule.Type
- for PcdFromModule in self._NonDynaPcdList_:
- # 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]
- # section, then the tools must NOT add the PCD to the Platform's PCD
- # Database; the build must assign the access method for this PCD as
- # 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\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
- % NoDatumTypePcdListString)
- self._NonDynamicPcdList = self._NonDynaPcdList_
- self._DynamicPcdList = self._DynaPcdList_
- #
- # Sort dynamic PCD list to:
- # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
- # 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
-
- for pcd in self.Platform.Pcds:
- if pcd not in self._PlatformPcds:
- 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"]:
- self._PlatformPcds[item].DatumType = TAB_VOID
-
- if (self.Workspace.ArchList[-1] == self.Arch):
- for Pcd in self._DynamicPcdList:
- # just pick the a value to determine whether is unicode string type
- Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
- Sku.VpdOffset = Sku.VpdOffset.strip()
-
- if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
- Pcd.DatumType = TAB_VOID
-
- # 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
- PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
- if PcdNvStoreDfBuffer:
- self.VariableInfo = self.CollectVariables(self._DynamicPcdList)
- vardump = self.VariableInfo.dump()
- if vardump:
- #
- #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(","))))
- PcdNvStoreDfBuffer.DefaultValue = vardump
- for skuname in PcdNvStoreDfBuffer.SkuInfoList:
- PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump
- PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))
- 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())
- #
- # 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 = {}
- DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)
- if DefaultSku:
- PcdValue = DefaultSku.DefaultValue
- if PcdValue not in SkuValueMap:
- SkuValueMap[PcdValue] = []
- VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)
- SkuValueMap[PcdValue].append(DefaultSku)
-
- for (SkuName, Sku) in Pcd.SkuInfoList.items():
- Sku.VpdOffset = Sku.VpdOffset.strip()
- PcdValue = Sku.DefaultValue
- if PcdValue == "":
- PcdValue = Pcd.DefaultValue
- if Sku.VpdOffset != TAB_STAR:
- 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] = []
- VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)
- SkuValueMap[PcdValue].append(Sku)
- # if the offset of a VPD is *, then it need to be fixed up by third party tool.
- if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
- NeedProcessVpdMapFile = True
- if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':
- 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.
- #
- for DscPcd in PlatformPcds:
- DscPcdEntry = self._PlatformPcds[DscPcd]
- if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
- if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):
- FoundFlag = False
- for VpdPcd in VpdFile._VpdArray:
- # 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 = {}
- SkuObjList = list(DscPcdEntry.SkuInfoList.items())
- DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)
- if DefaultSku:
- defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))
- SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]
- for (SkuName, Sku) in SkuObjList:
- Sku.VpdOffset = Sku.VpdOffset.strip()
-
- # 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." \
- %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
-
- 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.
- if not Sku.DefaultValue:
- DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue
-
- if DscPcdEntry not in self._DynamicPcdList:
- self._DynamicPcdList.append(DscPcdEntry)
- Sku.VpdOffset = Sku.VpdOffset.strip()
- PcdValue = Sku.DefaultValue
- if PcdValue == "":
- PcdValue = DscPcdEntry.DefaultValue
- if Sku.VpdOffset != TAB_STAR:
- 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] = []
- VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)
- SkuValueMap[PcdValue].append(Sku)
- if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
- NeedProcessVpdMapFile = True
- if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):
- 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
- if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \
- VpdFile.GetCount() != 0:
- EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
- "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))
- 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() ]}
-
- # Process VPD map file generated by third party BPDG tool
- if NeedProcessVpdMapFile:
- VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
- if os.path.exists(VpdMapFilePath):
- VpdFile.Read(VpdMapFilePath)
-
- # Fixup TAB_STAR offset
- 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
- Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
- Sku.VpdOffset = Sku.VpdOffset.strip()
-
- if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
- Pcd.DatumType = TAB_VOID
-
- PcdValue = Sku.DefaultValue
- if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):
- # 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))
- allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]
- for pcd in self._DynamicPcdList:
- if len(pcd.SkuInfoList) == 1:
- for (SkuName, SkuId) in allskuset:
- if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:
- continue
- pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])
- pcd.SkuInfoList[SkuName].SkuId = SkuId
- pcd.SkuInfoList[SkuName].SkuIdName = SkuName
-
- def FixVpdOffset(self, VpdFile ):
- FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)
- 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():
- if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:
- if "PATH" not in ToolDef:
- 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.
- if BPDGToolName is not None:
- 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
- @cached_property
- def Platform(self):
- return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
-
- ## Return platform name
- @cached_property
- def Name(self):
- return self.Platform.PlatformName
-
- ## Return the meta file GUID
- @cached_property
- def Guid(self):
- return self.Platform.Guid
-
- ## Return the platform version
- @cached_property
- def Version(self):
- return self.Platform.Version
-
- ## Return the FDF file name
- @cached_property
- def FdfFile(self):
- if self.Workspace.FdfFile:
- RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
- else:
- RetVal = ''
- return RetVal
-
- ## Return the build output directory platform specifies
- @cached_property
- def OutputDir(self):
- return self.Platform.OutputDirectory
-
- ## Return the directory to store all intermediate and final files built
- @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
-
- ## Return directory of platform makefile
- #
- # @retval string Makefile directory
- #
- @cached_property
- def MakeFileDir(self):
- return path.join(self.BuildDir, self.Arch)
-
- ## Return build command string
- #
- # @retval string Build command string
- #
- @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
-
- ## Get tool chain definition
- #
- # Get each tool definition for given tool chain from tools_def.txt and platform
- #
- @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 = OrderedDict()
- 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
-
- Value = ToolDefinition[Def]
- # don't record the DLL
- if Attr == "DLL":
- DllPathList.add(Value)
- continue
-
- if Tool not in RetVal:
- RetVal[Tool] = OrderedDict()
- RetVal[Tool][Attr] = Value
-
- 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]
- else:
- Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
-
- 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"
- tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
- SaveFileOnChange(tool_def_file, ToolsDef, False)
- for DllPath in DllPathList:
- os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
- os.environ["MAKE_FLAGS"] = MakeFlags
-
- return RetVal
-
- ## Return the paths of tools
- @cached_property
- def ToolDefinitionFile(self):
- tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
- if not os.path.exists(tool_def_file):
- self.ToolDefinition
- return tool_def_file
-
- ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
- @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
-
- @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]
-
- ## Return the build options specific for all modules in this platform
- @cached_property
- def BuildOption(self):
- return self._ExpandBuildOption(self.Platform.BuildOptions)
-
- def _BuildOptionWithToolDef(self, ToolDef):
- return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)
-
- ## Return the build options specific for EDK modules in this platform
- @cached_property
- def EdkBuildOption(self):
- return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
-
- ## Return the build options specific for EDKII modules in this platform
- @cached_property
- def EdkIIBuildOption(self):
- return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
-
- ## Summarize the packages used by modules in this platform
- @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)
-
- @cached_property
- def NonDynamicPcdDict(self):
- return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}
-
- ## Get list of non-dynamic PCDs
- @property
- def NonDynamicPcdList(self):
- if not self._NonDynamicPcdList:
- self.CollectPlatformDynamicPcds()
- return self._NonDynamicPcdList
-
- ## Get list of dynamic PCDs
- @property
- def DynamicPcdList(self):
- if not self._DynamicPcdList:
- self.CollectPlatformDynamicPcds()
- return self._DynamicPcdList
-
- ## Generate Token Number for all PCD
- @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
- TokenNumber += 1
-
- 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):
- for ModuleFile in self.Platform.Modules:
- Ma = ModuleAutoGen(
- 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()]
-
- ## Summarize ModuleAutoGen objects of all modules to be built for this platform
- @cached_property
- def ModuleAutoGenList(self):
- RetVal = []
- for Ma in self._MaList:
- if Ma not in RetVal:
- RetVal.append(Ma)
- return RetVal
-
- ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
- @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
-
- ## 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 []
-
- return GetModuleLibInstances(Module,
- self.Platform,
- self.BuildDatabase,
- self.Arch,
- self.BuildTarget,
- self.ToolChain,
- self.MetaFile,
- EdkLogger)
-
- ## Override PCD setting (type, value, ...)
- #
- # @param ToPcd The PCD to be overridden
- # @param FromPcd The PCD overriding from
- #
- def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):
- #
- # 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
- if FromPcd is not None:
- if ToPcd.Pending and FromPcd.Type:
- ToPcd.Type = FromPcd.Type
- 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:
- ToPcd.Type = FromPcd.Type
- elif ToPcd.Type and FromPcd.Type \
- and ToPcd.Type != FromPcd.Type:
- if Library:
- Module = str(Module) + " 's library file (" + str(Library) + ")"
- EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
- ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
- % (ToPcd.TokenSpaceGuidCName, TokenCName,
- ToPcd.Type, Module, FromPcd.Type, Msg),
- File=self.MetaFile)
-
- if FromPcd.MaxDatumSize:
- ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
- ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize
- if FromPcd.DefaultValue:
- ToPcd.DefaultValue = FromPcd.DefaultValue
- if FromPcd.TokenValue:
- ToPcd.TokenValue = FromPcd.TokenValue
- if FromPcd.DatumType:
- ToPcd.DatumType = FromPcd.DatumType
- if FromPcd.SkuInfoList:
- ToPcd.SkuInfoList = FromPcd.SkuInfoList
- if FromPcd.UserDefinedDefaultStoresFlag:
- ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag
- # Add Flexible PCD format parse
- if ToPcd.DefaultValue:
- try:
- ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Workspace._GuidDict)(True)
- except BadExpression as Value:
- 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
- ToPcd.CustomAttribute = FromPcd.CustomAttribute
-
- if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:
- EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
- % (ToPcd.TokenSpaceGuidCName, TokenCName))
- Value = ToPcd.DefaultValue
- if not Value:
- 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
- if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \
- and not ToPcd.SkuInfoList:
- if self.Platform.SkuName in self.Platform.SkuIds:
- SkuName = self.Platform.SkuName
- else:
- SkuName = TAB_DEFAULT
- ToPcd.SkuInfoList = {
- SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
- }
-
- ## Apply PCD setting defined platform to a module
- #
- # @param Module The module from which the PCD setting will be overridden
- #
- # @retval PCD_list The list PCDs with settings from platform
- #
- def ApplyPcdSetting(self, Module, Pcds, Library=""):
- # 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
- self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)
- # 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)
- if Sku.VariableGuidValue is None:
- PackageList = "\n\t".join(str(P) for P in self.PackageList)
- 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:
- 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
- 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:
- self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
- # use PCD value to calculate the MaxDatumSize when it is not specified
- for Name, Guid in Pcds:
- Pcd = Pcds[Name, Guid]
- if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:
- Pcd.MaxSizeUserSet = None
- Value = Pcd.DefaultValue
- if not Value:
- 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)
- return list(Pcds.values())
-
-
-
- ## 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
- if Target == TAB_STAR:
- PriorityValue &= 0x01111
- if ToolChain == TAB_STAR:
- PriorityValue &= 0x10111
- if Arch == TAB_STAR:
- PriorityValue &= 0x11011
- if CommandType == TAB_STAR:
- PriorityValue &= 0x11101
- if Attr == TAB_STAR:
- PriorityValue &= 0x11110
-
- return self.PrioList["0x%0.5x" % PriorityValue]
-
-
- ## Expand * in build option key
- #
- # @param Options Options to be expanded
- # @param ToolDef Use specified ToolDef instead of full version.
- # This is needed during initialization to prevent
- # infinite recursion betweeh BuildOptions,
- # ToolDefinition, and this function.
- #
- # @retval options Options expanded
- #
- def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):
- if not ToolDef:
- ToolDef = self.ToolDefinition
- 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
- (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
- Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
- 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]
-
- #
- # Use the highest priority value.
- #
- if (len(OverrideList) >= 2):
- KeyList = list(OverrideList.keys())
- 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
- #
- Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
- 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))
-
- for Key in Options:
- if ModuleStyle is not None and len (Key) > 2:
- # 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
- if Tool in ToolDef and Family != "":
- FamilyIsNull = False
- if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
- if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
- continue
- elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
- continue
- FamilyMatch = True
- # expand any wildcard
- if Target == TAB_STAR or Target == self.BuildTarget:
- if Tag == TAB_STAR or Tag == self.ToolChain:
- if Arch == TAB_STAR or Arch == self.Arch:
- 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:
- if ModuleStyle is not None and len (Key) > 2:
- # 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
- if Tool not in ToolDef or Family == "":
- continue
- # option has been added before
- if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
- continue
-
- # expand any wildcard
- if Target == TAB_STAR or Target == self.BuildTarget:
- if Tag == TAB_STAR or Tag == self.ToolChain:
- if Arch == TAB_STAR or Arch == self.Arch:
- 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
- def GetGlobalBuildOptions(self,Module):
- ModuleTypeOptions = self.Platform.GetBuildOptionsByPkg(Module, Module.ModuleType)
- ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
- if Module in self.Platform.Modules:
- PlatformModule = self.Platform.Modules[str(Module)]
- PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
- else:
- PlatformModuleOptions = {}
- return ModuleTypeOptions, PlatformModuleOptions
- ## Append build options in platform to a module
- #
- # @param Module The module to which the build options will be appended
- #
- # @retval options The options appended with build options in platform
- #
- def ApplyBuildOption(self, Module):
- # Get the different options for the different style module
- PlatformOptions = self.EdkIIBuildOption
- ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
- 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]
-
- AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +
- list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +
- list(self.ToolDefinition.keys()))
- BuildOptions = defaultdict(lambda: defaultdict(str))
- 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
- Value = Options[Tool][Attr]
- # check if override is indicated
- if Value.startswith('='):
- BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
- else:
- if Attr != 'PATH':
- BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
- else:
- BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
-
- return BuildOptions, BuildRuleOrder
-
-#
-# 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])
-
-# 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
-
-## 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):
- # 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
- #
- TimeDict = {}
-
- 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
- #
- # @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
- #
- def _InitWorker(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
- 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
-
- self._PcdComments = OrderedListDict()
- self._GuidComments = OrderedListDict()
- self._ProtocolComments = OrderedListDict()
- self._PpiComments = OrderedListDict()
- self._BuildTargets = None
- self._IntroBuildTargetList = None
- self._FinalBuildTargetList = None
- self._FileTypes = None
-
- self.AutoGenDepSet = set()
- self.ReferenceModules = []
- self.ConstPcd = {}
-
- ## hash() operator of ModuleAutoGen
- #
- # The module file path and arch string will be used to represent
- # hash value of this object
- #
- # @retval int Hash value of the module file path and arch
- #
- @cached_class_function
- def __hash__(self):
- return hash((self.MetaFile, self.Arch))
-
- def __repr__(self):
- return "%s [%s]" % (self.MetaFile, self.Arch)
-
- # Get FixedAtBuild Pcds of this Module
- @cached_property
- def FixedAtBuildPcds(self):
- RetVal = []
- for Pcd in self.ModulePcdList:
- if Pcd.Type != TAB_PCDS_FIXED_AT_BUILD:
- continue
- if Pcd not in RetVal:
- RetVal.append(Pcd)
- return RetVal
-
- @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):
- 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)
- @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)
- ))
-
- ## Return the module build data object
- @cached_property
- def Module(self):
- return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
-
- ## Return the module name
- @cached_property
- def Name(self):
- return self.Module.BaseName
-
- ## Return the module DxsFile if exist
- @cached_property
- def DxsFile(self):
- return self.Module.DxsFile
-
- ## Return the module meta-file GUID
- @cached_property
- def Guid(self):
- #
- # To build same module more than once, the module path with FILE_GUID overridden has
- # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
- # 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
- @cached_property
- def Version(self):
- return self.Module.Version
-
- ## Return the module type
- @cached_property
- def ModuleType(self):
- return self.Module.ModuleType
-
- ## Return the component type (for Edk.x style of module)
- @cached_property
- def ComponentType(self):
- return self.Module.ComponentType
-
- ## Return the build type
- @cached_property
- def BuildType(self):
- return self.Module.BuildType
-
- ## Return the PCD_IS_DRIVER setting
- @cached_property
- def PcdIsDriver(self):
- return self.Module.PcdIsDriver
-
- ## Return the autogen version, i.e. module meta-file version
- @cached_property
- def AutoGenVersion(self):
- return self.Module.AutoGenVersion
-
- ## Check if the module is library or not
- @cached_property
- def IsLibrary(self):
- return bool(self.Module.LibraryClass)
-
- ## Check if the module is binary module or not
- @cached_property
- def IsBinaryModule(self):
- return self.Module.IsBinaryModule
-
- ## Return the directory to store intermediate files of the module
- @cached_property
- def BuildDir(self):
- return _MakeDir((
- self.PlatformInfo.BuildDir,
- self.Arch,
- self.SourceDir,
- self.MetaFile.BaseName
- ))
-
- ## Return the directory to store the intermediate object files of the module
- @cached_property
- def OutputDir(self):
- return _MakeDir((self.BuildDir, "OUTPUT"))
-
- ## 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 ''
-
- ## Return the directory to store auto-gened source files of the module
- @cached_property
- def DebugDir(self):
- return _MakeDir((self.BuildDir, "DEBUG"))
-
- ## Return the path of custom file
- @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
-
- ## Return the directory of the makefile
- #
- # @retval string The directory string of module's makefile
- #
- @cached_property
- def MakeFileDir(self):
- return self.BuildDir
-
- ## Return build command string
- #
- # @retval string Build command string
- #
- @cached_property
- def BuildCommand(self):
- 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
- #
- @cached_property
- def DerivedPackageList(self):
- PackageList = []
- for M in [self.Module] + self.DependentLibraryList:
- for Package in M.Packages:
- if Package in PackageList:
- continue
- PackageList.append(Package)
- return PackageList
-
- ## Get the depex string
- #
- # @return : a string contain all depex expression.
- 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)
- DepexExpressionList = InfObj.GetDepexExpresionList()
- for DepexExpression in DepexExpressionList:
- for key in DepexExpression:
- Arch, ModuleType = key
- DepexExpr = [x for x in DepexExpression[key] if not str(x).startswith('#')]
- # 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 or self.ModuleType.upper() == SUP_MODULE_HOST_APPLICATION:
- 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})
-
- #the type of build module is USER_DEFINED.
- if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED or self.ModuleType.upper() == SUP_MODULE_HOST_APPLICATION:
- for Depex in DepexList:
- for key in Depex:
- DepexStr += '[Depex.%s.%s]\n' % key
- DepexStr += '\n'.join('# '+ val for val in Depex[key])
- DepexStr += '\n\n'
- if not DepexStr:
- return '[Depex.%s]\n' % self.Arch
- return DepexStr
-
- #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():
- DepexStr += ' '.join(val for val in D)
- 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
- #
- @cached_property
- def DepexList(self):
- if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
- return {}
-
- 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}
-
- ## 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}
-
- # 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:
- for Section in TianoCoreUserExtent:
- 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
- #
- @cached_property
- def Specification(self):
- return self.Module.Specification
-
- ## Tool option for the module build
- #
- # @param PlatformInfo The object of PlatformBuildInfo
- # @retval dict The dict containing valid options
- #
- @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
-
- ## Get include path list from tool option for the module build
- #
- # @retval list The include path list
- #
- @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:
- #
- # New ToolChainFamily, don't known whether there is option to specify include directories
- #
- 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)]
- else:
- #
- # RVCT may specify a list of directory separated by commas
- #
- IncPathList = []
- for Path in BuildOptIncludeRegEx.findall(FlagOption):
- PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
- IncPathList.extend(NormPath(PathEntry, self.Macros) for PathEntry in PathList)
-
- #
- # 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
-
- ## 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.
- #
- @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
-
- # 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)
-
- self._MatchBuildRuleOrder(RetVal)
-
- for F in RetVal:
- self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
- return RetVal
-
- def _MatchBuildRuleOrder(self, FileList):
- Order_Dict = {}
- self.BuildOption
- for SingleFile in FileList:
- if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
- key = SingleFile.Path.rsplit(SingleFile.Ext,1)[0]
- 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)
-
- for item in RemoveList:
- FileList.remove(item)
-
- return FileList
-
- ## Return the list of unicode files
- @cached_property
- def UnicodeFileList(self):
- return self.FileTypes.get(TAB_UNICODE_FILE,[])
-
- ## Return the list of vfr files
- @cached_property
- def VfrFileList(self):
- return self.FileTypes.get(TAB_VFR_FILE, [])
-
- ## Return the list of Image Definition files
- @cached_property
- def IdfFileList(self):
- return self.FileTypes.get(TAB_IMAGE_FILE,[])
-
- ## 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
- #
- @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
-
- @cached_property
- def BuildRules(self):
- RetVal = {}
- BuildRuleDatabase = 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]
- if not RuleObject:
- # build type is always module type, but ...
- if self.ModuleType != self.BuildType:
- 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
-
- def _ApplyBuildRule(self, File, FileType, BinaryFileList=None):
- if self._BuildTargets is None:
- self._IntroBuildTargetList = set()
- self._FinalBuildTargetList = set()
- self._BuildTargets = defaultdict(set)
- self._FileTypes = defaultdict(set)
-
- if not BinaryFileList:
- BinaryFileList = self.BinaryFileList
-
- SubDirectory = os.path.join(self.OutputDir, File.SubDir)
- if not os.path.exists(SubDirectory):
- CreateDirectory(SubDirectory)
- LastTarget = None
- RuleChain = set()
- SourceList = [File]
- Index = 0
- #
- # Make sure to get build rule order value
- #
- self.BuildOption
-
- while Index < len(SourceList):
- Source = SourceList[Index]
- Index = Index + 1
-
- if Source != File:
- CreateDirectory(Source.Dir)
-
- if File.IsBinary and File == Source and File in BinaryFileList:
- # 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
-
- RuleChain.add(FileType)
- SourceList.extend(Target.Outputs)
- LastTarget = Target
- FileType = TAB_UNKNOWN_FILE
-
- @cached_property
- def Targets(self):
- if self._BuildTargets is None:
- self._IntroBuildTargetList = set()
- self._FinalBuildTargetList = set()
- self._BuildTargets = defaultdict(set)
- self._FileTypes = defaultdict(set)
-
- #TRICK: call SourceFileList property to apply build rule for source files
- self.SourceFileList
-
- #TRICK: call _GetBinaryFileList to apply build rule for binary files
- self.BinaryFileList
-
- return self._BuildTargets
-
- @cached_property
- def IntroTargetList(self):
- self.Targets
- return self._IntroBuildTargetList
-
- @cached_property
- def CodaTargetList(self):
- self.Targets
- return self._FinalBuildTargetList
-
- @cached_property
- def FileTypes(self):
- self.Targets
- return self._FileTypes
-
- ## Get the list of package object the module depends on
- #
- # @retval list The package object list
- #
- @cached_property
- def DependentPackageList(self):
- return self.Module.Packages
-
- ## Return the list of auto-generated code file
- #
- # @retval list The list of auto-generated file
- #
- @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
-
- ## 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)
-
- ## Get the list of PCDs from current module
- #
- # @retval list The list of PCD
- #
- @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
-
- ## Get the list of PCDs from dependent libraries
- #
- # @retval list The list of PCD
- #
- @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
-
- ## Get the GUID value mapping
- #
- # @retval dict The mapping between GUID cname and its value
- #
- @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
-
- @cached_property
- def GetGuidsUsedByPcd(self):
- RetVal = OrderedDict(self.Module.GetGuidsUsedByPcd())
- for Library in self.DependentLibraryList:
- RetVal.update(Library.GetGuidsUsedByPcd())
- return RetVal
- ## Get the protocol value mapping
- #
- # @retval dict The mapping between protocol cname and its value
- #
- @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
-
- ## Get the PPI value mapping
- #
- # @retval dict The mapping between PPI cname and its value
- #
- @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
-
- ## Get the list of include search path
- #
- # @retval list The list path
- #
- @cached_property
- def IncludePathList(self):
- RetVal = []
- RetVal.append(self.MetaFile.Dir)
- RetVal.append(self.DebugDir)
-
- 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
-
- @cached_property
- def IncludePathLength(self):
- return sum(len(inc)+1 for inc in self.IncludePathList)
-
- ## 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 []
-
- NameGuids = set()
- 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
- NameArray = _ConvertStringToByteArray('L"' + Name.group(1) + '"')
- NameGuids.add((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
- 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
- for SkuInfo in Pcd.SkuInfoList.values():
- Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
- if not Value:
- continue
- Name = _ConvertStringToByteArray(SkuInfo.VariableName)
- 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" :
- #
- # search the .map file to find the offset of vfr binary in the PE32+/TE file.
- #
- VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
- elif SourceFile.Type.upper() == ".UNI" :
- #
- # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
- #
- VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
-
- if not VfrUniBaseName:
- return None
- MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
- EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
- VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
- if not VfrUniOffsetList:
- return None
-
- OutputName = '%sOffset.bin' % self.Name
- UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)
-
- try:
- fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
- except:
- EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName, None)
-
- # Use a instance of BytesIO to cache data
- fStringIO = BytesIO()
-
- for Item in VfrUniOffsetList:
- if (Item[0].find("Strings") != -1):
- #
- # UNI offset in image.
- # GUID + Offset
- # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
- #
- UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
- fStringIO.write(UniGuid)
- UniValue = pack ('Q', int (Item[1], 16))
- fStringIO.write (UniValue)
- else:
- #
- # VFR binary offset in image.
- # GUID + Offset
- # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
- #
- VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
- fStringIO.write(VfrGuid)
- VfrValue = pack ('Q', int (Item[1], 16))
- fStringIO.write (VfrValue)
- #
- # write data into file.
- #
- try :
- fInputfile.write (fStringIO.getvalue())
- except:
- EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
- "file been locked or using by other applications." %UniVfrOffsetFileName, None)
-
- fStringIO.close ()
- fInputfile.close ()
- return OutputName
-
- @cached_property
- def OutputFile(self):
- retVal = set()
- 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('/')
- retVal.add(File)
- if self.DepexGenerated:
- retVal.add(self.Name + '.depex')
-
- Bin = self._GenOffsetBin()
- if Bin:
- retVal.add(Bin)
-
- for Root, Dirs, Files in os.walk(OutputDir):
- for File in Files:
- if File.lower().endswith('.pdb'):
- retVal.add(File)
-
- return retVal
-
- ## Create AsBuilt INF file the module
- #
- def CreateAsBuiltInf(self):
-
- if self.IsAsBuiltInfCreated:
- return
-
- # Skip INF file generation for libraries
- if self.IsLibrary:
- return
-
- # Skip the following code for modules with no source files
- if not self.SourceFileList:
- return
-
- # Skip the following code for modules without any binary files
- if self.BinaryFileList:
- return
-
- ### 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:
- PatchablePcds.append(Pcd)
- PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_PATCHABLE_IN_MODULE))
- elif Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
- if Pcd not in Pcds:
- Pcds.append(Pcd)
- PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX))
- PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC))
- PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
- GuidList = OrderedDict(self.GuidList)
- for TokenSpace in self.GetGuidsUsedByPcd:
- # 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]:
- Packages.append(Package)
- Found = True
- break
- if Found:
- break
-
- VfrPcds = self._GetPcdsMaybeUsedByVfr()
- for Pkg in self.PlatformInfo.PackageList:
- if Pkg in Packages:
- continue
- for VfrPcd in VfrPcds:
- 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)
- break
-
- 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 ''
- 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,
- 'package_item' : [Package.MetaFile.File.replace('\\', '/') for Package in Packages],
- '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:
- AsBuiltInfDict['pcd_is_driver_string'].append(DriverType)
-
- if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
- AsBuiltInfDict['module_uefi_specification_version'].append(self.Specification['UEFI_SPECIFICATION_VERSION'])
- if 'PI_SPECIFICATION_VERSION' in self.Specification:
- AsBuiltInfDict['module_pi_specification_version'].append(self.Specification['PI_SPECIFICATION_VERSION'])
-
- 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('/')
- if os.path.isabs(File):
- File = File.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
- if Item.Target.Ext.lower() == '.aml':
- AsBuiltInfDict['binary_item'].append('ASL|' + File)
- elif Item.Target.Ext.lower() == '.acpi':
- AsBuiltInfDict['binary_item'].append('ACPI|' + File)
- elif Item.Target.Ext.lower() == '.efi':
- AsBuiltInfDict['binary_item'].append('PE32|' + self.Name + '.efi')
- else:
- 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
- if self.DepexGenerated:
- 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')
-
- Bin = self._GenOffsetBin()
- if Bin:
- AsBuiltInfDict['binary_item'].append('BIN|%s' % Bin)
-
- for Root, Dirs, Files in os.walk(OutputDir):
- for File in Files:
- if File.lower().endswith('.pdb'):
- AsBuiltInfDict['binary_item'].append('DISPOSABLE|' + File)
- 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]:
- Comments = '\n '.join(Item[1][CName]) if CName in Item[1] else ''
- Entry = Comments + '\n ' + CName if Comments else CName
- 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'
-
- if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES:
- HexFormat = '0x%02x'
- if Pcd.DatumType == TAB_UINT16:
- HexFormat = '0x%04x'
- elif Pcd.DatumType == TAB_UINT32:
- HexFormat = '0x%08x'
- elif Pcd.DatumType == TAB_UINT64:
- HexFormat = '0x%016x'
- PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
- else:
- if Pcd.MaxDatumSize is None or Pcd.MaxDatumSize == '':
- 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
- ArraySize = ArraySize // 2
- if ArraySize < (len(PcdValue) + 1):
- if Pcd.MaxSizeUserSet:
- EdkLogger.error("build", AUTOGEN_ERROR,
- "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
- )
- else:
- ArraySize = len(PcdValue) + 1
- 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:
- if Pcd.MaxSizeUserSet:
- EdkLogger.error("build", AUTOGEN_ERROR,
- "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
- )
- else:
- ArraySize = len(PcdValue) + 1
- 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:
- PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
- else:
- PcdCommentList.append('## UNDEFINED ' + HiiInfo)
- PcdComments = '\n '.join(PcdCommentList)
- PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
- if PcdComments:
- PcdEntry = PcdComments + '\n ' + PcdEntry
- AsBuiltInfDict['pcd_item'].append(PcdEntry)
- for Item in self.BuildOption:
- if 'FLAGS' in self.BuildOption[Item]:
- 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()))
-
- # Generated LibraryClasses section in comments.
- for Library in self.LibraryAutoGenList:
- AsBuiltInfDict['libraryclasses_item'].append(Library.MetaFile.File.replace('\\', '/'))
-
- # 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.
- DepexExpression = self._GetDepexExpresionString()
- AsBuiltInfDict['depexsection_item'] = DepexExpression if DepexExpression else ''
-
- AsBuiltInf = TemplateString()
- AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
-
- SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
-
- self.IsAsBuiltInfCreated = True
-
- def CopyModuleToCache(self):
- FileDir = path.join(GlobalData.gBinCacheDest, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)
- CreateDirectory (FileDir)
- HashFile = path.join(self.BuildDir, self.Name + '.hash')
- if os.path.exists(HashFile):
- CopyFileOnChange(HashFile, FileDir)
- ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
- if os.path.exists(ModuleFile):
- CopyFileOnChange(ModuleFile, FileDir)
-
- if not self.OutputFile:
- Ma = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
- self.OutputFile = Ma.Binaries
-
- 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):
- 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)
- CopyFileOnChange(File, destination_dir)
-
- def AttemptModuleCacheCopy(self):
- # 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
- FileDir = path.join(GlobalData.gBinCacheSource, self.PlatformInfo.OutputDir, self.BuildTarget + "_" + self.ToolChain, self.Arch, self.SourceDir, self.MetaFile.BaseName)
- HashFile = path.join(FileDir, self.Name + '.hash')
- if os.path.exists(HashFile):
- f = open(HashFile, 'r')
- CacheHash = f.read()
- f.close()
- self.GenModuleHash()
- 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:
- CopyFileOnChange(HashFile, self.BuildDir)
- else:
- File = path.join(root, f)
- 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)
- CopyFileOnChange(File, destination_dir)
- 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
- #
- @cached_class_function
- def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):
- # nest this function inside its 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)
-
- # 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()
-
- # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
- if not GlobalData.gUseHashCache and 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))
-
- CreateTimeStamp()
-
- def CopyBinaryFiles(self):
- for File in self.Module.Binaries:
- SrcPath = File.Path
- DstPath = os.path.join(self.OutputDir, os.path.basename(SrcPath))
- 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()
-
- # Don't enable if hash feature enabled, CanSkip uses timestamps to determine build skipping
- if not GlobalData.gUseHashCache and 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:
- # 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 or ModuleType == SUP_MODULE_HOST_APPLICATION:
- continue
-
- Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
- DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
-
- if len(Dpx.PostfixNotation) != 0:
- 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
- @cached_property
- def LibraryAutoGenList(self):
- RetVal = []
- for Library in self.DependentLibraryList:
- La = ModuleAutoGen(
- self.Workspace,
- Library.MetaFile,
- self.BuildTarget,
- self.ToolChain,
- self.Arch,
- self.PlatformInfo.MetaFile
- )
- if La not in RetVal:
- RetVal.append(La)
- for Lib in La.CodaTargetList:
- self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
- return RetVal
-
- def GenModuleHash(self):
- # Initialize a dictionary for each arch type
- if self.Arch not in GlobalData.gModuleHash:
- GlobalData.gModuleHash[self.Arch] = {}
-
- # 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
- m = hashlib.md5()
-
- # Add Platform level hash
- m.update(GlobalData.gPlatformHash.encode('utf-8'))
-
- # Add Package level hash
- if self.DependentPackageList:
- 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'))
-
- # Add Library hash
- if self.LibraryAutoGenList:
- for Lib in sorted(self.LibraryAutoGenList, key=lambda x: x.Name):
- if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
- Lib.GenModuleHash()
- m.update(GlobalData.gModuleHash[self.Arch][Lib.Name].encode('utf-8'))
-
- # Add Module self
- f = open(str(self.MetaFile), 'rb')
- Content = f.read()
- f.close()
- m.update(Content)
-
- # Add Module's source files
- if self.SourceFileList:
- for File in sorted(self.SourceFileList, key=lambda x: str(x)):
- f = open(str(File), 'rb')
- Content = f.read()
- f.close()
- m.update(Content)
-
- GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
-
- return GlobalData.gModuleHash[self.Arch][self.Name].encode('utf-8')
-
- ## Decide whether we can skip the ModuleAutoGen process
- def CanSkipbyHash(self):
- # 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]
-
- ## Decide whether we can skip the ModuleAutoGen process
- # If any source file is newer than the module than we cannot skip
- #
- def CanSkip(self):
- if self.MakeFileDir in GlobalData.gSikpAutoGenCache:
- return True
- if not os.path.exists(self.TimeStampPath):
- return False
- #last creation time of the module
- DstTimeStamp = os.stat(self.TimeStampPath)[8]
-
- SrcTimeStamp = self.Workspace._SrcTimeStamp
- if SrcTimeStamp > DstTimeStamp:
- return False
-
- with open(self.TimeStampPath,'r') as f:
- 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
- GlobalData.gSikpAutoGenCache.add(self.MakeFileDir)
- return True
-
- @cached_property
- def TimeStampPath(self):
- return os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')
+ @classmethod
+ def Cache(cls):
+ return cls.__ObjectCache
+
+#
+# The priority list while override build option
+#
+PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
+ "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
+ "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
+ "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
+ "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)
+## 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(Key):
+ Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
+ PriorityValue = 0x11111
+ if Target == TAB_STAR:
+ PriorityValue &= 0x01111
+ if ToolChain == TAB_STAR:
+ PriorityValue &= 0x10111
+ if Arch == TAB_STAR:
+ PriorityValue &= 0x11011
+ if CommandType == TAB_STAR:
+ PriorityValue &= 0x11101
+ if Attr == TAB_STAR:
+ PriorityValue &= 0x11110
+
+ return PrioList["0x%0.5x" % PriorityValue]
|