summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace')
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py646
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DecBuildData.py475
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py3588
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/InfBuildData.py1064
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaDataTable.py306
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py45
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileParser.py2193
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py430
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py256
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py204
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/__init__.py9
11 files changed, 9216 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py
new file mode 100755
index 00000000..a4be167d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py
@@ -0,0 +1,646 @@
+## @file
+# This file is used to define each component of the build database
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+from collections import OrderedDict, namedtuple
+from Common.DataType import *
+import collections
+import re
+from collections import OrderedDict
+from Common.Misc import CopyDict,ArrayIndex
+import copy
+import Common.EdkLogger as EdkLogger
+from Common.BuildToolError import OPTION_VALUE_INVALID
+from Common.caching import cached_property
+StructPattern = re.compile(r'[_a-zA-Z][0-9A-Za-z_\[\]]*$')
+
+## PcdClassObject
+#
+# This Class is used for PcdObject
+#
+# @param object: Inherited from object class
+# @param Name: Input value for Name of Pcd, default is None
+# @param Guid: Input value for Guid of Pcd, default is None
+# @param Type: Input value for Type of Pcd, default is None
+# @param DatumType: Input value for DatumType of Pcd, default is None
+# @param Value: Input value for Value of Pcd, default is None
+# @param Token: Input value for Token of Pcd, default is None
+# @param MaxDatumSize: Input value for MaxDatumSize of Pcd, default is None
+# @param SkuInfoList: Input value for SkuInfoList of Pcd, default is {}
+# @param IsOverrided: Input value for IsOverrided of Pcd, default is False
+# @param GuidValue: Input value for TokenSpaceGuidValue of Pcd, default is None
+#
+# @var TokenCName: To store value for TokenCName
+# @var TokenSpaceGuidCName: To store value for TokenSpaceGuidCName
+# @var Type: To store value for Type
+# @var DatumType: To store value for DatumType
+# @var TokenValue: To store value for TokenValue
+# @var MaxDatumSize: To store value for MaxDatumSize
+# @var SkuInfoList: To store value for SkuInfoList
+# @var IsOverrided: To store value for IsOverrided
+# @var Phase: To store value for Phase, default is "DXE"
+#
+class PcdClassObject(object):
+ def __init__(self, Name = None, Guid = None, Type = None, DatumType = None, Value = None, Token = None, MaxDatumSize = None, SkuInfoList = None, IsOverrided = False, GuidValue = None, validateranges = None, validlists = None, expressions = None, IsDsc = False, UserDefinedDefaultStoresFlag = False):
+ self.TokenCName = Name
+ self.TokenSpaceGuidCName = Guid
+ self.TokenSpaceGuidValue = GuidValue
+ self.Type = Type
+ self._DatumType = DatumType
+ self.DefaultValue = Value
+ self.TokenValue = Token
+ self.MaxDatumSize = MaxDatumSize
+ self.MaxSizeUserSet = None
+ self.SkuInfoList = SkuInfoList if SkuInfoList is not None else OrderedDict()
+ self.Phase = "DXE"
+ self.Pending = False
+ self.IsOverrided = IsOverrided
+ self.IsFromBinaryInf = False
+ self.IsFromDsc = False
+ self.validateranges = validateranges if validateranges is not None else []
+ self.validlists = validlists if validlists is not None else []
+ self.expressions = expressions if expressions is not None else []
+ self.DscDefaultValue = None
+ self.DscRawValue = {}
+ self.DscRawValueInfo = {}
+ if IsDsc:
+ self.DscDefaultValue = Value
+ self.PcdValueFromComm = ""
+ self.PcdValueFromFdf = ""
+ self.PcdValueFromComponents = {} #{ModuleGuid:value, file_path,lineNo}
+ self.CustomAttribute = {}
+ self.UserDefinedDefaultStoresFlag = UserDefinedDefaultStoresFlag
+ self._Capacity = None
+
+ @property
+ def Capacity(self):
+ if self._Capacity is None:
+ self._Capacity = []
+ dimension = ArrayIndex.findall(self._DatumType)
+ for item in dimension:
+ maxsize = item.lstrip("[").rstrip("]").strip()
+ if not maxsize:
+ maxsize = "-1"
+ maxsize = str(int(maxsize,16)) if maxsize.startswith(("0x","0X")) else maxsize
+ self._Capacity.append(maxsize)
+ if hasattr(self, "SkuOverrideValues"):
+ for sku in self.SkuOverrideValues:
+ for defaultstore in self.SkuOverrideValues[sku]:
+ fields = self.SkuOverrideValues[sku][defaultstore]
+ for demesionattr in fields:
+ fieldinfo = fields[demesionattr]
+ deme = ArrayIndex.findall(demesionattr)
+ for i in range(len(deme)):
+ if int(deme[i].lstrip("[").rstrip("]").strip()) >= int(self._Capacity[i]):
+ if self._Capacity[i] != "-1":
+ firstfieldinfo = list(fieldinfo.values())[0]
+ EdkLogger.error('Build', OPTION_VALUE_INVALID, "For Pcd %s, Array Index exceed the Array size. From %s Line %s \n " %
+ (".".join((self.TokenSpaceGuidCName, self.TokenCName)), firstfieldinfo[1],firstfieldinfo[2] ))
+ if hasattr(self,"DefaultValues"):
+ for demesionattr in self.DefaultValues:
+ fieldinfo = self.DefaultValues[demesionattr]
+ deme = ArrayIndex.findall(demesionattr)
+ for i in range(len(deme)):
+ if int(deme[i].lstrip("[").rstrip("]").strip()) >= int(self._Capacity[i]):
+ if self._Capacity[i] != "-1":
+ firstfieldinfo = list(fieldinfo.values())[0]
+ EdkLogger.error('Build', OPTION_VALUE_INVALID, "For Pcd %s, Array Index exceed the Array size. From %s Line %s \n " %
+ (".".join((self.TokenSpaceGuidCName, self.TokenCName)), firstfieldinfo[1],firstfieldinfo[2] ))
+ return self._Capacity
+
+ def PcdArraySize(self):
+ if self.Capacity[-1] == "-1":
+ return -1
+ size = 1
+ for de in self.Capacity:
+ size = size * int(de)
+ return size
+ @property
+ def DatumType(self):
+ return self._DatumType
+
+ @DatumType.setter
+ def DatumType(self,DataType):
+ self._DatumType = DataType
+ self._Capacity = None
+
+ @property
+ def BaseDatumType(self):
+ if self.IsArray():
+ return self._DatumType[:self._DatumType.index("[")]
+ else:
+ return self._DatumType
+ def IsArray(self):
+ return True if len(self.Capacity) else False
+
+ def IsAggregateDatumType(self):
+ if self.DatumType in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
+ return False
+ if self.IsArray() or StructPattern.match(self.DatumType):
+ return True
+ return False
+
+ def IsSimpleTypeArray(self):
+ if self.IsArray() and self.BaseDatumType in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, "BOOLEAN"]:
+ return True
+ return False
+
+ @staticmethod
+ def GetPcdMaxSizeWorker(PcdString, MaxSize):
+ if PcdString.startswith("{") and PcdString.endswith("}"):
+ return max([len(PcdString.split(",")),MaxSize])
+
+ if PcdString.startswith("\"") or PcdString.startswith("\'"):
+ return max([len(PcdString)-2+1,MaxSize])
+
+ if PcdString.startswith("L\""):
+ return max([2*(len(PcdString)-3+1),MaxSize])
+
+ return max([len(PcdString),MaxSize])
+
+ ## Get the maximum number of bytes
+ def GetPcdMaxSize(self):
+ if self.DatumType in TAB_PCD_NUMERIC_TYPES:
+ return MAX_SIZE_TYPE[self.DatumType]
+
+ MaxSize = int(self.MaxDatumSize, 10) if self.MaxDatumSize else 0
+ if self.PcdValueFromFdf:
+ MaxSize = self.GetPcdMaxSizeWorker(self.PcdValueFromFdf,MaxSize)
+ if self.PcdValueFromComm:
+ MaxSize = self.GetPcdMaxSizeWorker(self.PcdValueFromComm,MaxSize)
+ if hasattr(self, "DefaultValueFromDec"):
+ MaxSize = self.GetPcdMaxSizeWorker(self.DefaultValueFromDec,MaxSize)
+ return MaxSize
+
+ ## Get the number of bytes
+ def GetPcdSize(self):
+ if self.DatumType in TAB_PCD_NUMERIC_TYPES:
+ return MAX_SIZE_TYPE[self.DatumType]
+ if not self.DefaultValue:
+ return 1
+ elif self.DefaultValue[0] == 'L':
+ return (len(self.DefaultValue) - 2) * 2
+ elif self.DefaultValue[0] == '{':
+ return len(self.DefaultValue.split(','))
+ else:
+ return len(self.DefaultValue) - 1
+
+
+ ## Convert the class to a string
+ #
+ # Convert each member of the class to string
+ # Organize to a single line format string
+ #
+ # @retval Rtn Formatted String
+ #
+ def __str__(self):
+ Rtn = '\tTokenCName=' + str(self.TokenCName) + ', ' + \
+ 'TokenSpaceGuidCName=' + str(self.TokenSpaceGuidCName) + ', ' + \
+ 'Type=' + str(self.Type) + ', ' + \
+ 'DatumType=' + str(self.DatumType) + ', ' + \
+ 'DefaultValue=' + str(self.DefaultValue) + ', ' + \
+ 'TokenValue=' + str(self.TokenValue) + ', ' + \
+ 'MaxDatumSize=' + str(self.MaxDatumSize) + ', '
+ for Item in self.SkuInfoList.values():
+ Rtn = Rtn + 'SkuId=' + Item.SkuId + ', ' + 'SkuIdName=' + Item.SkuIdName
+ Rtn = Rtn + ', IsOverrided=' + str(self.IsOverrided)
+
+ return Rtn
+
+ ## Override __eq__ function
+ #
+ # Check whether pcds are the same
+ #
+ # @retval False The two pcds are different
+ # @retval True The two pcds are the same
+ #
+ def __eq__(self, Other):
+ return Other and self.TokenCName == Other.TokenCName and self.TokenSpaceGuidCName == Other.TokenSpaceGuidCName
+
+ ## Override __hash__ function
+ #
+ # Use (TokenCName, TokenSpaceGuidCName) as key in hash table
+ #
+ # @retval truple() Key for hash table
+ #
+ def __hash__(self):
+ return hash((self.TokenCName, self.TokenSpaceGuidCName))
+
+ @cached_property
+ def _fullname(self):
+ return ".".join((self.TokenSpaceGuidCName,self.TokenCName))
+
+ def __lt__(self,pcd):
+ return self._fullname < pcd._fullname
+ def __gt__(self,pcd):
+ return self._fullname > pcd._fullname
+
+ def sharedcopy(self,new_pcd):
+ new_pcd.TokenCName = self.TokenCName
+ new_pcd.TokenSpaceGuidCName = self.TokenSpaceGuidCName
+ new_pcd.TokenSpaceGuidValue = self.TokenSpaceGuidValue
+ new_pcd.Type = self.Type
+ new_pcd.DatumType = self.DatumType
+ new_pcd.DefaultValue = self.DefaultValue
+ new_pcd.TokenValue = self.TokenValue
+ new_pcd.MaxDatumSize = self.MaxDatumSize
+ new_pcd.MaxSizeUserSet = self.MaxSizeUserSet
+
+ new_pcd.Phase = self.Phase
+ new_pcd.Pending = self.Pending
+ new_pcd.IsOverrided = self.IsOverrided
+ new_pcd.IsFromBinaryInf = self.IsFromBinaryInf
+ new_pcd.IsFromDsc = self.IsFromDsc
+ new_pcd.PcdValueFromComm = self.PcdValueFromComm
+ new_pcd.PcdValueFromFdf = self.PcdValueFromFdf
+ new_pcd.UserDefinedDefaultStoresFlag = self.UserDefinedDefaultStoresFlag
+ new_pcd.DscRawValue = self.DscRawValue
+ new_pcd.DscRawValueInfo = self.DscRawValueInfo
+ new_pcd.CustomAttribute = self.CustomAttribute
+ new_pcd.validateranges = [item for item in self.validateranges]
+ new_pcd.validlists = [item for item in self.validlists]
+ new_pcd.expressions = [item for item in self.expressions]
+ new_pcd.SkuInfoList = {key: copy.deepcopy(skuobj) for key,skuobj in self.SkuInfoList.items()}
+ return new_pcd
+
+ def __deepcopy__(self,memo):
+ new_pcd = PcdClassObject()
+ self.sharedcopy(new_pcd)
+ return new_pcd
+
+class StructurePcd(PcdClassObject):
+ def __init__(self, StructuredPcdIncludeFile=None, Packages=None, Name=None, Guid=None, Type=None, DatumType=None, Value=None, Token=None, MaxDatumSize=None, SkuInfoList=None, IsOverrided=False, GuidValue=None, validateranges=None, validlists=None, expressions=None,default_store = TAB_DEFAULT_STORES_DEFAULT):
+ if SkuInfoList is None:
+ SkuInfoList = {}
+ if validateranges is None:
+ validateranges = []
+ if validlists is None:
+ validlists = []
+ if expressions is None:
+ expressions = []
+ if Packages is None:
+ Packages = []
+ super(StructurePcd, self).__init__(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, IsOverrided, GuidValue, validateranges, validlists, expressions)
+ self.StructuredPcdIncludeFile = [] if StructuredPcdIncludeFile is None else StructuredPcdIncludeFile
+ self.PackageDecs = Packages
+ self.DefaultStoreName = [default_store]
+ self.DefaultValues = OrderedDict()
+ self.PcdMode = None
+ self.SkuOverrideValues = OrderedDict()
+ self.StructName = None
+ self.PcdDefineLineNo = 0
+ self.PkgPath = ""
+ self.DefaultValueFromDec = ""
+ self.DefaultValueFromDecInfo = None
+ self.ValueChain = set()
+ self.PcdFieldValueFromComm = OrderedDict()
+ self.PcdFieldValueFromFdf = OrderedDict()
+ self.DefaultFromDSC=None
+ self.PcdFiledValueFromDscComponent = OrderedDict()
+ def __repr__(self):
+ return self.TypeName
+
+ def AddDefaultValue (self, FieldName, Value, FileName="", LineNo=0,DimensionAttr ="-1"):
+ if DimensionAttr not in self.DefaultValues:
+ self.DefaultValues[DimensionAttr] = collections.OrderedDict()
+ if FieldName in self.DefaultValues[DimensionAttr]:
+ del self.DefaultValues[DimensionAttr][FieldName]
+ self.DefaultValues[DimensionAttr][FieldName] = [Value.strip(), FileName, LineNo]
+ return self.DefaultValues[DimensionAttr][FieldName]
+
+ def SetDecDefaultValue(self, DefaultValue,decpath=None,lineno=None):
+ self.DefaultValueFromDec = DefaultValue
+ self.DefaultValueFromDecInfo = (decpath,lineno)
+ def AddOverrideValue (self, FieldName, Value, SkuName, DefaultStoreName, FileName="", LineNo=0, DimensionAttr = '-1'):
+ if SkuName not in self.SkuOverrideValues:
+ self.SkuOverrideValues[SkuName] = OrderedDict()
+ if DefaultStoreName not in self.SkuOverrideValues[SkuName]:
+ self.SkuOverrideValues[SkuName][DefaultStoreName] = OrderedDict()
+ if DimensionAttr not in self.SkuOverrideValues[SkuName][DefaultStoreName]:
+ self.SkuOverrideValues[SkuName][DefaultStoreName][DimensionAttr] = collections.OrderedDict()
+ if FieldName in self.SkuOverrideValues[SkuName][DefaultStoreName][DimensionAttr]:
+ del self.SkuOverrideValues[SkuName][DefaultStoreName][DimensionAttr][FieldName]
+ self.SkuOverrideValues[SkuName][DefaultStoreName][DimensionAttr][FieldName] = [Value.strip(), FileName, LineNo]
+ return self.SkuOverrideValues[SkuName][DefaultStoreName][DimensionAttr][FieldName]
+
+ def AddComponentOverrideValue(self,FieldName, Value, ModuleGuid, FileName="", LineNo=0, DimensionAttr = '-1'):
+ self.PcdFiledValueFromDscComponent.setdefault(ModuleGuid, OrderedDict())
+ self.PcdFiledValueFromDscComponent[ModuleGuid].setdefault(DimensionAttr,OrderedDict())
+ self.PcdFiledValueFromDscComponent[ModuleGuid][DimensionAttr][FieldName] = [Value.strip(), FileName, LineNo]
+ return self.PcdFiledValueFromDscComponent[ModuleGuid][DimensionAttr][FieldName]
+
+ def SetPcdMode (self, PcdMode):
+ self.PcdMode = PcdMode
+
+ def copy(self, PcdObject):
+ self.TokenCName = PcdObject.TokenCName if PcdObject.TokenCName else self.TokenCName
+ self.TokenSpaceGuidCName = PcdObject.TokenSpaceGuidCName if PcdObject.TokenSpaceGuidCName else PcdObject.TokenSpaceGuidCName
+ self.TokenSpaceGuidValue = PcdObject.TokenSpaceGuidValue if PcdObject.TokenSpaceGuidValue else self.TokenSpaceGuidValue
+ self.Type = PcdObject.Type if PcdObject.Type else self.Type
+ self._DatumType = PcdObject.DatumType if PcdObject.DatumType else self.DatumType
+ self.DefaultValue = PcdObject.DefaultValue if PcdObject.DefaultValue else self.DefaultValue
+ self.TokenValue = PcdObject.TokenValue if PcdObject.TokenValue else self.TokenValue
+ self.MaxDatumSize = PcdObject.MaxDatumSize if PcdObject.MaxDatumSize else self.MaxDatumSize
+ self.SkuInfoList = PcdObject.SkuInfoList if PcdObject.SkuInfoList else self.SkuInfoList
+ self.Phase = PcdObject.Phase if PcdObject.Phase else self.Phase
+ self.Pending = PcdObject.Pending if PcdObject.Pending else self.Pending
+ self.IsOverrided = PcdObject.IsOverrided if PcdObject.IsOverrided else self.IsOverrided
+ self.IsFromBinaryInf = PcdObject.IsFromBinaryInf if PcdObject.IsFromBinaryInf else self.IsFromBinaryInf
+ self.IsFromDsc = PcdObject.IsFromDsc if PcdObject.IsFromDsc else self.IsFromDsc
+ self.validateranges = PcdObject.validateranges if PcdObject.validateranges else self.validateranges
+ self.validlists = PcdObject.validlists if PcdObject.validlists else self.validlists
+ self.expressions = PcdObject.expressions if PcdObject.expressions else self.expressions
+ self.DscRawValue = PcdObject.DscRawValue if PcdObject.DscRawValue else self.DscRawValue
+ self.DscRawValueInfo = PcdObject.DscRawValueInfo if PcdObject.DscRawValueInfo else self.DscRawValueInfo
+ self.PcdValueFromComm = PcdObject.PcdValueFromComm if PcdObject.PcdValueFromComm else self.PcdValueFromComm
+ self.PcdValueFromFdf = PcdObject.PcdValueFromFdf if PcdObject.PcdValueFromFdf else self.PcdValueFromFdf
+ self.CustomAttribute = PcdObject.CustomAttribute if PcdObject.CustomAttribute else self.CustomAttribute
+ self.UserDefinedDefaultStoresFlag = PcdObject.UserDefinedDefaultStoresFlag if PcdObject.UserDefinedDefaultStoresFlag else self.UserDefinedDefaultStoresFlag
+ if isinstance(PcdObject, StructurePcd):
+ self.StructuredPcdIncludeFile = PcdObject.StructuredPcdIncludeFile if PcdObject.StructuredPcdIncludeFile else self.StructuredPcdIncludeFile
+ self.PackageDecs = PcdObject.PackageDecs if PcdObject.PackageDecs else self.PackageDecs
+ self.DefaultValues = PcdObject.DefaultValues if PcdObject.DefaultValues else self.DefaultValues
+ self.PcdMode = PcdObject.PcdMode if PcdObject.PcdMode else self.PcdMode
+ self.DefaultValueFromDec = PcdObject.DefaultValueFromDec if PcdObject.DefaultValueFromDec else self.DefaultValueFromDec
+ self.DefaultValueFromDecInfo = PcdObject.DefaultValueFromDecInfo if PcdObject.DefaultValueFromDecInfo else self.DefaultValueFromDecInfo
+ self.SkuOverrideValues = PcdObject.SkuOverrideValues if PcdObject.SkuOverrideValues else self.SkuOverrideValues
+ self.StructName = PcdObject.DatumType if PcdObject.DatumType else self.StructName
+ self.PcdDefineLineNo = PcdObject.PcdDefineLineNo if PcdObject.PcdDefineLineNo else self.PcdDefineLineNo
+ self.PkgPath = PcdObject.PkgPath if PcdObject.PkgPath else self.PkgPath
+ self.ValueChain = PcdObject.ValueChain if PcdObject.ValueChain else self.ValueChain
+ self.PcdFieldValueFromComm = PcdObject.PcdFieldValueFromComm if PcdObject.PcdFieldValueFromComm else self.PcdFieldValueFromComm
+ self.PcdFieldValueFromFdf = PcdObject.PcdFieldValueFromFdf if PcdObject.PcdFieldValueFromFdf else self.PcdFieldValueFromFdf
+ self.PcdFiledValueFromDscComponent = PcdObject.PcdFiledValueFromDscComponent if PcdObject.PcdFiledValueFromDscComponent else self.PcdFiledValueFromDscComponent
+
+ def __deepcopy__(self,memo):
+ new_pcd = StructurePcd()
+ self.sharedcopy(new_pcd)
+
+ new_pcd.DefaultValueFromDec = self.DefaultValueFromDec
+ new_pcd.DefaultValueFromDecInfo = self.DefaultValueFromDecInfo
+ new_pcd.PcdMode = self.PcdMode
+ new_pcd.StructName = self.DatumType
+ new_pcd.PcdDefineLineNo = self.PcdDefineLineNo
+ new_pcd.PkgPath = self.PkgPath
+ new_pcd.StructuredPcdIncludeFile = [item for item in self.StructuredPcdIncludeFile]
+ new_pcd.PackageDecs = [item for item in self.PackageDecs]
+ new_pcd.DefaultValues = CopyDict(self.DefaultValues)
+ new_pcd.DefaultFromDSC=CopyDict(self.DefaultFromDSC)
+ new_pcd.SkuOverrideValues = CopyDict(self.SkuOverrideValues)
+ new_pcd.PcdFieldValueFromComm = CopyDict(self.PcdFieldValueFromComm)
+ new_pcd.PcdFieldValueFromFdf = CopyDict(self.PcdFieldValueFromFdf)
+ new_pcd.PcdFiledValueFromDscComponent = CopyDict(self.PcdFiledValueFromDscComponent)
+ new_pcd.ValueChain = {item for item in self.ValueChain}
+ return new_pcd
+
+LibraryClassObject = namedtuple('LibraryClassObject', ['LibraryClass','SupModList'])
+
+## ModuleBuildClassObject
+#
+# This Class defines ModuleBuildClass
+#
+# @param object: Inherited from object class
+#
+# @var MetaFile: To store value for module meta file path
+# @var BaseName: To store value for BaseName
+# @var ModuleType: To store value for ModuleType
+# @var Guid: To store value for Guid
+# @var Version: To store value for Version
+# @var PcdIsDriver: To store value for PcdIsDriver
+# @var BinaryModule: To store value for BinaryModule
+# @var CustomMakefile: To store value for CustomMakefile
+# @var Specification: To store value for Specification
+# @var Shadow To store value for Shadow
+# @var LibraryClass: To store value for LibraryClass, it is a list structure as
+# [ LibraryClassObject, ...]
+# @var ModuleEntryPointList: To store value for ModuleEntryPointList
+# @var ModuleUnloadImageList: To store value for ModuleUnloadImageList
+# @var ConstructorList: To store value for ConstructorList
+# @var DestructorList: To store value for DestructorList
+# @var Binaries: To store value for Binaries, it is a list structure as
+# [ ModuleBinaryClassObject, ...]
+# @var Sources: To store value for Sources, it is a list structure as
+# [ ModuleSourceFilesClassObject, ... ]
+# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as
+# { [LibraryClassName, ModuleType] : LibraryClassInfFile }
+# @var Protocols: To store value for Protocols, it is a list structure as
+# [ ProtocolName, ... ]
+# @var Ppis: To store value for Ppis, it is a list structure as
+# [ PpiName, ... ]
+# @var Guids: To store value for Guids, it is a list structure as
+# [ GuidName, ... ]
+# @var Includes: To store value for Includes, it is a list structure as
+# [ IncludePath, ... ]
+# @var Packages: To store value for Packages, it is a list structure as
+# [ DecFileName, ... ]
+# @var Pcds: To store value for Pcds, it is a set structure as
+# { [(PcdCName, PcdGuidCName)] : PcdClassObject}
+# @var BuildOptions: To store value for BuildOptions, it is a set structure as
+# { [BuildOptionKey] : BuildOptionValue}
+# @var Depex: To store value for Depex
+#
+class ModuleBuildClassObject(object):
+ def __init__(self):
+ self.AutoGenVersion = 0
+ self.MetaFile = ''
+ self.BaseName = ''
+ self.ModuleType = ''
+ self.Guid = ''
+ self.Version = ''
+ self.PcdIsDriver = ''
+ self.BinaryModule = ''
+ self.Shadow = ''
+ self.CustomMakefile = {}
+ self.Specification = {}
+ self.LibraryClass = []
+ self.ModuleEntryPointList = []
+ self.ModuleUnloadImageList = []
+ self.ConstructorList = []
+ self.DestructorList = []
+
+ self.Binaries = []
+ self.Sources = []
+ self.LibraryClasses = OrderedDict()
+ self.Libraries = []
+ self.Protocols = []
+ self.Ppis = []
+ self.Guids = []
+ self.Includes = []
+ self.Packages = []
+ self.Pcds = {}
+ self.BuildOptions = {}
+ self.Depex = {}
+ self.StrPcdSet = []
+ self.StrPcdOverallValue = {}
+
+ ## Convert the class to a string
+ #
+ # Convert member MetaFile of the class to a string
+ #
+ # @retval string Formatted String
+ #
+ def __str__(self):
+ return str(self.MetaFile)
+
+ ## Override __eq__ function
+ #
+ # Check whether ModuleBuildClassObjects are the same
+ #
+ # @retval False The two ModuleBuildClassObjects are different
+ # @retval True The two ModuleBuildClassObjects are the same
+ #
+ def __eq__(self, Other):
+ return self.MetaFile == Other
+
+ ## Override __hash__ function
+ #
+ # Use MetaFile as key in hash table
+ #
+ # @retval string Key for hash table
+ #
+ def __hash__(self):
+ return hash(self.MetaFile)
+
+## PackageBuildClassObject
+#
+# This Class defines PackageBuildClass
+#
+# @param object: Inherited from object class
+#
+# @var MetaFile: To store value for package meta file path
+# @var PackageName: To store value for PackageName
+# @var Guid: To store value for Guid
+# @var Version: To store value for Version
+# @var Protocols: To store value for Protocols, it is a set structure as
+# { [ProtocolName] : Protocol Guid, ... }
+# @var Ppis: To store value for Ppis, it is a set structure as
+# { [PpiName] : Ppi Guid, ... }
+# @var Guids: To store value for Guids, it is a set structure as
+# { [GuidName] : Guid, ... }
+# @var Includes: To store value for Includes, it is a list structure as
+# [ IncludePath, ... ]
+# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as
+# { [LibraryClassName] : LibraryClassInfFile }
+# @var Pcds: To store value for Pcds, it is a set structure as
+# { [(PcdCName, PcdGuidCName)] : PcdClassObject}
+#
+class PackageBuildClassObject(object):
+ def __init__(self):
+ self.MetaFile = ''
+ self.PackageName = ''
+ self.Guid = ''
+ self.Version = ''
+
+ self.Protocols = {}
+ self.Ppis = {}
+ self.Guids = {}
+ self.Includes = []
+ self.LibraryClasses = {}
+ self.Pcds = {}
+
+ ## Convert the class to a string
+ #
+ # Convert member MetaFile of the class to a string
+ #
+ # @retval string Formatted String
+ #
+ def __str__(self):
+ return str(self.MetaFile)
+
+ ## Override __eq__ function
+ #
+ # Check whether PackageBuildClassObjects are the same
+ #
+ # @retval False The two PackageBuildClassObjects are different
+ # @retval True The two PackageBuildClassObjects are the same
+ #
+ def __eq__(self, Other):
+ return self.MetaFile == Other
+
+ ## Override __hash__ function
+ #
+ # Use MetaFile as key in hash table
+ #
+ # @retval string Key for hash table
+ #
+ def __hash__(self):
+ return hash(self.MetaFile)
+
+## PlatformBuildClassObject
+#
+# This Class defines PlatformBuildClass
+#
+# @param object: Inherited from object class
+#
+# @var MetaFile: To store value for platform meta-file path
+# @var PlatformName: To store value for PlatformName
+# @var Guid: To store value for Guid
+# @var Version: To store value for Version
+# @var DscSpecification: To store value for DscSpecification
+# @var OutputDirectory: To store value for OutputDirectory
+# @var FlashDefinition: To store value for FlashDefinition
+# @var BuildNumber: To store value for BuildNumber
+# @var MakefileName: To store value for MakefileName
+# @var SkuIds: To store value for SkuIds, it is a set structure as
+# { 'SkuName' : SkuId, '!include' : includefilename, ...}
+# @var Modules: To store value for Modules, it is a list structure as
+# [ InfFileName, ... ]
+# @var Libraries: To store value for Libraries, it is a list structure as
+# [ InfFileName, ... ]
+# @var LibraryClasses: To store value for LibraryClasses, it is a set structure as
+# { (LibraryClassName, ModuleType) : LibraryClassInfFile }
+# @var Pcds: To store value for Pcds, it is a set structure as
+# { [(PcdCName, PcdGuidCName)] : PcdClassObject }
+# @var BuildOptions: To store value for BuildOptions, it is a set structure as
+# { [BuildOptionKey] : BuildOptionValue }
+#
+class PlatformBuildClassObject(object):
+ def __init__(self):
+ self.MetaFile = ''
+ self.PlatformName = ''
+ self.Guid = ''
+ self.Version = ''
+ self.DscSpecification = ''
+ self.OutputDirectory = ''
+ self.FlashDefinition = ''
+ self.BuildNumber = ''
+ self.MakefileName = ''
+
+ self.SkuIds = {}
+ self.Modules = []
+ self.LibraryInstances = []
+ self.LibraryClasses = {}
+ self.Libraries = {}
+ self.Pcds = {}
+ self.BuildOptions = {}
+
+ ## Convert the class to a string
+ #
+ # Convert member MetaFile of the class to a string
+ #
+ # @retval string Formatted String
+ #
+ def __str__(self):
+ return str(self.MetaFile)
+
+ ## Override __eq__ function
+ #
+ # Check whether PlatformBuildClassObjects are the same
+ #
+ # @retval False The two PlatformBuildClassObjects are different
+ # @retval True The two PlatformBuildClassObjects are the same
+ #
+ def __eq__(self, Other):
+ return self.MetaFile == Other
+
+ ## Override __hash__ function
+ #
+ # Use MetaFile as key in hash table
+ #
+ # @retval string Key for hash table
+ #
+ def __hash__(self):
+ return hash(self.MetaFile)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DecBuildData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DecBuildData.py
new file mode 100755
index 00000000..78377286
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DecBuildData.py
@@ -0,0 +1,475 @@
+## @file
+# This file is used to create a database used by build tool
+#
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+from Common.StringUtils import *
+from Common.DataType import *
+from Common.Misc import *
+from types import *
+from collections import OrderedDict
+from CommonDataClass.DataClass import *
+from Workspace.BuildClassObject import PackageBuildClassObject, StructurePcd, PcdClassObject
+from Common.GlobalData import gGlobalDefines
+from re import compile
+
+## Platform build information from DEC file
+#
+# This class is used to retrieve information stored in database and convert them
+# into PackageBuildClassObject form for easier use for AutoGen.
+#
+class DecBuildData(PackageBuildClassObject):
+ # dict used to convert PCD type in database to string used by build tool
+ _PCD_TYPE_STRING_ = {
+ MODEL_PCD_FIXED_AT_BUILD : TAB_PCDS_FIXED_AT_BUILD,
+ MODEL_PCD_PATCHABLE_IN_MODULE : TAB_PCDS_PATCHABLE_IN_MODULE,
+ MODEL_PCD_FEATURE_FLAG : TAB_PCDS_FEATURE_FLAG,
+ MODEL_PCD_DYNAMIC : TAB_PCDS_DYNAMIC,
+ MODEL_PCD_DYNAMIC_DEFAULT : TAB_PCDS_DYNAMIC,
+ MODEL_PCD_DYNAMIC_HII : TAB_PCDS_DYNAMIC_HII,
+ MODEL_PCD_DYNAMIC_VPD : TAB_PCDS_DYNAMIC_VPD,
+ MODEL_PCD_DYNAMIC_EX : TAB_PCDS_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC_EX_DEFAULT : TAB_PCDS_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC_EX_HII : TAB_PCDS_DYNAMIC_EX_HII,
+ MODEL_PCD_DYNAMIC_EX_VPD : TAB_PCDS_DYNAMIC_EX_VPD,
+ }
+
+ # dict used to convert part of [Defines] to members of DecBuildData directly
+ _PROPERTY_ = {
+ #
+ # Required Fields
+ #
+ TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName",
+ TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid",
+ TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version",
+ TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile",
+ }
+
+
+ ## Constructor of DecBuildData
+ #
+ # Initialize object of DecBuildData
+ #
+ # @param FilePath The path of package description file
+ # @param RawData The raw data of DEC file
+ # @param BuildDataBase Database used to retrieve module information
+ # @param Arch The target architecture
+ # @param Platform (not used for DecBuildData)
+ # @param Macros Macros used for replacement in DSC file
+ #
+ def __init__(self, File, RawData, BuildDataBase, Arch=TAB_ARCH_COMMON, Target=None, Toolchain=None):
+ self.MetaFile = File
+ self._PackageDir = File.Dir
+ self._RawData = RawData
+ self._Bdb = BuildDataBase
+ self._Arch = Arch
+ self._Target = Target
+ self._Toolchain = Toolchain
+ self._Clear()
+
+ ## XXX[key] = value
+ def __setitem__(self, key, value):
+ self.__dict__[self._PROPERTY_[key]] = value
+
+ ## value = XXX[key]
+ def __getitem__(self, key):
+ return self.__dict__[self._PROPERTY_[key]]
+
+ ## "in" test support
+ def __contains__(self, key):
+ return key in self._PROPERTY_
+
+ ## Set all internal used members of DecBuildData to None
+ def _Clear(self):
+ self._Header = None
+ self._PackageName = None
+ self._Guid = None
+ self._Version = None
+ self._PkgUniFile = None
+ self._Protocols = None
+ self._Ppis = None
+ self._Guids = None
+ self._Includes = None
+ self._CommonIncludes = None
+ self._LibraryClasses = None
+ self._Pcds = None
+ self._MacroDict = None
+ self._PrivateProtocols = None
+ self._PrivatePpis = None
+ self._PrivateGuids = None
+ self._PrivateIncludes = None
+
+ ## Get current effective macros
+ @property
+ def _Macros(self):
+ if self._MacroDict is None:
+ self._MacroDict = dict(gGlobalDefines)
+ return self._MacroDict
+
+ ## Get architecture
+ @property
+ def Arch(self):
+ return self._Arch
+
+ ## Retrieve all information in [Defines] section
+ #
+ # (Retrieving all [Defines] information in one-shot is just to save time.)
+ #
+ def _GetHeaderInfo(self):
+ RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
+ for Record in RecordList:
+ Name = Record[1]
+ if Name in self:
+ self[Name] = Record[2]
+ self._Header = 'DUMMY'
+
+ ## Retrieve package name
+ @property
+ def PackageName(self):
+ if self._PackageName is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._PackageName is None:
+ EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
+ return self._PackageName
+
+ ## Retrieve file guid
+ @property
+ def PackageName(self):
+ if self._Guid is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._Guid is None:
+ EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
+ return self._Guid
+
+ ## Retrieve package version
+ @property
+ def Version(self):
+ if self._Version is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._Version is None:
+ self._Version = ''
+ return self._Version
+
+ ## Retrieve protocol definitions (name/value pairs)
+ @property
+ def Protocols(self):
+ if self._Protocols is None:
+ #
+ # tdict is a special kind of dict, used for selecting correct
+ # protocol definition for given ARCH
+ #
+ ProtocolDict = tdict(True)
+ PrivateProtocolDict = tdict(True)
+ NameList = []
+ PrivateNameList = []
+ PublicNameList = []
+ # find out all protocol definitions for specific and 'common' arch
+ RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
+ for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
+ if PrivateFlag == 'PRIVATE':
+ if Name not in PrivateNameList:
+ PrivateNameList.append(Name)
+ PrivateProtocolDict[Arch, Name] = Guid
+ if Name in PublicNameList:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
+ else:
+ if Name not in PublicNameList:
+ PublicNameList.append(Name)
+ if Name in PrivateNameList:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
+ if Name not in NameList:
+ NameList.append(Name)
+ ProtocolDict[Arch, Name] = Guid
+ # use OrderedDict to keep the order
+ self._Protocols = OrderedDict()
+ self._PrivateProtocols = OrderedDict()
+ for Name in NameList:
+ #
+ # limit the ARCH to self._Arch, if no self._Arch found, tdict
+ # will automatically turn to 'common' ARCH for trying
+ #
+ self._Protocols[Name] = ProtocolDict[self._Arch, Name]
+ for Name in PrivateNameList:
+ self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name]
+ return self._Protocols
+
+ ## Retrieve PPI definitions (name/value pairs)
+ @property
+ def Ppis(self):
+ if self._Ppis is None:
+ #
+ # tdict is a special kind of dict, used for selecting correct
+ # PPI definition for given ARCH
+ #
+ PpiDict = tdict(True)
+ PrivatePpiDict = tdict(True)
+ NameList = []
+ PrivateNameList = []
+ PublicNameList = []
+ # find out all PPI definitions for specific arch and 'common' arch
+ RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
+ for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
+ if PrivateFlag == 'PRIVATE':
+ if Name not in PrivateNameList:
+ PrivateNameList.append(Name)
+ PrivatePpiDict[Arch, Name] = Guid
+ if Name in PublicNameList:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
+ else:
+ if Name not in PublicNameList:
+ PublicNameList.append(Name)
+ if Name in PrivateNameList:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
+ if Name not in NameList:
+ NameList.append(Name)
+ PpiDict[Arch, Name] = Guid
+ # use OrderedDict to keep the order
+ self._Ppis = OrderedDict()
+ self._PrivatePpis = OrderedDict()
+ for Name in NameList:
+ #
+ # limit the ARCH to self._Arch, if no self._Arch found, tdict
+ # will automatically turn to 'common' ARCH for trying
+ #
+ self._Ppis[Name] = PpiDict[self._Arch, Name]
+ for Name in PrivateNameList:
+ self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name]
+ return self._Ppis
+
+ ## Retrieve GUID definitions (name/value pairs)
+ @property
+ def Guids(self):
+ if self._Guids is None:
+ #
+ # tdict is a special kind of dict, used for selecting correct
+ # GUID definition for given ARCH
+ #
+ GuidDict = tdict(True)
+ PrivateGuidDict = tdict(True)
+ NameList = []
+ PrivateNameList = []
+ PublicNameList = []
+ # find out all protocol definitions for specific and 'common' arch
+ RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
+ for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
+ if PrivateFlag == 'PRIVATE':
+ if Name not in PrivateNameList:
+ PrivateNameList.append(Name)
+ PrivateGuidDict[Arch, Name] = Guid
+ if Name in PublicNameList:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
+ else:
+ if Name not in PublicNameList:
+ PublicNameList.append(Name)
+ if Name in PrivateNameList:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
+ if Name not in NameList:
+ NameList.append(Name)
+ GuidDict[Arch, Name] = Guid
+ # use OrderedDict to keep the order
+ self._Guids = OrderedDict()
+ self._PrivateGuids = OrderedDict()
+ for Name in NameList:
+ #
+ # limit the ARCH to self._Arch, if no self._Arch found, tdict
+ # will automatically turn to 'common' ARCH for trying
+ #
+ self._Guids[Name] = GuidDict[self._Arch, Name]
+ for Name in PrivateNameList:
+ self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name]
+ return self._Guids
+
+ ## Retrieve public include paths declared in this package
+ @property
+ def Includes(self):
+ if self._Includes is None or self._CommonIncludes is None:
+ self._CommonIncludes = []
+ self._Includes = []
+ self._PrivateIncludes = []
+ PublicInclues = []
+ RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
+ Macros = self._Macros
+ for Record in RecordList:
+ File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)
+ LineNo = Record[-1]
+ # validate the path
+ ErrorCode, ErrorInfo = File.Validate()
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+
+ # avoid duplicate include path
+ if File not in self._Includes:
+ self._Includes.append(File)
+ if Record[4] == 'PRIVATE':
+ if File not in self._PrivateIncludes:
+ self._PrivateIncludes.append(File)
+ if File in PublicInclues:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)
+ else:
+ if File not in PublicInclues:
+ PublicInclues.append(File)
+ if File in self._PrivateIncludes:
+ EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)
+ if Record[3] == TAB_COMMON:
+ self._CommonIncludes.append(File)
+ return self._Includes
+
+ ## Retrieve library class declarations (not used in build at present)
+ @property
+ def LibraryClasses(self):
+ if self._LibraryClasses is None:
+ #
+ # tdict is a special kind of dict, used for selecting correct
+ # library class declaration for given ARCH
+ #
+ LibraryClassDict = tdict(True)
+ LibraryClassSet = set()
+ RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
+ Macros = self._Macros
+ for LibraryClass, File, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
+ File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)
+ # check the file validation
+ ErrorCode, ErrorInfo = File.Validate()
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+ LibraryClassSet.add(LibraryClass)
+ LibraryClassDict[Arch, LibraryClass] = File
+ self._LibraryClasses = OrderedDict()
+ for LibraryClass in LibraryClassSet:
+ self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
+ return self._LibraryClasses
+
+ ## Retrieve PCD declarations
+ @property
+ def Pcds(self):
+ if self._Pcds is None:
+ self._Pcds = OrderedDict()
+ self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
+ self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
+ self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
+ self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
+ self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
+ return self._Pcds
+
+ def ParsePcdName(self,TokenCName):
+ TokenCName = TokenCName.strip()
+ if TokenCName.startswith("["):
+ if "." in TokenCName:
+ Demesionattr = TokenCName[:TokenCName.index(".")]
+ Fields = TokenCName[TokenCName.index(".")+1:]
+ else:
+ Demesionattr = TokenCName
+ Fields = ""
+ else:
+ Demesionattr = ""
+ Fields = TokenCName
+
+ return Demesionattr,Fields
+
+ def ProcessStructurePcd(self, StructurePcdRawDataSet):
+ s_pcd_set = OrderedDict()
+ for s_pcd, LineNo in StructurePcdRawDataSet:
+ if s_pcd.TokenSpaceGuidCName not in s_pcd_set:
+ s_pcd_set[s_pcd.TokenSpaceGuidCName] = []
+ s_pcd_set[s_pcd.TokenSpaceGuidCName].append((s_pcd, LineNo))
+
+ str_pcd_set = []
+ for pcdname in s_pcd_set:
+ dep_pkgs = []
+ struct_pcd = StructurePcd()
+ for item, LineNo in s_pcd_set[pcdname]:
+ if not item.TokenCName:
+ continue
+ if "<HeaderFiles>" in item.TokenCName:
+ struct_pcd.StructuredPcdIncludeFile.append(item.DefaultValue)
+ elif "<Packages>" in item.TokenCName:
+ dep_pkgs.append(item.DefaultValue)
+ elif item.DatumType == item.TokenCName:
+ struct_pcd.copy(item)
+ struct_pcd.TokenValue = struct_pcd.TokenValue.strip("{").strip()
+ struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName = pcdname.split(".")
+ struct_pcd.PcdDefineLineNo = LineNo
+ struct_pcd.PkgPath = self.MetaFile.File
+ struct_pcd.SetDecDefaultValue(item.DefaultValue,self.MetaFile.File,LineNo)
+ else:
+ DemesionAttr, Fields = self.ParsePcdName(item.TokenCName)
+ struct_pcd.AddDefaultValue(Fields, item.DefaultValue, self.MetaFile.File, LineNo,DemesionAttr)
+
+ struct_pcd.PackageDecs = dep_pkgs
+ str_pcd_set.append(struct_pcd)
+ return str_pcd_set
+
+ ## Retrieve PCD declarations for given type
+ def _GetPcd(self, Type):
+ Pcds = OrderedDict()
+ #
+ # tdict is a special kind of dict, used for selecting correct
+ # PCD declaration for given ARCH
+ #
+ PcdDict = tdict(True, 3)
+ # for summarizing PCD
+ PcdSet = []
+ # find out all PCDs of the 'type'
+
+ StrPcdSet = []
+ RecordList = self._RawData[Type, self._Arch]
+ for TokenSpaceGuid, PcdCName, Setting, Arch, PrivateFlag, Dummy1, Dummy2 in RecordList:
+ PcdDict[Arch, PcdCName, TokenSpaceGuid] = (Setting, Dummy2)
+ if not (PcdCName, TokenSpaceGuid) in PcdSet:
+ PcdSet.append((PcdCName, TokenSpaceGuid))
+
+ DefinitionPosition = {}
+ for PcdCName, TokenSpaceGuid in PcdSet:
+ #
+ # limit the ARCH to self._Arch, if no self._Arch found, tdict
+ # will automatically turn to 'common' ARCH and try again
+ #
+ Setting, LineNo = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
+ if Setting is None:
+ continue
+
+ DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)
+ validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName)
+ PcdObj = PcdClassObject(
+ PcdCName,
+ TokenSpaceGuid,
+ self._PCD_TYPE_STRING_[Type],
+ DatumType,
+ DefaultValue,
+ TokenNumber,
+ '',
+ {},
+ False,
+ None,
+ list(validateranges),
+ list(validlists),
+ list(expressions)
+ )
+ DefinitionPosition[PcdObj] = (self.MetaFile.File, LineNo)
+ if "." in TokenSpaceGuid:
+ StrPcdSet.append((PcdObj, LineNo))
+ else:
+ Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdObj
+
+ StructurePcds = self.ProcessStructurePcd(StrPcdSet)
+ for pcd in StructurePcds:
+ Pcds[pcd.TokenCName, pcd.TokenSpaceGuidCName, self._PCD_TYPE_STRING_[Type]] = pcd
+ StructPattern = compile(r'[_a-zA-Z][0-9A-Za-z_]*$')
+ for pcd in Pcds.values():
+ if pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
+ if not pcd.IsAggregateDatumType():
+ EdkLogger.error('build', FORMAT_INVALID, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", DefinitionPosition[pcd][0], DefinitionPosition[pcd][1])
+ elif not pcd.IsArray() and not pcd.StructuredPcdIncludeFile:
+ EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "The structure Pcd %s.%s header file is not found in %s line %s \n" % (pcd.TokenSpaceGuidCName, pcd.TokenCName, pcd.DefinitionPosition[0], pcd.DefinitionPosition[1] ))
+ return Pcds
+
+ @property
+ def CommonIncludes(self):
+ if self._CommonIncludes is None:
+ self.Includes
+ return self._CommonIncludes
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py
new file mode 100755
index 00000000..eeefc9f5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -0,0 +1,3588 @@
+## @file
+# This file is used to create a database used by build tool
+#
+# Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+## Platform build information from DSC file
+#
+# This class is used to retrieve information stored in database and convert them
+# into PlatformBuildClassObject form for easier use for AutoGen.
+#
+from __future__ import print_function
+from __future__ import absolute_import
+from Common.StringUtils import *
+from Common.DataType import *
+from Common.Misc import *
+from types import *
+from Common.Expression import *
+from CommonDataClass.CommonClass import SkuInfoClass
+from Common.TargetTxtClassObject import TargetTxtDict
+from Common.ToolDefClassObject import ToolDefDict
+from .MetaDataTable import *
+from .MetaFileTable import *
+from .MetaFileParser import *
+
+from .WorkspaceCommon import GetDeclaredPcd
+from Common.Misc import AnalyzeDscPcd
+from Common.Misc import ProcessDuplicatedInf,RemoveCComments,ArrayIndex
+import re
+from Common.Parsing import IsValidWord
+from Common.VariableAttributes import VariableAttributes
+import Common.GlobalData as GlobalData
+import subprocess
+from functools import reduce
+from Common.Misc import SaveFileOnChange
+from Workspace.BuildClassObject import PlatformBuildClassObject, StructurePcd, PcdClassObject, ModuleBuildClassObject
+from collections import OrderedDict, defaultdict
+
+def _IsFieldValueAnArray (Value):
+ Value = Value.strip()
+ if Value.startswith(TAB_GUID) and Value.endswith(')'):
+ return True
+ if Value.startswith('L"') and Value.endswith('"') and len(list(Value[2:-1])) > 1:
+ return True
+ if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
+ return True
+ if Value[0] == '{' and Value[-1] == '}':
+ return True
+ if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
+ return True
+ if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
+ return True
+ return False
+
+PcdValueInitName = 'PcdValueInit'
+PcdValueCommonName = 'PcdValueCommon'
+
+PcdMainCHeader = '''
+/**
+ DO NOT EDIT
+ FILE auto-generated
+**/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <PcdValueCommon.h>
+'''
+
+PcdMainCEntry = '''
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return PcdValueMain (argc, argv);
+}
+'''
+
+PcdMakefileHeader = '''
+#
+# DO NOT EDIT
+# This file is auto-generated by build utility
+#
+
+'''
+
+WindowsCFLAGS = 'CFLAGS = $(CFLAGS) /wd4200 /wd4034 /wd4101 '
+LinuxCFLAGS = 'BUILD_CFLAGS += -Wno-pointer-to-int-cast -Wno-unused-variable '
+PcdMakefileEnd = '''
+!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common
+!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app
+'''
+
+AppTarget = '''
+all: $(APPFILE)
+$(APPFILE): $(OBJECTS)
+%s
+'''
+
+PcdGccMakefile = '''
+MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C
+LIBS = -lCommon
+'''
+
+variablePattern = re.compile(r'[\t\s]*0[xX][a-fA-F0-9]+$')
+SkuIdPattern = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$')
+## regular expressions for finding decimal and hex numbers
+Pattern = re.compile('^[1-9]\d*|0$')
+HexPattern = re.compile(r'0[xX][0-9a-fA-F]+$')
+## Regular expression for finding header file inclusions
+from AutoGen.GenMake import gIncludePattern
+
+## Find dependencies for one source file
+#
+# By searching recursively "#include" directive in file, find out all the
+# files needed by given source file. The dependecies will be only searched
+# in given search path list.
+#
+# @param SearchPathList The list of search path
+#
+# @retval list The list of files the given source file depends on
+#
+def GetDependencyList(FileStack, SearchPathList):
+ DepDb = dict()
+ DependencySet = set(FileStack)
+ while len(FileStack) > 0:
+ F = FileStack.pop()
+ FullPathDependList = []
+ CurrentFileDependencyList = []
+ if F in DepDb:
+ CurrentFileDependencyList = DepDb[F]
+ else:
+ try:
+ Fd = open(F, 'r')
+ FileContent = Fd.read()
+ except BaseException as X:
+ EdkLogger.error("build", FILE_OPEN_FAILURE, ExtraData=F + "\n\t" + str(X))
+ finally:
+ if "Fd" in dir(locals()):
+ Fd.close()
+
+ if len(FileContent) == 0:
+ continue
+
+ try:
+ if FileContent[0] == 0xff or FileContent[0] == 0xfe:
+ FileContent = FileContent.decode('utf-16')
+ else:
+ FileContent = FileContent.decode()
+ except:
+ # The file is not txt file. for example .mcb file
+ continue
+ IncludedFileList = gIncludePattern.findall(FileContent)
+
+ for Inc in IncludedFileList:
+ Inc = Inc.strip()
+ Inc = os.path.normpath(Inc)
+ CurrentFileDependencyList.append(Inc)
+ DepDb[F] = CurrentFileDependencyList
+
+ CurrentFilePath = os.path.dirname(F)
+ PathList = [CurrentFilePath] + SearchPathList
+ for Inc in CurrentFileDependencyList:
+ for SearchPath in PathList:
+ FilePath = os.path.join(SearchPath, Inc)
+ if not os.path.exists(FilePath):
+ continue
+ if FilePath not in DependencySet:
+ FileStack.append(FilePath)
+ FullPathDependList.append(FilePath)
+ break
+ DependencySet.update(FullPathDependList)
+ DependencyList = list(DependencySet) # remove duplicate ones
+
+ return DependencyList
+
+class DscBuildData(PlatformBuildClassObject):
+ # dict used to convert PCD type in database to string used by build tool
+ _PCD_TYPE_STRING_ = {
+ MODEL_PCD_FIXED_AT_BUILD : TAB_PCDS_FIXED_AT_BUILD,
+ MODEL_PCD_PATCHABLE_IN_MODULE : TAB_PCDS_PATCHABLE_IN_MODULE,
+ MODEL_PCD_FEATURE_FLAG : TAB_PCDS_FEATURE_FLAG,
+ MODEL_PCD_DYNAMIC : TAB_PCDS_DYNAMIC,
+ MODEL_PCD_DYNAMIC_DEFAULT : TAB_PCDS_DYNAMIC,
+ MODEL_PCD_DYNAMIC_HII : TAB_PCDS_DYNAMIC_HII,
+ MODEL_PCD_DYNAMIC_VPD : TAB_PCDS_DYNAMIC_VPD,
+ MODEL_PCD_DYNAMIC_EX : TAB_PCDS_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC_EX_DEFAULT : TAB_PCDS_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC_EX_HII : TAB_PCDS_DYNAMIC_EX_HII,
+ MODEL_PCD_DYNAMIC_EX_VPD : TAB_PCDS_DYNAMIC_EX_VPD,
+ }
+
+ # dict used to convert part of [Defines] to members of DscBuildData directly
+ _PROPERTY_ = {
+ #
+ # Required Fields
+ #
+ TAB_DSC_DEFINES_PLATFORM_NAME : "_PlatformName",
+ TAB_DSC_DEFINES_PLATFORM_GUID : "_Guid",
+ TAB_DSC_DEFINES_PLATFORM_VERSION : "_Version",
+ TAB_DSC_DEFINES_DSC_SPECIFICATION : "_DscSpecification",
+ # TAB_DSC_DEFINES_OUTPUT_DIRECTORY : "_OutputDirectory",
+ # TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES : "_SupArchList",
+ # TAB_DSC_DEFINES_BUILD_TARGETS : "_BuildTargets",
+ TAB_DSC_DEFINES_SKUID_IDENTIFIER : "_SkuName",
+ # TAB_DSC_DEFINES_FLASH_DEFINITION : "_FlashDefinition",
+ TAB_DSC_DEFINES_BUILD_NUMBER : "_BuildNumber",
+ TAB_DSC_DEFINES_MAKEFILE_NAME : "_MakefileName",
+ TAB_DSC_DEFINES_BS_BASE_ADDRESS : "_BsBaseAddress",
+ TAB_DSC_DEFINES_RT_BASE_ADDRESS : "_RtBaseAddress",
+ # TAB_DSC_DEFINES_RFC_LANGUAGES : "_RFCLanguages",
+ # TAB_DSC_DEFINES_ISO_LANGUAGES : "_ISOLanguages",
+ }
+
+ # used to compose dummy library class name for those forced library instances
+ _NullLibraryNumber = 0
+
+ ## Constructor of DscBuildData
+ #
+ # Initialize object of DscBuildData
+ #
+ # @param FilePath The path of platform description file
+ # @param RawData The raw data of DSC file
+ # @param BuildDataBase Database used to retrieve module/package information
+ # @param Arch The target architecture
+ # @param Platform (not used for DscBuildData)
+ # @param Macros Macros used for replacement in DSC file
+ #
+ def __init__(self, FilePath, RawData, BuildDataBase, Arch=TAB_ARCH_COMMON, Target=None, Toolchain=None):
+ self.MetaFile = FilePath
+ self._RawData = RawData
+ self._Bdb = BuildDataBase
+ self._Arch = Arch
+ self._Target = Target
+ self._Toolchain = Toolchain
+ self._ToolChainFamily = None
+ self._Clear()
+ self.WorkspaceDir = os.getenv("WORKSPACE") if os.getenv("WORKSPACE") else ""
+ self.DefaultStores = None
+ self.SkuIdMgr = SkuClass(self.SkuName, self.SkuIds)
+
+ @property
+ def OutputPath(self):
+ if os.getenv("WORKSPACE"):
+ return os.path.join(os.getenv("WORKSPACE"), self.OutputDirectory, self._Target + "_" + self._Toolchain, PcdValueInitName)
+ else:
+ return os.path.dirname(self.DscFile)
+
+ ## XXX[key] = value
+ def __setitem__(self, key, value):
+ self.__dict__[self._PROPERTY_[key]] = value
+
+ ## value = XXX[key]
+ def __getitem__(self, key):
+ return self.__dict__[self._PROPERTY_[key]]
+
+ ## "in" test support
+ def __contains__(self, key):
+ return key in self._PROPERTY_
+
+ ## Set all internal used members of DscBuildData to None
+ def _Clear(self):
+ self._Header = None
+ self._PlatformName = None
+ self._Guid = None
+ self._Version = None
+ self._DscSpecification = None
+ self._OutputDirectory = None
+ self._SupArchList = None
+ self._BuildTargets = None
+ self._SkuName = None
+ self._PcdInfoFlag = None
+ self._VarCheckFlag = None
+ self._FlashDefinition = None
+ self._Prebuild = None
+ self._Postbuild = None
+ self._BuildNumber = None
+ self._MakefileName = None
+ self._BsBaseAddress = None
+ self._RtBaseAddress = None
+ self._SkuIds = None
+ self._Modules = None
+ self._LibraryInstances = None
+ self._LibraryClasses = None
+ self._Pcds = None
+ self._DecPcds = None
+ self._BuildOptions = None
+ self._ModuleTypeOptions = None
+ self._LoadFixAddress = None
+ self._RFCLanguages = None
+ self._ISOLanguages = None
+ self._VpdToolGuid = None
+ self._MacroDict = None
+ self.DefaultStores = None
+
+ ## Get current effective macros
+ @property
+ def _Macros(self):
+ if self._MacroDict is None:
+ self._MacroDict = {}
+ self._MacroDict.update(GlobalData.gPlatformDefines)
+ self._MacroDict.update(GlobalData.gGlobalDefines)
+ self._MacroDict.update(GlobalData.gCommandLineDefines)
+ return self._MacroDict
+
+ ## Get architecture
+ @property
+ def Arch(self):
+ return self._Arch
+ @property
+ def Dir(self):
+ return self.MetaFile.Dir
+
+ ## Retrieve all information in [Defines] section
+ #
+ # (Retrieving all [Defines] information in one-shot is just to save time.)
+ #
+ def _GetHeaderInfo(self):
+ RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
+ for Record in RecordList:
+ Name = Record[1]
+ # items defined _PROPERTY_ don't need additional processing
+
+ # some special items in [Defines] section need special treatment
+ if Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:
+ self._OutputDirectory = NormPath(Record[2], self._Macros)
+ if ' ' in self._OutputDirectory:
+ EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY",
+ File=self.MetaFile, Line=Record[-1],
+ ExtraData=self._OutputDirectory)
+ elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:
+ self._FlashDefinition = PathClass(NormPath(Record[2], self._Macros), GlobalData.gWorkspace)
+ ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf')
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1],
+ ExtraData=ErrorInfo)
+ elif Name == TAB_DSC_PREBUILD:
+ PrebuildValue = Record[2]
+ if Record[2][0] == '"':
+ if Record[2][-1] != '"':
+ EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_PREBUILD,
+ File=self.MetaFile, Line=Record[-1])
+ PrebuildValue = Record[2][1:-1]
+ self._Prebuild = PrebuildValue
+ elif Name == TAB_DSC_POSTBUILD:
+ PostbuildValue = Record[2]
+ if Record[2][0] == '"':
+ if Record[2][-1] != '"':
+ EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_POSTBUILD,
+ File=self.MetaFile, Line=Record[-1])
+ PostbuildValue = Record[2][1:-1]
+ self._Postbuild = PostbuildValue
+ elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:
+ self._SupArchList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
+ elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:
+ self._BuildTargets = GetSplitValueList(Record[2])
+ elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:
+ if self._SkuName is None:
+ self._SkuName = Record[2]
+ if GlobalData.gSKUID_CMD:
+ self._SkuName = GlobalData.gSKUID_CMD
+ elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION:
+ self._PcdInfoFlag = Record[2]
+ elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION:
+ self._VarCheckFlag = Record[2]
+ elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:
+ try:
+ self._LoadFixAddress = int (Record[2], 0)
+ except:
+ EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (Record[2]))
+ elif Name == TAB_DSC_DEFINES_RFC_LANGUAGES:
+ if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
+ EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for RFC_LANGUAGES must have double quotes around it, for example: RFC_LANGUAGES = "en-us;zh-hans"',
+ File=self.MetaFile, Line=Record[-1])
+ LanguageCodes = Record[2][1:-1]
+ if not LanguageCodes:
+ EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more RFC4646 format language code must be provided for RFC_LANGUAGES statement',
+ File=self.MetaFile, Line=Record[-1])
+ LanguageList = GetSplitValueList(LanguageCodes, TAB_SEMI_COLON_SPLIT)
+ # check whether there is empty entries in the list
+ if None in LanguageList:
+ EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more empty language code is in RFC_LANGUAGES statement',
+ File=self.MetaFile, Line=Record[-1])
+ self._RFCLanguages = LanguageList
+ elif Name == TAB_DSC_DEFINES_ISO_LANGUAGES:
+ if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:
+ EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for ISO_LANGUAGES must have double quotes around it, for example: ISO_LANGUAGES = "engchn"',
+ File=self.MetaFile, Line=Record[-1])
+ LanguageCodes = Record[2][1:-1]
+ if not LanguageCodes:
+ EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more ISO639-2 format language code must be provided for ISO_LANGUAGES statement',
+ File=self.MetaFile, Line=Record[-1])
+ if len(LanguageCodes) % 3:
+ EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'bad ISO639-2 format for ISO_LANGUAGES',
+ File=self.MetaFile, Line=Record[-1])
+ LanguageList = []
+ for i in range(0, len(LanguageCodes), 3):
+ LanguageList.append(LanguageCodes[i:i + 3])
+ self._ISOLanguages = LanguageList
+ elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID:
+ #
+ # try to convert GUID to a real UUID value to see whether the GUID is format
+ # for VPD_TOOL_GUID is correct.
+ #
+ try:
+ uuid.UUID(Record[2])
+ except:
+ EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile)
+ self._VpdToolGuid = Record[2]
+ elif Name in self:
+ self[Name] = Record[2]
+ # set _Header to non-None in order to avoid database re-querying
+ self._Header = 'DUMMY'
+
+ ## Retrieve platform name
+ @property
+ def PlatformName(self):
+ if self._PlatformName is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._PlatformName is None:
+ EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)
+ return self._PlatformName
+
+ @property
+ def Platform(self):
+ return self.PlatformName
+
+ ## Retrieve file guid
+ @property
+ def Guid(self):
+ if self._Guid is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._Guid is None:
+ EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_GUID", File=self.MetaFile)
+ return self._Guid
+
+ ## Retrieve platform version
+ @property
+ def Version(self):
+ if self._Version is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._Version is None:
+ EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_VERSION", File=self.MetaFile)
+ return self._Version
+
+ ## Retrieve platform description file version
+ @property
+ def DscSpecification(self):
+ if self._DscSpecification is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._DscSpecification is None:
+ EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No DSC_SPECIFICATION", File=self.MetaFile)
+ return self._DscSpecification
+
+ ## Retrieve OUTPUT_DIRECTORY
+ @property
+ def OutputDirectory(self):
+ if self._OutputDirectory is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._OutputDirectory is None:
+ self._OutputDirectory = os.path.join("Build", self._PlatformName)
+ return self._OutputDirectory
+
+ ## Retrieve SUPPORTED_ARCHITECTURES
+ @property
+ def SupArchList(self):
+ if self._SupArchList is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._SupArchList is None:
+ EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No SUPPORTED_ARCHITECTURES", File=self.MetaFile)
+ return self._SupArchList
+
+ ## Retrieve BUILD_TARGETS
+ @property
+ def BuildTargets(self):
+ if self._BuildTargets is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._BuildTargets is None:
+ EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BUILD_TARGETS", File=self.MetaFile)
+ return self._BuildTargets
+
+ @property
+ def PcdInfoFlag(self):
+ if self._PcdInfoFlag is None or self._PcdInfoFlag.upper() == 'FALSE':
+ return False
+ elif self._PcdInfoFlag.upper() == 'TRUE':
+ return True
+ else:
+ return False
+
+ @property
+ def VarCheckFlag(self):
+ if self._VarCheckFlag is None or self._VarCheckFlag.upper() == 'FALSE':
+ return False
+ elif self._VarCheckFlag.upper() == 'TRUE':
+ return True
+ else:
+ return False
+
+ # # Retrieve SKUID_IDENTIFIER
+ @property
+ def SkuName(self):
+ if self._SkuName is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._SkuName is None:
+ self._SkuName = TAB_DEFAULT
+ return self._SkuName
+
+ ## Override SKUID_IDENTIFIER
+ @SkuName.setter
+ def SkuName(self, Value):
+ self._SkuName = Value
+
+ @property
+ def FlashDefinition(self):
+ if self._FlashDefinition is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._FlashDefinition is None:
+ self._FlashDefinition = ''
+ return self._FlashDefinition
+
+ @property
+ def Prebuild(self):
+ if self._Prebuild is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._Prebuild is None:
+ self._Prebuild = ''
+ return self._Prebuild
+
+ @property
+ def Postbuild(self):
+ if self._Postbuild is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._Postbuild is None:
+ self._Postbuild = ''
+ return self._Postbuild
+
+ ## Retrieve FLASH_DEFINITION
+ @property
+ def BuildNumber(self):
+ if self._BuildNumber is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._BuildNumber is None:
+ self._BuildNumber = ''
+ return self._BuildNumber
+
+ ## Retrieve MAKEFILE_NAME
+ @property
+ def MakefileName(self):
+ if self._MakefileName is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._MakefileName is None:
+ self._MakefileName = ''
+ return self._MakefileName
+
+ ## Retrieve BsBaseAddress
+ @property
+ def BsBaseAddress(self):
+ if self._BsBaseAddress is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._BsBaseAddress is None:
+ self._BsBaseAddress = ''
+ return self._BsBaseAddress
+
+ ## Retrieve RtBaseAddress
+ @property
+ def RtBaseAddress(self):
+ if self._RtBaseAddress is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._RtBaseAddress is None:
+ self._RtBaseAddress = ''
+ return self._RtBaseAddress
+
+ ## Retrieve the top address for the load fix address
+ @property
+ def LoadFixAddress(self):
+ if self._LoadFixAddress is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+
+ if self._LoadFixAddress is None:
+ self._LoadFixAddress = self._Macros.get(TAB_FIX_LOAD_TOP_MEMORY_ADDRESS, '0')
+
+ try:
+ self._LoadFixAddress = int (self._LoadFixAddress, 0)
+ except:
+ EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (self._LoadFixAddress))
+
+ #
+ # If command line defined, should override the value in DSC file.
+ #
+ if 'FIX_LOAD_TOP_MEMORY_ADDRESS' in GlobalData.gCommandLineDefines:
+ try:
+ self._LoadFixAddress = int(GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS'], 0)
+ except:
+ EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS']))
+
+ if self._LoadFixAddress < 0:
+ EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid negative value 0x%x" % (self._LoadFixAddress))
+ if self._LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self._LoadFixAddress % 0x1000 != 0:
+ EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid unaligned 4K value 0x%x" % (self._LoadFixAddress))
+
+ return self._LoadFixAddress
+
+ ## Retrieve RFCLanguage filter
+ @property
+ def RFCLanguages(self):
+ if self._RFCLanguages is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._RFCLanguages is None:
+ self._RFCLanguages = []
+ return self._RFCLanguages
+
+ ## Retrieve ISOLanguage filter
+ @property
+ def ISOLanguages(self):
+ if self._ISOLanguages is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._ISOLanguages is None:
+ self._ISOLanguages = []
+ return self._ISOLanguages
+
+ ## Retrieve the GUID string for VPD tool
+ @property
+ def VpdToolGuid(self):
+ if self._VpdToolGuid is None:
+ if self._Header is None:
+ self._GetHeaderInfo()
+ if self._VpdToolGuid is None:
+ self._VpdToolGuid = ''
+ return self._VpdToolGuid
+
+ ## Retrieve [SkuIds] section information
+ @property
+ def SkuIds(self):
+ if self._SkuIds is None:
+ self._SkuIds = OrderedDict()
+ RecordList = self._RawData[MODEL_EFI_SKU_ID, self._Arch]
+ for Record in RecordList:
+ if not Record[0]:
+ EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',
+ File=self.MetaFile, Line=Record[-1])
+ if not Record[1]:
+ EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',
+ File=self.MetaFile, Line=Record[-1])
+ if not Pattern.match(Record[0]) and not HexPattern.match(Record[0]):
+ EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID number is invalid. It only support Integer and HexNumber",
+ File=self.MetaFile, Line=Record[-1])
+ if not SkuIdPattern.match(Record[1]) or (Record[2] and not SkuIdPattern.match(Record[2])):
+ EdkLogger.error('build', FORMAT_INVALID, "The format of the Sku ID name is invalid. The correct format is '(a-zA-Z_)(a-zA-Z0-9_)*'",
+ File=self.MetaFile, Line=Record[-1])
+ self._SkuIds[Record[1].upper()] = (str(DscBuildData.ToInt(Record[0])), Record[1].upper(), Record[2].upper())
+ if TAB_DEFAULT not in self._SkuIds:
+ self._SkuIds[TAB_DEFAULT] = ("0", TAB_DEFAULT, TAB_DEFAULT)
+ if TAB_COMMON not in self._SkuIds:
+ self._SkuIds[TAB_COMMON] = ("0", TAB_DEFAULT, TAB_DEFAULT)
+ return self._SkuIds
+
+ @staticmethod
+ def ToInt(intstr):
+ return int(intstr, 16) if intstr.upper().startswith("0X") else int(intstr)
+
+ def _GetDefaultStores(self):
+ if self.DefaultStores is None:
+ self.DefaultStores = OrderedDict()
+ RecordList = self._RawData[MODEL_EFI_DEFAULT_STORES, self._Arch]
+ for Record in RecordList:
+ if not Record[0]:
+ EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID number',
+ File=self.MetaFile, Line=Record[-1])
+ if not Record[1]:
+ EdkLogger.error('build', FORMAT_INVALID, 'No DefaultStores ID name',
+ File=self.MetaFile, Line=Record[-1])
+ if not Pattern.match(Record[0]) and not HexPattern.match(Record[0]):
+ EdkLogger.error('build', FORMAT_INVALID, "The format of the DefaultStores ID number is invalid. It only support Integer and HexNumber",
+ File=self.MetaFile, Line=Record[-1])
+ if not IsValidWord(Record[1]):
+ EdkLogger.error('build', FORMAT_INVALID, "The format of the DefaultStores ID name is invalid. The correct format is '(a-zA-Z0-9_)(a-zA-Z0-9_-.)*'",
+ File=self.MetaFile, Line=Record[-1])
+ self.DefaultStores[Record[1].upper()] = (DscBuildData.ToInt(Record[0]), Record[1].upper())
+ if TAB_DEFAULT_STORES_DEFAULT not in self.DefaultStores:
+ self.DefaultStores[TAB_DEFAULT_STORES_DEFAULT] = (0, TAB_DEFAULT_STORES_DEFAULT)
+ GlobalData.gDefaultStores = sorted(self.DefaultStores.keys())
+ return self.DefaultStores
+
+ def OverrideDuplicateModule(self):
+ RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
+ Macros = self._Macros
+ Components = {}
+ for Record in RecordList:
+ ModuleId = Record[6]
+ file_guid = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]
+ file_guid_str = file_guid[0][2] if file_guid else "NULL"
+ ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+ if self._Arch != TAB_ARCH_COMMON and (file_guid_str,str(ModuleFile)) in Components:
+ self._RawData.DisableOverrideComponent(Components[(file_guid_str,str(ModuleFile))])
+ Components[(file_guid_str,str(ModuleFile))] = ModuleId
+ self._RawData._PostProcessed = False
+
+ ## Retrieve packages this Platform depends on
+ @cached_property
+ def Packages(self):
+ RetVal = set()
+ RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch]
+ Macros = self._Macros
+ for Record in RecordList:
+ File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+ # check the file validation
+ ErrorCode, ErrorInfo = File.Validate('.dec')
+ if ErrorCode != 0:
+ LineNo = Record[-1]
+ EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+ # parse this package now. we need it to get protocol/ppi/guid value
+ RetVal.add(self._Bdb[File, self._Arch, self._Target, self._Toolchain])
+ return RetVal
+
+ ## Retrieve [Components] section information
+ @property
+ def Modules(self):
+ if self._Modules is not None:
+ return self._Modules
+ self.OverrideDuplicateModule()
+ self._Modules = OrderedDict()
+ RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
+ Macros = self._Macros
+ for Record in RecordList:
+ ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+ ModuleId = Record[6]
+ LineNo = Record[7]
+
+ # check the file validation
+ ErrorCode, ErrorInfo = ModuleFile.Validate('.inf')
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
+ ExtraData=ErrorInfo)
+
+ ModuleBuildData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
+ Module = ModuleBuildClassObject()
+ Module.MetaFile = ModuleFile
+ Module.Guid = ModuleBuildData.Guid
+ # get module private library instance
+ RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]
+ for Record in RecordList:
+ LibraryClass = Record[0]
+ LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+ LineNo = Record[-1]
+
+ # check the file validation
+ ErrorCode, ErrorInfo = LibraryPath.Validate('.inf')
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
+ ExtraData=ErrorInfo)
+
+ if LibraryClass == '' or LibraryClass == 'NULL':
+ self._NullLibraryNumber += 1
+ LibraryClass = 'NULL%d' % self._NullLibraryNumber
+ EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))
+ Module.LibraryClasses[LibraryClass] = LibraryPath
+ if LibraryPath not in self.LibraryInstances:
+ self.LibraryInstances.append(LibraryPath)
+ S_PcdSet = []
+ # get module private PCD setting
+ for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \
+ MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:
+ RecordList = self._RawData[Type, self._Arch, None, ModuleId]
+ for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
+ TokenList = GetSplitValueList(Setting)
+ DefaultValue = TokenList[0]
+ # the format is PcdName| Value | VOID* | MaxDatumSize
+ if len(TokenList) > 2:
+ MaxDatumSize = TokenList[2]
+ else:
+ MaxDatumSize = ''
+ TypeString = self._PCD_TYPE_STRING_[Type]
+
+ TCName,PCName,DimensionAttr,Field = self.ParsePcdNameStruct(TokenSpaceGuid, PcdCName)
+
+ if ("." in TokenSpaceGuid or "[" in PcdCName):
+ S_PcdSet.append([ TCName,PCName,DimensionAttr,Field, ModuleBuildData.Guid, "", Dummy5, AnalyzePcdExpression(Setting)[0]])
+ DefaultValue = ''
+ if ( PCName,TCName) not in Module.Pcds:
+ Pcd = PcdClassObject(
+ PCName,
+ TCName,
+ TypeString,
+ '',
+ DefaultValue,
+ '',
+ MaxDatumSize,
+ {},
+ False,
+ None,
+ IsDsc=True)
+ Module.Pcds[PCName, TCName] = Pcd
+
+ Module.StrPcdSet = S_PcdSet
+ for TCName,PCName, _,_,_,_,_,_ in S_PcdSet:
+ if (PCName,TCName) in Module.Pcds:
+ Module.StrPcdOverallValue[(PCName,TCName)] = Module.Pcds[(PCName,TCName)].DefaultValue, self.MetaFile,Dummy5
+ # get module private build options
+ RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]
+ for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
+ if (ToolChainFamily, ToolChain) not in Module.BuildOptions:
+ Module.BuildOptions[ToolChainFamily, ToolChain] = Option
+ else:
+ OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]
+ Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
+
+ RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]
+ if RecordList:
+ if len(RecordList) != 1:
+ EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in <Defines> section.',
+ File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
+ ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace)
+ ModuleFile.Arch = self._Arch
+ Module.Guid = RecordList[0][2]
+ for item in Module.StrPcdSet:
+ item[4] = RecordList[0][2]
+ self._Modules[ModuleFile] = Module
+ return self._Modules
+
+ ## Retrieve all possible library instances used in this platform
+ @property
+ def LibraryInstances(self):
+ if self._LibraryInstances is None:
+ self.LibraryClasses
+ return self._LibraryInstances
+
+ ## Retrieve [LibraryClasses] information
+ @property
+ def LibraryClasses(self):
+ if self._LibraryClasses is None:
+ self._LibraryInstances = []
+ #
+ # tdict is a special dict kind of type, used for selecting correct
+ # library instance for given library class and module type
+ #
+ LibraryClassDict = tdict(True, 3)
+ # track all library class names
+ LibraryClassSet = set()
+ RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, -1]
+ Macros = self._Macros
+ for Record in RecordList:
+ LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, Dummy, LineNo = Record
+ if LibraryClass == '' or LibraryClass == 'NULL':
+ self._NullLibraryNumber += 1
+ LibraryClass = 'NULL%d' % self._NullLibraryNumber
+ EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass))
+ LibraryClassSet.add(LibraryClass)
+ LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch)
+ # check the file validation
+ ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf')
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
+ ExtraData=ErrorInfo)
+
+ if ModuleType != TAB_COMMON and ModuleType not in SUP_MODULE_LIST:
+ EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType,
+ File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo)
+ LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance
+ if LibraryInstance not in self._LibraryInstances:
+ self._LibraryInstances.append(LibraryInstance)
+
+ # resolve the specific library instance for each class and each module type
+ self._LibraryClasses = tdict(True)
+ for LibraryClass in LibraryClassSet:
+ # try all possible module types
+ for ModuleType in SUP_MODULE_LIST:
+ LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]
+ if LibraryInstance is None:
+ continue
+ self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance
+
+ RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]
+ for Record in RecordList:
+ File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+ LineNo = Record[-1]
+ # check the file validation
+ ErrorCode, ErrorInfo = File.Validate('.inf')
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
+ ExtraData=ErrorInfo)
+ if File not in self._LibraryInstances:
+ self._LibraryInstances.append(File)
+ #
+ # we need the module name as the library class name, so we have
+ # to parse it here. (self._Bdb[] will trigger a file parse if it
+ # hasn't been parsed)
+ #
+ Library = self._Bdb[File, self._Arch, self._Target, self._Toolchain]
+ self._LibraryClasses[Library.BaseName, ':dummy:'] = Library
+ return self._LibraryClasses
+
+ def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo):
+ if not self._DecPcds:
+
+ FdfInfList = []
+ if GlobalData.gFdfParser:
+ FdfInfList = GlobalData.gFdfParser.Profile.InfList
+
+ PkgSet = set()
+ for Inf in FdfInfList:
+ ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
+ if ModuleFile in self._Modules:
+ continue
+ ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
+ PkgSet.update(ModuleData.Packages)
+ if self.Packages:
+ PkgSet.update(self.Packages)
+ self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain, PkgSet)
+ self._GuidDict.update(GlobalData.gPlatformPcds)
+
+ if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
+ EdkLogger.error('build', PARSER_ERROR,
+ "Pcd (%s.%s) defined in DSC is not declared in DEC files referenced in INF files in FDF. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),
+ File=self.MetaFile, Line=LineNo)
+ ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType)
+ if not IsValid:
+ if PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
+ EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,
+ ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
+ else:
+ if ValueList[2] == '-1':
+ EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,
+ ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))
+ if ValueList[Index]:
+ DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
+ if "{CODE(" not in ValueList[Index]:
+ try:
+ ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
+ except BadExpression as Value:
+ EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
+ ExtraData="PCD [%s.%s] Value \"%s\" " % (
+ TokenSpaceGuid, PcdCName, ValueList[Index]))
+ except EvaluationException as Excpt:
+ if hasattr(Excpt, 'Pcd'):
+ if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
+ " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
+ " of the DSC file" % Excpt.Pcd,
+ File=self.MetaFile, Line=LineNo)
+ else:
+ EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
+ File=self.MetaFile, Line=LineNo)
+ else:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
+ File=self.MetaFile, Line=LineNo)
+
+ if ValueList[Index]:
+ Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
+ if not Valid:
+ EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
+ ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))
+ if PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
+ if self._DecPcds[PcdCName, TokenSpaceGuid].DatumType.strip() != ValueList[1].strip():
+ DecPcd = self._DecPcds[PcdCName, TokenSpaceGuid]
+ EdkLogger.error('build', FORMAT_INVALID,
+ "Pcd datumtype used in DSC file is not the same as its declaration. DatumType:%s"%DecPcd.DatumType,
+ File=self.MetaFile, Line=LineNo,
+ ExtraData="Dsc:%s.%s|%s\n Dec:%s.%s|%s|%s|%s" % (TokenSpaceGuid, PcdCName, Setting, TokenSpaceGuid, \
+ PcdCName, DecPcd.DefaultValue, DecPcd.DatumType, DecPcd.TokenValue))
+ if (TokenSpaceGuid + '.' + PcdCName) in GlobalData.gPlatformPcds:
+ if GlobalData.gPlatformPcds[TokenSpaceGuid + '.' + PcdCName] != ValueList[Index]:
+ GlobalData.gPlatformPcds[TokenSpaceGuid + '.' + PcdCName] = ValueList[Index]
+ return ValueList
+
+ def _FilterPcdBySkuUsage(self, Pcds):
+ available_sku = self.SkuIdMgr.AvailableSkuIdSet
+ sku_usage = self.SkuIdMgr.SkuUsageType
+ if sku_usage == SkuClass.SINGLE:
+ for pcdname in Pcds:
+ pcd = Pcds[pcdname]
+ Pcds[pcdname].SkuInfoList = {TAB_DEFAULT:pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
+ if isinstance(pcd, StructurePcd) and pcd.SkuOverrideValues:
+ Pcds[pcdname].SkuOverrideValues = {TAB_DEFAULT:pcd.SkuOverrideValues[skuid] for skuid in pcd.SkuOverrideValues if skuid in available_sku}
+ else:
+ for pcdname in Pcds:
+ pcd = Pcds[pcdname]
+ Pcds[pcdname].SkuInfoList = {skuid:pcd.SkuInfoList[skuid] for skuid in pcd.SkuInfoList if skuid in available_sku}
+ if isinstance(pcd, StructurePcd) and pcd.SkuOverrideValues:
+ Pcds[pcdname].SkuOverrideValues = {skuid:pcd.SkuOverrideValues[skuid] for skuid in pcd.SkuOverrideValues if skuid in available_sku}
+ return Pcds
+
+ def CompleteHiiPcdsDefaultStores(self, Pcds):
+ HiiPcd = [Pcds[pcd] for pcd in Pcds if Pcds[pcd].Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]]
+ DefaultStoreMgr = DefaultStore(self.DefaultStores)
+ for pcd in HiiPcd:
+ for skuid in pcd.SkuInfoList:
+ skuobj = pcd.SkuInfoList.get(skuid)
+ if TAB_DEFAULT_STORES_DEFAULT not in skuobj.DefaultStoreDict:
+ PcdDefaultStoreSet = set(defaultstorename for defaultstorename in skuobj.DefaultStoreDict)
+ mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)
+ skuobj.DefaultStoreDict[TAB_DEFAULT_STORES_DEFAULT] = skuobj.DefaultStoreDict[mindefaultstorename]
+ return Pcds
+
+ def RecoverCommandLinePcd(self):
+ def UpdateCommandLineValue(pcd):
+ if pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
+ pcd.PcdValueFromComm = pcd.DefaultValue
+ elif pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ pcd.PcdValueFromComm = pcd.SkuInfoList.get(TAB_DEFAULT).HiiDefaultValue
+ else:
+ pcd.PcdValueFromComm = pcd.SkuInfoList.get(TAB_DEFAULT).DefaultValue
+ for pcd in self._Pcds:
+ if isinstance(self._Pcds[pcd], StructurePcd) and (self._Pcds[pcd].PcdValueFromComm or self._Pcds[pcd].PcdFieldValueFromComm):
+ UpdateCommandLineValue(self._Pcds[pcd])
+
+ def __ParsePcdFromCommandLine(self):
+ if GlobalData.BuildOptionPcd:
+ for i, pcd in enumerate(GlobalData.BuildOptionPcd):
+ if isinstance(pcd, tuple):
+ continue
+ (pcdname, pcdvalue) = pcd.split('=')
+ if not pcdvalue:
+ EdkLogger.error('build', AUTOGEN_ERROR, "No Value specified for the PCD %s." % (pcdname))
+ if '.' in pcdname:
+ (Name1, Name2) = pcdname.split('.', 1)
+ if "." in Name2:
+ (Name3, FieldName) = Name2.split(".", 1)
+ if ((Name3, Name1)) in self.DecPcds:
+ HasTokenSpace = True
+ TokenCName = Name3
+ TokenSpaceGuidCName = Name1
+ else:
+ FieldName = Name2
+ TokenCName = Name1
+ TokenSpaceGuidCName = ''
+ HasTokenSpace = False
+ else:
+ if ((Name2, Name1)) in self.DecPcds:
+ HasTokenSpace = True
+ TokenCName = Name2
+ TokenSpaceGuidCName = Name1
+ FieldName =""
+ else:
+ FieldName = Name2
+ TokenCName = Name1
+ TokenSpaceGuidCName = ''
+ HasTokenSpace = False
+ else:
+ FieldName = ""
+ TokenCName = pcdname
+ TokenSpaceGuidCName = ''
+ HasTokenSpace = False
+ TokenSpaceGuidCNameList = []
+ FoundFlag = False
+ PcdDatumType = ''
+ DisplayName = TokenCName
+ if FieldName:
+ DisplayName = TokenCName + '.' + FieldName
+ if not HasTokenSpace:
+ for key in self.DecPcds:
+ PcdItem = self.DecPcds[key]
+ if TokenCName == PcdItem.TokenCName:
+ if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
+ if len (TokenSpaceGuidCNameList) < 1:
+ TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
+ TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
+ PcdDatumType = PcdItem.DatumType
+ FoundFlag = True
+ else:
+ EdkLogger.error(
+ 'build',
+ AUTOGEN_ERROR,
+ "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (DisplayName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
+ )
+ else:
+ if (TokenCName, TokenSpaceGuidCName) in self.DecPcds:
+ PcdDatumType = self.DecPcds[(TokenCName, TokenSpaceGuidCName)].DatumType
+ FoundFlag = True
+ if not FoundFlag:
+ if HasTokenSpace:
+ EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, DisplayName))
+ else:
+ EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (DisplayName))
+ pcdvalue = pcdvalue.replace("\\\\\\'", '\\\\\\"').replace('\\\'', '\'').replace('\\\\\\"', "\\'")
+ if FieldName:
+ pcdvalue = DscBuildData.HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, pcdvalue, PcdDatumType, self._GuidDict, FieldName)
+ else:
+ pcdvalue = DscBuildData.HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, pcdvalue, PcdDatumType, self._GuidDict)
+ IsValid, Cause = CheckPcdDatum(PcdDatumType, pcdvalue)
+ if not IsValid:
+ EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))
+ GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, ("build command options", 1))
+
+ if GlobalData.BuildOptionPcd:
+ inf_objs = [item for item in self._Bdb._CACHE_.values() if item.Arch == self.Arch and item.MetaFile.Ext.lower() == '.inf']
+ for pcd in GlobalData.BuildOptionPcd:
+ (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
+ for BuildData in inf_objs:
+ for key in BuildData.Pcds:
+ PcdItem = BuildData.Pcds[key]
+ if (TokenSpaceGuidCName, TokenCName) == (PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName) and FieldName =="":
+ PcdItem.DefaultValue = pcdvalue
+ PcdItem.PcdValueFromComm = pcdvalue
+ #In command line, the latter full assign value in commandLine should override the former field assign value.
+ #For example, --pcd Token.pcd.field="" --pcd Token.pcd=H"{}"
+ delete_assign = []
+ field_assign = {}
+ if GlobalData.BuildOptionPcd:
+ for pcdTuple in GlobalData.BuildOptionPcd:
+ TokenSpaceGuid, Token, Field = pcdTuple[0], pcdTuple[1], pcdTuple[2]
+ if Field:
+ if (TokenSpaceGuid, Token) not in field_assign:
+ field_assign[TokenSpaceGuid, Token] = []
+ field_assign[TokenSpaceGuid, Token].append(pcdTuple)
+ else:
+ if (TokenSpaceGuid, Token) in field_assign:
+ delete_assign.extend(field_assign[TokenSpaceGuid, Token])
+ field_assign[TokenSpaceGuid, Token] = []
+ for item in delete_assign:
+ GlobalData.BuildOptionPcd.remove(item)
+
+ @staticmethod
+ def HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, PcdValue, PcdDatumType, GuidDict, FieldName=''):
+ if FieldName:
+ IsArray = False
+ TokenCName += '.' + FieldName
+ if PcdValue.startswith('H'):
+ if FieldName and _IsFieldValueAnArray(PcdValue[1:]):
+ PcdDatumType = TAB_VOID
+ IsArray = True
+ if FieldName and not IsArray:
+ return PcdValue
+ try:
+ PcdValue = ValueExpressionEx(PcdValue[1:], PcdDatumType, GuidDict)(True)
+ except BadExpression as Value:
+ EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
+ (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+ elif PcdValue.startswith("L'") or PcdValue.startswith("'"):
+ if FieldName and _IsFieldValueAnArray(PcdValue):
+ PcdDatumType = TAB_VOID
+ IsArray = True
+ if FieldName and not IsArray:
+ return PcdValue
+ try:
+ PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
+ except BadExpression as Value:
+ EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
+ (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+ elif PcdValue.startswith('L'):
+ PcdValue = 'L"' + PcdValue[1:] + '"'
+ if FieldName and _IsFieldValueAnArray(PcdValue):
+ PcdDatumType = TAB_VOID
+ IsArray = True
+ if FieldName and not IsArray:
+ return PcdValue
+ try:
+ PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
+ except BadExpression as Value:
+ EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
+ (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+ else:
+ if PcdValue.upper() == 'FALSE':
+ PcdValue = str(0)
+ if PcdValue.upper() == 'TRUE':
+ PcdValue = str(1)
+ if not FieldName:
+ if PcdDatumType not in TAB_PCD_NUMERIC_TYPES:
+ PcdValue = '"' + PcdValue + '"'
+ elif not PcdValue.isdigit() and not PcdValue.upper().startswith('0X'):
+ PcdValue = '"' + PcdValue + '"'
+ else:
+ IsArray = False
+ Base = 10
+ if PcdValue.upper().startswith('0X'):
+ Base = 16
+ try:
+ Num = int(PcdValue, Base)
+ except:
+ PcdValue = '"' + PcdValue + '"'
+ if _IsFieldValueAnArray(PcdValue):
+ PcdDatumType = TAB_VOID
+ IsArray = True
+ if not IsArray:
+ return PcdValue
+ try:
+ PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
+ except BadExpression as Value:
+ EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
+ (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+ return PcdValue
+
+ ## Retrieve all PCD settings in platform
+ @property
+ def Pcds(self):
+ if self._Pcds is None:
+ self._Pcds = OrderedDict()
+ self.__ParsePcdFromCommandLine()
+ self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
+ self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
+ self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
+ self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))
+ self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))
+ self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))
+ self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))
+ self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))
+ self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))
+
+ self._Pcds = self.CompletePcdValues(self._Pcds)
+ self._Pcds = self.OverrideByFdfOverAll(self._Pcds)
+ self._Pcds = self.OverrideByCommOverAll(self._Pcds)
+ self._Pcds = self.UpdateStructuredPcds(MODEL_PCD_TYPE_LIST, self._Pcds)
+ self._Pcds = self.CompleteHiiPcdsDefaultStores(self._Pcds)
+ self._Pcds = self._FilterPcdBySkuUsage(self._Pcds)
+
+ self.RecoverCommandLinePcd()
+ return self._Pcds
+
+ ## Retrieve [BuildOptions]
+ @property
+ def BuildOptions(self):
+ if self._BuildOptions is None:
+ self._BuildOptions = OrderedDict()
+ #
+ # Retrieve build option for EDKII and EDK style module
+ #
+ for CodeBase in (EDKII_NAME, EDK_NAME):
+ RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, CodeBase]
+ for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
+ if Dummy3.upper() != TAB_COMMON:
+ continue
+ CurKey = (ToolChainFamily, ToolChain, CodeBase)
+ #
+ # Only flags can be appended
+ #
+ if CurKey not in self._BuildOptions or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
+ self._BuildOptions[CurKey] = Option
+ else:
+ if ' ' + Option not in self._BuildOptions[CurKey]:
+ self._BuildOptions[CurKey] += ' ' + Option
+ return self._BuildOptions
+ def GetBuildOptionsByPkg(self, Module, ModuleType):
+
+ local_pkg = os.path.split(Module.LocalPkg())[0]
+ if self._ModuleTypeOptions is None:
+ self._ModuleTypeOptions = OrderedDict()
+ if ModuleType not in self._ModuleTypeOptions:
+ options = OrderedDict()
+ self._ModuleTypeOptions[ ModuleType] = options
+ RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch]
+ for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
+ if Dummy2 not in (TAB_COMMON,local_pkg.upper(),"EDKII"):
+ continue
+ Type = Dummy3
+ if Type.upper() == ModuleType.upper():
+ Key = (ToolChainFamily, ToolChain)
+ if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
+ options[Key] = Option
+ else:
+ if ' ' + Option not in options[Key]:
+ options[Key] += ' ' + Option
+ return self._ModuleTypeOptions[ModuleType]
+ def GetBuildOptionsByModuleType(self, Edk, ModuleType):
+ if self._ModuleTypeOptions is None:
+ self._ModuleTypeOptions = OrderedDict()
+ if (Edk, ModuleType) not in self._ModuleTypeOptions:
+ options = OrderedDict()
+ self._ModuleTypeOptions[Edk, ModuleType] = options
+ DriverType = '%s.%s' % (Edk, ModuleType)
+ CommonDriverType = '%s.%s' % (TAB_COMMON, ModuleType)
+ RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch]
+ for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
+ Type = Dummy2 + '.' + Dummy3
+ if Type.upper() == DriverType.upper() or Type.upper() == CommonDriverType.upper():
+ Key = (ToolChainFamily, ToolChain, Edk)
+ if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='):
+ options[Key] = Option
+ else:
+ if ' ' + Option not in options[Key]:
+ options[Key] += ' ' + Option
+ return self._ModuleTypeOptions[Edk, ModuleType]
+
+ @staticmethod
+ def GetStructurePcdInfo(PcdSet):
+ structure_pcd_data = defaultdict(list)
+ for item in PcdSet:
+ structure_pcd_data[(item[0], item[1])].append(item)
+
+ return structure_pcd_data
+
+ @staticmethod
+ def OverrideByFdf(StruPcds,workspace):
+ if GlobalData.gFdfParser is None:
+ return StruPcds
+ StructurePcdInFdf = OrderedDict()
+ fdfpcd = GlobalData.gFdfParser.Profile.PcdDict
+ fdfpcdlocation = GlobalData.gFdfParser.Profile.PcdLocalDict
+ for item in fdfpcd :
+ if len(item[2]) and (item[0],item[1]) in StruPcds:
+ StructurePcdInFdf[(item[1],item[0],item[2] )] = fdfpcd[item]
+ GlobalPcds = {(item[0],item[1]) for item in StructurePcdInFdf}
+ for Pcd in StruPcds.values():
+ if (Pcd.TokenSpaceGuidCName,Pcd.TokenCName) not in GlobalPcds:
+ continue
+ FieldValues = OrderedDict()
+ for item in StructurePcdInFdf:
+ if (Pcd.TokenSpaceGuidCName,Pcd.TokenCName) == (item[0],item[1]) and item[2]:
+ FieldValues[item[2]] = StructurePcdInFdf[item]
+ for field in FieldValues:
+ if field not in Pcd.PcdFieldValueFromFdf:
+ Pcd.PcdFieldValueFromFdf[field] = ["","",""]
+ Pcd.PcdFieldValueFromFdf[field][0] = FieldValues[field]
+ Pcd.PcdFieldValueFromFdf[field][1] = os.path.relpath(fdfpcdlocation[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName,field)][0],workspace)
+ Pcd.PcdFieldValueFromFdf[field][2] = fdfpcdlocation[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName,field)][1]
+
+ return StruPcds
+
+ @staticmethod
+ def OverrideByComm(StruPcds):
+ StructurePcdInCom = OrderedDict()
+ for item in GlobalData.BuildOptionPcd:
+ if len(item) == 5 and (item[1], item[0]) in StruPcds:
+ StructurePcdInCom[(item[0], item[1], item[2] )] = (item[3], item[4])
+ GlobalPcds = {(item[0], item[1]) for item in StructurePcdInCom}
+ for Pcd in StruPcds.values():
+ if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) not in GlobalPcds:
+ continue
+ FieldValues = OrderedDict()
+ for item in StructurePcdInCom:
+ if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (item[0], item[1]) and item[2]:
+ FieldValues[item[2]] = StructurePcdInCom[item]
+ for field in FieldValues:
+ if field not in Pcd.PcdFieldValueFromComm:
+ Pcd.PcdFieldValueFromComm[field] = ["", "", ""]
+ Pcd.PcdFieldValueFromComm[field][0] = FieldValues[field][0]
+ Pcd.PcdFieldValueFromComm[field][1] = FieldValues[field][1][0]
+ Pcd.PcdFieldValueFromComm[field][2] = FieldValues[field][1][1]
+ return StruPcds
+
+ def OverrideByCommOverAll(self,AllPcds):
+ def CheckStructureInComm(commpcds):
+ if not commpcds:
+ return False
+ if len(commpcds[0]) == 5:
+ return True
+ return False
+ NoFiledValues = OrderedDict()
+ if CheckStructureInComm(GlobalData.BuildOptionPcd):
+ StructurePcdInCom = OrderedDict()
+ for item in GlobalData.BuildOptionPcd:
+ StructurePcdInCom[(item[0], item[1], item[2] )] = (item[3], item[4])
+ for item in StructurePcdInCom:
+ if not item[2]:
+ NoFiledValues[(item[0], item[1])] = StructurePcdInCom[item]
+ else:
+ for item in GlobalData.BuildOptionPcd:
+ NoFiledValues[(item[0], item[1])] = [item[2]]
+ for Guid, Name in NoFiledValues:
+ if (Name, Guid) in AllPcds:
+ Pcd = AllPcds.get((Name, Guid))
+ if isinstance(self._DecPcds.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName), None), StructurePcd):
+ self._DecPcds.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName)).PcdValueFromComm = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
+ else:
+ Pcd.PcdValueFromComm = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
+ Pcd.DefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
+ for sku in Pcd.SkuInfoList:
+ SkuInfo = Pcd.SkuInfoList[sku]
+ if SkuInfo.DefaultValue:
+ SkuInfo.DefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
+ else:
+ SkuInfo.HiiDefaultValue = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
+ for defaultstore in SkuInfo.DefaultStoreDict:
+ SkuInfo.DefaultStoreDict[defaultstore] = NoFiledValues[(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)][0]
+ if Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII]]:
+ if Pcd.DatumType == TAB_VOID:
+ if not Pcd.MaxDatumSize:
+ Pcd.MaxDatumSize = '0'
+ CurrentSize = int(Pcd.MaxDatumSize, 16) if Pcd.MaxDatumSize.upper().startswith("0X") else int(Pcd.MaxDatumSize)
+ OptionSize = len((StringToArray(Pcd.PcdValueFromComm)).split(","))
+ MaxSize = max(CurrentSize, OptionSize)
+ Pcd.MaxDatumSize = str(MaxSize)
+ else:
+ PcdInDec = self.DecPcds.get((Name, Guid))
+ if PcdInDec:
+ PcdInDec.PcdValueFromComm = NoFiledValues[(Guid, Name)][0]
+ if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE],
+ self._PCD_TYPE_STRING_[MODEL_PCD_FEATURE_FLAG],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX]]:
+ self._Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
+ self._Pcds[Name, Guid].DefaultValue = NoFiledValues[( Guid, Name)][0]
+ if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX]]:
+ self._Pcds[Name, Guid].SkuInfoList = {TAB_DEFAULT:SkuInfoClass(TAB_DEFAULT, self.SkuIds[TAB_DEFAULT][0], '', '', '', '', '', NoFiledValues[( Guid, Name)][0])}
+ return AllPcds
+
+ def OverrideByFdfOverAll(self,AllPcds):
+
+ if GlobalData.gFdfParser is None:
+ return AllPcds
+ NoFiledValues = GlobalData.gFdfParser.Profile.PcdDict
+ for Name,Guid,Field in NoFiledValues:
+ if len(Field):
+ continue
+ Value = NoFiledValues[(Name,Guid,Field)]
+ if (Name,Guid) in AllPcds:
+ Pcd = AllPcds.get((Name,Guid))
+ if isinstance(self._DecPcds.get((Pcd.TokenCName,Pcd.TokenSpaceGuidCName), None),StructurePcd):
+ self._DecPcds.get((Pcd.TokenCName,Pcd.TokenSpaceGuidCName)).PcdValueFromComm = Value
+ else:
+ Pcd.PcdValueFromComm = Value
+ Pcd.DefaultValue = Value
+ for sku in Pcd.SkuInfoList:
+ SkuInfo = Pcd.SkuInfoList[sku]
+ if SkuInfo.DefaultValue:
+ SkuInfo.DefaultValue = Value
+ else:
+ SkuInfo.HiiDefaultValue = Value
+ for defaultstore in SkuInfo.DefaultStoreDict:
+ SkuInfo.DefaultStoreDict[defaultstore] = Value
+ if Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII]]:
+ if Pcd.DatumType == TAB_VOID:
+ if not Pcd.MaxDatumSize:
+ Pcd.MaxDatumSize = '0'
+ CurrentSize = int(Pcd.MaxDatumSize,16) if Pcd.MaxDatumSize.upper().startswith("0X") else int(Pcd.MaxDatumSize)
+ OptionSize = len((StringToArray(Pcd.PcdValueFromComm)).split(","))
+ MaxSize = max(CurrentSize, OptionSize)
+ Pcd.MaxDatumSize = str(MaxSize)
+ else:
+ PcdInDec = self.DecPcds.get((Name,Guid))
+ if PcdInDec:
+ PcdInDec.PcdValueFromFdf = Value
+ if PcdInDec.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE],
+ self._PCD_TYPE_STRING_[MODEL_PCD_FEATURE_FLAG]]:
+ self._Pcds[Name, Guid] = copy.deepcopy(PcdInDec)
+ self._Pcds[Name, Guid].DefaultValue = Value
+ return AllPcds
+
+ def ParsePcdNameStruct(self,NamePart1,NamePart2):
+ TokenSpaceCName = PcdCName = DimensionAttr = Field = ""
+ if "." in NamePart1:
+ TokenSpaceCName, TempPcdCName = NamePart1.split(".")
+ if "[" in TempPcdCName:
+ PcdCName = TempPcdCName[:TempPcdCName.index("[")]
+ DimensionAttr = TempPcdCName[TempPcdCName.index("["):]
+ else:
+ PcdCName = TempPcdCName
+ Field = NamePart2
+ else:
+ TokenSpaceCName = NamePart1
+ if "[" in NamePart2:
+ PcdCName = NamePart2[:NamePart2.index("[")]
+ DimensionAttr = NamePart2[NamePart2.index("["):]
+ else:
+ PcdCName = NamePart2
+
+ return TokenSpaceCName,PcdCName,DimensionAttr,Field
+
+ def UpdateStructuredPcds(self, TypeList, AllPcds):
+
+ DynamicPcdType = [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]
+
+ Pcds = AllPcds
+ DefaultStoreMgr = DefaultStore(self.DefaultStores)
+ SkuIds = self.SkuIds
+ self.SkuIdMgr.AvailableSkuIdSet.update({TAB_DEFAULT:0})
+ DefaultStores = {storename for pcdobj in AllPcds.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict}
+ DefaultStores.add(TAB_DEFAULT_STORES_DEFAULT)
+
+ S_PcdSet = []
+ # Find out all possible PCD candidates for self._Arch
+ RecordList = []
+
+ for Type in TypeList:
+ RecordList.extend(self._RawData[Type, self._Arch])
+
+ for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, default_store, Dummy4, Dummy5 in RecordList:
+ SkuName = SkuName.upper()
+ default_store = default_store.upper()
+ SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
+ if SkuName not in SkuIds:
+ continue
+ TCName,PCName,DimensionAttr,Field = self.ParsePcdNameStruct(TokenSpaceGuid, PcdCName)
+ pcd_in_dec = self._DecPcds.get((PCName,TCName), None)
+ if pcd_in_dec is None:
+ EdkLogger.error('build', PARSER_ERROR,
+ "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TCName, PCName, self._Arch),
+ File=self.MetaFile, Line = Dummy5)
+ if SkuName in SkuIds and ("." in TokenSpaceGuid or "[" in PcdCName):
+ if not isinstance (pcd_in_dec, StructurePcd):
+ EdkLogger.error('build', PARSER_ERROR,
+ "Pcd (%s.%s) is not declared as Structure PCD in DEC files. Arch: ['%s']" % (TCName, PCName, self._Arch),
+ File=self.MetaFile, Line = Dummy5)
+
+ S_PcdSet.append([ TCName,PCName,DimensionAttr,Field, SkuName, default_store, Dummy5, AnalyzePcdExpression(Setting)[0]])
+ ModuleScopeOverallValue = {}
+ for m in self.Modules.values():
+ mguid = m.Guid
+ if m.StrPcdSet:
+ S_PcdSet.extend(m.StrPcdSet)
+ mguid = m.StrPcdSet[0][4]
+ for (PCName,TCName) in m.StrPcdOverallValue:
+ Value, dsc_file, lineNo = m.StrPcdOverallValue[(PCName,TCName)]
+ ModuleScopeOverallValue.setdefault((PCName,TCName),{})[mguid] = Value, dsc_file, lineNo
+ # handle pcd value override
+ StrPcdSet = DscBuildData.GetStructurePcdInfo(S_PcdSet)
+ S_pcd_set = OrderedDict()
+ for str_pcd in StrPcdSet:
+ str_pcd_obj = Pcds.get((str_pcd[1], str_pcd[0]), None)
+ str_pcd_dec = self._DecPcds.get((str_pcd[1], str_pcd[0]), None)
+ str_pcd_obj_str = StructurePcd()
+ str_pcd_obj_str.copy(str_pcd_dec)
+ if str_pcd_obj:
+ str_pcd_obj_str.copy(str_pcd_obj)
+ if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
+ else:
+ str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].DefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
+ for str_pcd_data in StrPcdSet[str_pcd]:
+ if str_pcd_data[4] in SkuIds:
+ str_pcd_obj_str.AddOverrideValue(str_pcd_data[3], str(str_pcd_data[7]), TAB_DEFAULT if str_pcd_data[4] == TAB_COMMON else str_pcd_data[4], TAB_DEFAULT_STORES_DEFAULT if str_pcd_data[5] == TAB_COMMON else str_pcd_data[5], self.MetaFile.File if self.WorkspaceDir not in self.MetaFile.File else self.MetaFile.File[len(self.WorkspaceDir) if self.WorkspaceDir.endswith(os.path.sep) else len(self.WorkspaceDir)+1:], LineNo=str_pcd_data[6],DimensionAttr = str_pcd_data[2])
+ elif GlobalData.gGuidPattern.match(str_pcd_data[4]):
+ str_pcd_obj_str.AddComponentOverrideValue(str_pcd_data[3], str(str_pcd_data[7]), str_pcd_data[4].replace("-","S"), self.MetaFile.File if self.WorkspaceDir not in self.MetaFile.File else self.MetaFile.File[len(self.WorkspaceDir) if self.WorkspaceDir.endswith(os.path.sep) else len(self.WorkspaceDir)+1:], LineNo=str_pcd_data[6],DimensionAttr = str_pcd_data[2])
+ PcdComponentValue = ModuleScopeOverallValue.get((str_pcd_obj_str.TokenCName,str_pcd_obj_str.TokenSpaceGuidCName))
+ for module_guid in PcdComponentValue:
+ str_pcd_obj_str.PcdValueFromComponents[module_guid.replace("-","S")] = PcdComponentValue[module_guid]
+ S_pcd_set[str_pcd[1], str_pcd[0]] = str_pcd_obj_str
+
+ # Add the Structure PCD that only defined in DEC, don't have override in DSC file
+ for Pcd in self.DecPcds:
+ if isinstance(self._DecPcds[Pcd], StructurePcd):
+ if Pcd not in S_pcd_set:
+ str_pcd_obj_str = StructurePcd()
+ str_pcd_obj_str.copy(self._DecPcds[Pcd])
+ str_pcd_obj = Pcds.get(Pcd, None)
+ if str_pcd_obj:
+ str_pcd_obj_str.copy(str_pcd_obj)
+ if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
+ else:
+ str_pcd_obj_str.DefaultFromDSC = {skuname:{defaultstore: str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.get(defaultstore, str_pcd_obj.SkuInfoList[skuname].DefaultValue) for defaultstore in DefaultStores} for skuname in str_pcd_obj.SkuInfoList}
+ S_pcd_set[Pcd] = str_pcd_obj_str
+ if S_pcd_set:
+ GlobalData.gStructurePcd[self.Arch] = S_pcd_set.copy()
+ self.FilterStrcturePcd(S_pcd_set)
+ for stru_pcd in S_pcd_set.values():
+ for skuid in SkuIds:
+ if skuid in stru_pcd.SkuOverrideValues:
+ continue
+ nextskuid = self.SkuIdMgr.GetNextSkuId(skuid)
+ NoDefault = False
+ if skuid not in stru_pcd.SkuOverrideValues:
+ while nextskuid not in stru_pcd.SkuOverrideValues:
+ if nextskuid == TAB_DEFAULT:
+ NoDefault = True
+ break
+ nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
+ stru_pcd.SkuOverrideValues[skuid] = copy.deepcopy(stru_pcd.SkuOverrideValues[nextskuid]) if not NoDefault else copy.deepcopy({defaultstorename: stru_pcd.DefaultValues for defaultstorename in DefaultStores} if DefaultStores else {}) #{TAB_DEFAULT_STORES_DEFAULT:stru_pcd.DefaultValues})
+ if not NoDefault:
+ stru_pcd.ValueChain.add((skuid, ''))
+ if 'DEFAULT' in stru_pcd.SkuOverrideValues and not GlobalData.gPcdSkuOverrides.get((stru_pcd.TokenCName, stru_pcd.TokenSpaceGuidCName)):
+ GlobalData.gPcdSkuOverrides.update(
+ {(stru_pcd.TokenCName, stru_pcd.TokenSpaceGuidCName): {'DEFAULT':stru_pcd.SkuOverrideValues['DEFAULT']}})
+ if stru_pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ for skuid in SkuIds:
+ nextskuid = skuid
+ NoDefault = False
+ if skuid not in stru_pcd.SkuOverrideValues:
+ while nextskuid not in stru_pcd.SkuOverrideValues:
+ if nextskuid == TAB_DEFAULT:
+ NoDefault = True
+ break
+ nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
+ if NoDefault:
+ continue
+ PcdDefaultStoreSet = set(defaultstorename for defaultstorename in stru_pcd.SkuOverrideValues[nextskuid])
+ mindefaultstorename = DefaultStoreMgr.GetMin(PcdDefaultStoreSet)
+
+ for defaultstoreid in DefaultStores:
+ if defaultstoreid not in stru_pcd.SkuOverrideValues[skuid]:
+ stru_pcd.SkuOverrideValues[skuid][defaultstoreid] = CopyDict(stru_pcd.SkuOverrideValues[nextskuid][mindefaultstorename])
+ stru_pcd.ValueChain.add((skuid, defaultstoreid))
+ S_pcd_set = DscBuildData.OverrideByFdf(S_pcd_set,self.WorkspaceDir)
+ S_pcd_set = DscBuildData.OverrideByComm(S_pcd_set)
+
+ # Create a tool to caculate structure pcd value
+ Str_Pcd_Values = self.GenerateByteArrayValue(S_pcd_set)
+
+ if Str_Pcd_Values:
+ for (skuname, StoreName, PcdGuid, PcdName, PcdValue) in Str_Pcd_Values:
+ str_pcd_obj = S_pcd_set.get((PcdName, PcdGuid))
+ if str_pcd_obj is None:
+ print(PcdName, PcdGuid)
+ raise
+ if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ if skuname not in str_pcd_obj.SkuInfoList:
+ str_pcd_obj.SkuInfoList[skuname] = SkuInfoClass(SkuIdName=skuname, SkuId=self.SkuIds[skuname][0], HiiDefaultValue=PcdValue, DefaultStore = {StoreName:PcdValue})
+ else:
+ str_pcd_obj.SkuInfoList[skuname].HiiDefaultValue = PcdValue
+ str_pcd_obj.SkuInfoList[skuname].DefaultStoreDict.update({StoreName:PcdValue})
+ elif str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
+ if skuname in (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT, TAB_COMMON):
+ str_pcd_obj.DefaultValue = PcdValue
+ else:
+ #Module Scope Structure Pcd
+ moduleguid = skuname.replace("S","-")
+ if GlobalData.gGuidPattern.match(moduleguid):
+ for component in self.Modules.values():
+ if component.Guid == moduleguid:
+ component.Pcds[(PcdName, PcdGuid)].DefaultValue = PcdValue
+
+ else:
+ if skuname not in str_pcd_obj.SkuInfoList:
+ nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
+ NoDefault = False
+ while nextskuid not in str_pcd_obj.SkuInfoList:
+ if nextskuid == TAB_DEFAULT:
+ NoDefault = True
+ break
+ nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
+ str_pcd_obj.SkuInfoList[skuname] = copy.deepcopy(str_pcd_obj.SkuInfoList[nextskuid]) if not NoDefault else SkuInfoClass(SkuIdName=skuname, SkuId=self.SkuIds[skuname][0], DefaultValue=PcdValue)
+ str_pcd_obj.SkuInfoList[skuname].SkuId = self.SkuIds[skuname][0]
+ str_pcd_obj.SkuInfoList[skuname].SkuIdName = skuname
+ else:
+ str_pcd_obj.SkuInfoList[skuname].DefaultValue = PcdValue
+ for str_pcd_obj in S_pcd_set.values():
+ if str_pcd_obj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ continue
+ PcdDefaultStoreSet = set(defaultstorename for skuobj in str_pcd_obj.SkuInfoList.values() for defaultstorename in skuobj.DefaultStoreDict)
+ DefaultStoreObj = DefaultStore(self._GetDefaultStores())
+ mindefaultstorename = DefaultStoreObj.GetMin(PcdDefaultStoreSet)
+ str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].HiiDefaultValue = str_pcd_obj.SkuInfoList[self.SkuIdMgr.SystemSkuId].DefaultStoreDict[mindefaultstorename]
+
+ for str_pcd_obj in S_pcd_set.values():
+
+ str_pcd_obj.MaxDatumSize = DscBuildData.GetStructurePcdMaxSize(str_pcd_obj)
+ Pcds[str_pcd_obj.TokenCName, str_pcd_obj.TokenSpaceGuidCName] = str_pcd_obj
+ Pcds[str_pcd_obj.TokenCName, str_pcd_obj.TokenSpaceGuidCName].CustomAttribute['IsStru']=True
+
+ for pcdkey in Pcds:
+ pcd = Pcds[pcdkey]
+ if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
+ del pcd.SkuInfoList[TAB_COMMON]
+ elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ del pcd.SkuInfoList[TAB_COMMON]
+
+ list(map(self.FilterSkuSettings, [Pcds[pcdkey] for pcdkey in Pcds if Pcds[pcdkey].Type in DynamicPcdType]))
+ return Pcds
+ @cached_property
+ def PlatformUsedPcds(self):
+ FdfInfList = []
+ if GlobalData.gFdfParser:
+ FdfInfList = GlobalData.gFdfParser.Profile.InfList
+ FdfModuleList = [PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch) for Inf in FdfInfList]
+ AllModulePcds = set()
+ ModuleSet = set(list(self._Modules.keys()) + FdfModuleList)
+ for ModuleFile in ModuleSet:
+ ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
+ AllModulePcds = AllModulePcds | ModuleData.PcdsName
+ for ModuleFile in self.LibraryInstances:
+ ModuleData = self._Bdb.CreateBuildObject(ModuleFile, self._Arch, self._Target, self._Toolchain)
+ AllModulePcds = AllModulePcds | ModuleData.PcdsName
+ return AllModulePcds
+
+ #Filter the StrucutrePcd that is not used by any module in dsc file and fdf file.
+ def FilterStrcturePcd(self, S_pcd_set):
+ UnusedStruPcds = set(S_pcd_set.keys()) - self.PlatformUsedPcds
+ for (Token, TokenSpaceGuid) in UnusedStruPcds:
+ del S_pcd_set[(Token, TokenSpaceGuid)]
+
+ ## Retrieve non-dynamic PCD settings
+ #
+ # @param Type PCD type
+ #
+ # @retval a dict object contains settings of given PCD type
+ #
+ def _GetPcd(self, Type):
+ Pcds = OrderedDict()
+ #
+ # tdict is a special dict kind of type, used for selecting correct
+ # PCD settings for certain ARCH
+ #
+ AvailableSkuIdSet = copy.copy(self.SkuIds)
+
+ PcdDict = tdict(True, 4)
+ PcdList = []
+ # Find out all possible PCD candidates for self._Arch
+ RecordList = self._RawData[Type, self._Arch]
+ PcdValueDict = OrderedDict()
+ for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4, Dummy5 in RecordList:
+ SkuName = SkuName.upper()
+ SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
+ if SkuName not in AvailableSkuIdSet:
+ EdkLogger.error('build ', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
+ File=self.MetaFile, Line=Dummy5)
+ if SkuName in (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT, TAB_COMMON):
+ if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, Dummy5) not in PcdList:
+ PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
+ PcdDict[Arch, PcdCName, TokenSpaceGuid, SkuName] = Setting
+
+ for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
+ Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid, SkuName]
+ if Setting is None:
+ continue
+ PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
+ if MaxDatumSize:
+ if int(MaxDatumSize, 0) > 0xFFFF:
+ EdkLogger.error('build', FORMAT_INVALID, "The size value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)),
+ File=self.MetaFile, Line=Dummy4)
+ if int(MaxDatumSize, 0) < 0:
+ EdkLogger.error('build', FORMAT_INVALID, "The size value can't be set to negative value for %s." % ".".join((TokenSpaceGuid, PcdCName)),
+ File=self.MetaFile, Line=Dummy4)
+ if (PcdCName, TokenSpaceGuid) in PcdValueDict:
+ PcdValueDict[PcdCName, TokenSpaceGuid][SkuName] = (PcdValue, DatumType, MaxDatumSize,Dummy4)
+ else:
+ PcdValueDict[PcdCName, TokenSpaceGuid] = {SkuName:(PcdValue, DatumType, MaxDatumSize,Dummy4)}
+
+ for ((PcdCName, TokenSpaceGuid), PcdSetting) in PcdValueDict.items():
+ if self.SkuIdMgr.SystemSkuId in PcdSetting:
+ PcdValue, DatumType, MaxDatumSize,_ = PcdSetting[self.SkuIdMgr.SystemSkuId]
+ elif TAB_DEFAULT in PcdSetting:
+ PcdValue, DatumType, MaxDatumSize,_ = PcdSetting[TAB_DEFAULT]
+ elif TAB_COMMON in PcdSetting:
+ PcdValue, DatumType, MaxDatumSize,_ = PcdSetting[TAB_COMMON]
+ else:
+ PcdValue = None
+ DatumType = None
+ MaxDatumSize = None
+
+ Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
+ PcdCName,
+ TokenSpaceGuid,
+ self._PCD_TYPE_STRING_[Type],
+ DatumType,
+ PcdValue,
+ '',
+ MaxDatumSize,
+ {},
+ False,
+ None,
+ IsDsc=True)
+ for SkuName in PcdValueDict[PcdCName, TokenSpaceGuid]:
+ Settings = PcdValueDict[PcdCName, TokenSpaceGuid][SkuName]
+ if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][TAB_DEFAULT_STORES_DEFAULT] = Settings[0]
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][TAB_DEFAULT_STORES_DEFAULT] = (self.MetaFile.File,Settings[3])
+ return Pcds
+
+ @staticmethod
+ def GetStructurePcdMaxSize(str_pcd):
+ pcd_default_value = str_pcd.DefaultValue
+ sku_values = [skuobj.HiiDefaultValue if str_pcd.Type in [DscBuildData._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], DscBuildData._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]] else skuobj.DefaultValue for skuobj in str_pcd.SkuInfoList.values()]
+ sku_values.append(pcd_default_value)
+
+ def get_length(value):
+ Value = value.strip()
+ if len(value) > 1:
+ if Value.startswith(TAB_GUID) and Value.endswith(')'):
+ return 16
+ if Value.startswith('L"') and Value.endswith('"'):
+ return len(Value[2:-1])
+ if Value[0] == '"' and Value[-1] == '"':
+ return len(Value) - 2
+ if Value.strip().startswith("{CODE("):
+ tmpValue = RemoveCComments(Value)
+ return len(tmpValue.split(","))
+ if (Value[0] == '{' and Value[-1] == '}'):
+ return len(Value.split(","))
+ if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
+ return len(list(Value[2:-1]))
+ if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
+ return len(Value) - 2
+ return len(Value)
+
+ return str(max(get_length(item) for item in sku_values))
+
+ @staticmethod
+ def ExecuteCommand (Command):
+ try:
+ Process = subprocess.Popen(Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+ except:
+ EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s' % Command)
+ Result = Process.communicate()
+ return Process.returncode, Result[0].decode(errors='ignore'), Result[1].decode(errors='ignore')
+
+ @staticmethod
+ def IntToCString(Value, ValueSize):
+ Result = '"'
+ if not isinstance (Value, str):
+ for Index in range(0, ValueSize):
+ Result = Result + '\\x%02x' % (Value & 0xff)
+ Value = Value >> 8
+ Result = Result + '"'
+ return Result
+
+ def GenerateSizeFunction(self, Pcd):
+ CApp = "// Default Value in Dec \n"
+ CApp = CApp + "void Cal_%s_%s_Size(UINT32 *Size){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+
+ if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
+ CApp += " *Size = (sizeof (%s) > *Size ? sizeof (%s) : *Size);\n" % (Pcd.DatumType,Pcd.DatumType)
+ else:
+ if "{CODE(" in Pcd.DefaultValueFromDec:
+ CApp += " *Size = (sizeof (%s_%s_INIT_Value) > *Size ? sizeof (%s_%s_INIT_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,Pcd.TokenSpaceGuidCName,Pcd.TokenCName)
+ if Pcd.Type in PCD_DYNAMIC_TYPE_SET | PCD_DYNAMIC_EX_TYPE_SET:
+ for skuname in Pcd.SkuInfoList:
+ skuobj = Pcd.SkuInfoList[skuname]
+ if skuobj.VariableName:
+ for defaultstore in skuobj.DefaultStoreDict:
+ pcddef = self.GetPcdDscRawDefaultValue(Pcd,skuname,defaultstore)
+ if pcddef:
+ if "{CODE(" in pcddef:
+ CApp += " *Size = (sizeof (%s_%s_%s_%s_Value) > *Size ? sizeof (%s_%s_%s_%s_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,defaultstore,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,defaultstore)
+ else:
+ CApp += " *Size = %s > *Size ? %s : *Size;\n" % (self.GetStructurePcdMaxSize(Pcd),self.GetStructurePcdMaxSize(Pcd))
+ else:
+ pcddef = self.GetPcdDscRawDefaultValue(Pcd,skuname,TAB_DEFAULT_STORES_DEFAULT)
+ if pcddef:
+ if "{CODE(" in pcddef:
+ CApp += " *Size = (sizeof (%s_%s_%s_%s_Value) > *Size ? sizeof (%s_%s_%s_%s_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,TAB_DEFAULT_STORES_DEFAULT,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,TAB_DEFAULT_STORES_DEFAULT)
+ else:
+ CApp += " *Size = %s > *Size ? %s : *Size;\n" % (self.GetStructurePcdMaxSize(Pcd),self.GetStructurePcdMaxSize(Pcd))
+ else:
+ pcddef = self.GetPcdDscRawDefaultValue(Pcd,TAB_DEFAULT,TAB_DEFAULT_STORES_DEFAULT)
+ if pcddef:
+ if "{CODE(" in pcddef:
+ CApp += " *Size = (sizeof (%s_%s_%s_%s_Value) > *Size ? sizeof (%s_%s_%s_%s_Value) : *Size);\n" % (Pcd.TokenSpaceGuidCName,Pcd.TokenCName,TAB_DEFAULT,TAB_DEFAULT_STORES_DEFAULT,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,TAB_DEFAULT,TAB_DEFAULT_STORES_DEFAULT)
+ else:
+ CApp += " *Size = %s > *Size ? %s : *Size;\n" % (self.GetStructurePcdMaxSize(Pcd),self.GetStructurePcdMaxSize(Pcd))
+ ActualCap = []
+ for index in Pcd.DefaultValues:
+ if index:
+ ActualCap.append(index)
+ FieldList = Pcd.DefaultValues[index]
+ if not FieldList:
+ continue
+ for FieldName in FieldList:
+ FieldName = "." + FieldName
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
+ if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
+ try:
+ Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2]))
+ Value, ValueSize = ParseFieldValue(Value)
+ if not Pcd.IsArray():
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0)); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2], FieldList[FieldName.strip(".")][0]);
+ else:
+ NewFieldName = ''
+ FieldName_ori = FieldName.strip('.')
+ while '[' in FieldName:
+ NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
+ Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
+ FieldName = FieldName.split(']', 1)[1]
+ FieldName = NewFieldName + FieldName
+ while '[' in FieldName and not Pcd.IsArray():
+ FieldName = FieldName.rsplit('[', 1)[0]
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2], FieldList[FieldName_ori][0])
+ for skuname in Pcd.SkuOverrideValues:
+ if skuname == TAB_COMMON:
+ continue
+ for defaultstorenameitem in Pcd.SkuOverrideValues[skuname]:
+ CApp = CApp + "// SkuName: %s, DefaultStoreName: %s \n" % (skuname, defaultstorenameitem)
+ for index in Pcd.SkuOverrideValues[skuname][defaultstorenameitem]:
+ if index:
+ ActualCap.append(index)
+ for FieldList in [Pcd.SkuOverrideValues[skuname][defaultstorenameitem][index]]:
+ if not FieldList:
+ continue
+ for FieldName in FieldList:
+ FieldName = "." + FieldName
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
+ if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
+ try:
+ Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2]))
+ Value, ValueSize = ParseFieldValue(Value)
+ if not Pcd.IsArray():
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0)); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), FieldList[FieldName.strip(".")][1], FieldList[FieldName.strip(".")][2], FieldList[FieldName.strip(".")][0]);
+ else:
+ NewFieldName = ''
+ FieldName_ori = FieldName.strip('.')
+ while '[' in FieldName:
+ NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
+ Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
+ FieldName = FieldName.split(']', 1)[1]
+ FieldName = NewFieldName + FieldName
+ while '[' in FieldName and not Pcd.IsArray():
+ FieldName = FieldName.rsplit('[', 1)[0]
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2], FieldList[FieldName_ori][0])
+ if Pcd.PcdFieldValueFromFdf:
+ CApp = CApp + "// From fdf \n"
+ for FieldName in Pcd.PcdFieldValueFromFdf:
+ FieldName = "." + FieldName
+ IsArray = _IsFieldValueAnArray(Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0])
+ if IsArray and not (Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0].startswith('{GUID') and Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0].endswith('}')):
+ try:
+ Value = ValueExpressionEx(Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][1], Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][2]))
+ Value, ValueSize = ParseFieldValue(Value)
+ if not Pcd.IsArray():
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0)); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][1], Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][2], Pcd.PcdFieldValueFromFdf[FieldName.strip(".")][0]);
+ else:
+ NewFieldName = ''
+ FieldName_ori = FieldName.strip('.')
+ while '[' in FieldName:
+ NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
+ Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
+ FieldName = FieldName.split(']', 1)[1]
+ FieldName = NewFieldName + FieldName
+ while '[' in FieldName:
+ FieldName = FieldName.rsplit('[', 1)[0]
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %s Value %s \n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, Pcd.PcdFieldValueFromFdf[FieldName_ori][1], Pcd.PcdFieldValueFromFdf[FieldName_ori][2], Pcd.PcdFieldValueFromFdf[FieldName_ori][0])
+ if Pcd.PcdFieldValueFromComm:
+ CApp = CApp + "// From Command Line \n"
+ for FieldName in Pcd.PcdFieldValueFromComm:
+ FieldName = "." + FieldName
+ IsArray = _IsFieldValueAnArray(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0])
+ if IsArray and not (Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].startswith('{GUID') and Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].endswith('}')):
+ try:
+ Value = ValueExpressionEx(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName.strip('.'))), Pcd.PcdFieldValueFromComm[FieldName.strip(".")][1], Pcd.PcdFieldValueFromComm[FieldName.strip(".")][2]))
+ Value, ValueSize = ParseFieldValue(Value)
+ if not Pcd.IsArray():
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0)); // From %s Line %d Value %s\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), Pcd.PcdFieldValueFromComm[FieldName.strip(".")][1], Pcd.PcdFieldValueFromComm[FieldName.strip(".")][2], Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0]);
+ else:
+ NewFieldName = ''
+ FieldName_ori = FieldName.strip('.')
+ while '[' in FieldName:
+ NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'
+ Array_Index = int(FieldName.split('[', 1)[1].split(']', 1)[0])
+ FieldName = FieldName.split(']', 1)[1]
+ FieldName = NewFieldName + FieldName
+ while '[' in FieldName and not Pcd.IsArray():
+ FieldName = FieldName.rsplit('[', 1)[0]
+ CApp = CApp + ' __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), Array_Index + 1, Pcd.PcdFieldValueFromComm[FieldName_ori][1], Pcd.PcdFieldValueFromComm[FieldName_ori][2], Pcd.PcdFieldValueFromComm[FieldName_ori][0])
+ if Pcd.GetPcdMaxSize():
+ CApp = CApp + " *Size = (%d > *Size ? %d : *Size); // The Pcd maxsize is %d \n" % (Pcd.GetPcdMaxSize(), Pcd.GetPcdMaxSize(), Pcd.GetPcdMaxSize())
+ ArraySizeByAssign = self.CalculateActualCap(ActualCap)
+ if ArraySizeByAssign > 1:
+ CApp = CApp + " *Size = (%d > *Size ? %d : *Size); \n" % (ArraySizeByAssign, ArraySizeByAssign)
+ CApp = CApp + "}\n"
+ return CApp
+ def CalculateActualCap(self,ActualCap):
+ if not ActualCap:
+ return 1
+ maxsize = 1
+ for item in ActualCap:
+ index_elements = ArrayIndex.findall(item)
+ rt = 1
+ for index_e in index_elements:
+ index_num = index_e.lstrip("[").rstrip("]").strip()
+ if not index_num:
+ # Not support flexiable pcd array assignment
+ return 1
+ index_num = int(index_num,16) if index_num.startswith(("0x","0X")) else int(index_num)
+ rt = rt * (index_num+1)
+ if rt >maxsize:
+ maxsize = rt
+
+ return maxsize
+
+ @staticmethod
+ def GenerateSizeStatments(Pcd,skuname,defaultstorename):
+ if Pcd.IsArray():
+ r_datatype = [Pcd.BaseDatumType]
+ lastoneisEmpty = False
+ for dem in Pcd.Capacity:
+ if lastoneisEmpty:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))))
+ if dem == '0' or dem == "-1":
+ r_datatype.append("[1]")
+ lastoneisEmpty = True
+ else:
+ r_datatype.append("[" + dem + "]")
+
+ if Pcd.Type in [MODEL_PCD_DYNAMIC_EX_HII, MODEL_PCD_DYNAMIC_HII]:
+ PcdDefValue = Pcd.SkuInfoList.get(skuname).DefaultStoreDict.get(defaultstorename)
+ elif Pcd.Type in [MODEL_PCD_DYNAMIC_EX_DEFAULT,MODEL_PCD_DYNAMIC_VPD,MODEL_PCD_DYNAMIC_DEFAULT,MODEL_PCD_DYNAMIC_EX_VPD]:
+ PcdDefValue = Pcd.SkuInfoList.get(skuname).DefaultValue
+ else:
+ PcdDefValue = Pcd.DefaultValue
+ if lastoneisEmpty:
+ if "{CODE(" not in PcdDefValue:
+ sizebasevalue_plus = "(%s / sizeof(%s) + 1)" % ((DscBuildData.GetStructurePcdMaxSize(Pcd), Pcd.BaseDatumType))
+ sizebasevalue = "(%s / sizeof(%s))" % ((DscBuildData.GetStructurePcdMaxSize(Pcd), Pcd.BaseDatumType))
+ sizeof = "sizeof(%s)" % Pcd.BaseDatumType
+ CApp = ' int ArraySize = %s %% %s ? %s : %s ;\n' % ( (DscBuildData.GetStructurePcdMaxSize(Pcd), sizeof, sizebasevalue_plus, sizebasevalue))
+ CApp += ' Size = ArraySize * sizeof(%s); \n' % Pcd.BaseDatumType
+ else:
+ CApp = " Size = 0;\n"
+ else:
+ CApp = ' Size = sizeof(%s);\n' % ("".join(r_datatype) )
+ else:
+ CApp = ' Size = sizeof(%s);\n' % (Pcd.DatumType)
+ CApp = CApp + ' Cal_%s_%s_Size(&Size);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ return CApp
+
+ def GetIndicator(self,index,FieldName,Pcd):
+ def cleanupindex(indexstr):
+ return indexstr.strip("[").strip("]").strip()
+ index_elements = ArrayIndex.findall(index)
+ pcd_capacity = Pcd.Capacity
+ if index:
+ indicator = "(Pcd"
+ if len(pcd_capacity)>2:
+ for i in range(0,len(index_elements)):
+ index_ele = index_elements[i]
+ index_num = index_ele.strip("[").strip("]").strip()
+ if i == len(index_elements) -2:
+ indicator += "+ %d*Size/sizeof(%s)/%d + %s)" %(int(cleanupindex(index_elements[i+1])),Pcd.BaseDatumType,reduce(lambda x,y: int(x)*int(y),pcd_capacity[:-1]), cleanupindex(index_elements[i]))
+ break
+ else:
+ indicator += " + %d*%s*Size/sizeof(%s)/%d" %(int(cleanupindex(index_elements[i])),reduce(lambda x,y: int(x)*int(y),pcd_capacity[i+1:-1]),Pcd.BaseDatumType,reduce(lambda x,y: int(x)*int(y),pcd_capacity[:-1]))
+ elif len(pcd_capacity) == 2:
+ indicator += "+ %d*Size/sizeof(%s)/%d + %s)" %(int(cleanupindex(index_elements[0])),Pcd.BaseDatumType,int(pcd_capacity[0]), index_elements[1].strip("[").strip("]").strip())
+ elif len(pcd_capacity) == 1:
+ index_ele = index_elements[0]
+ index_num = index_ele.strip("[").strip("]").strip()
+ indicator += " + %s)" % (index_num)
+ else:
+ indicator = "Pcd"
+ if FieldName:
+ indicator += "->" + FieldName
+ return indicator
+
+ def GetStarNum(self,Pcd):
+ if not Pcd.IsArray():
+ return 1
+ elif Pcd.IsSimpleTypeArray():
+ return len(Pcd.Capacity)
+ else:
+ return len(Pcd.Capacity) + 1
+ def GenerateDefaultValueAssignFunction(self, Pcd):
+ CApp = "// Default value in Dec \n"
+ CApp = CApp + "void Assign_%s_%s_Default_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.BaseDatumType)
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+ CApp = CApp + ' UINT32 PcdArraySize;\n'
+ DefaultValueFromDec = Pcd.DefaultValueFromDec
+ IsArray = _IsFieldValueAnArray(Pcd.DefaultValueFromDec)
+ if IsArray:
+ try:
+ DefaultValueFromDec = ValueExpressionEx(Pcd.DefaultValueFromDec, TAB_VOID)(True)
+ except BadExpression:
+ EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DEC: %s" %
+ (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValueFromDec))
+ DefaultValueFromDec = StringToArray(DefaultValueFromDec)
+ Value, ValueSize = ParseFieldValue (DefaultValueFromDec)
+ if IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ if Pcd.IsArray():
+ pcdarraysize = Pcd.PcdArraySize()
+ if "{CODE(" in Pcd.DefaultValueFromDec:
+ if Pcd.Capacity[-1] != "-1":
+ CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_INIT_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dec exceed the array capability %s"); // From %s Line %s \n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,Pcd.DefaultValueFromDecInfo[0],Pcd.DefaultValueFromDecInfo[1])
+ CApp = CApp + ' PcdArraySize = sizeof(%s_%s_INIT_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ CApp = CApp + ' memcpy (Pcd, %s_%s_INIT_Value,PcdArraySize);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ else:
+ if Pcd.Capacity[-1] != "-1":
+ CApp = CApp + '__STATIC_ASSERT(%d < %d * sizeof(%s), "Pcd %s.%s Value in Dec exceed the array capability %s"); // From %s Line %s \n' % (ValueSize,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,Pcd.DefaultValueFromDecInfo[0],Pcd.DefaultValueFromDecInfo[1])
+ CApp = CApp + ' PcdArraySize = %d;\n' % ValueSize
+ CApp = CApp + ' Value = %s; // From DEC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultValueFromDec)
+ CApp = CApp + ' memcpy (Pcd, Value, PcdArraySize);\n'
+ else:
+ if "{CODE(" in Pcd.DefaultValueFromDec:
+ CApp = CApp + ' PcdArraySize = sizeof(%s_%s_INIT_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ CApp = CApp + ' memcpy (Pcd, &%s_%s_INIT_Value,PcdArraySize);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ else:
+ CApp = CApp + ' Value = %s; // From DEC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultValueFromDec)
+ CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
+ elif isinstance(Value, str):
+ CApp = CApp + ' Pcd = %s; // From DEC Default Value %s\n' % (Value, Pcd.DefaultValueFromDec)
+ for index in Pcd.DefaultValues:
+ FieldList = Pcd.DefaultValues[index]
+ if not FieldList:
+ continue
+ for FieldName in FieldList:
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
+ if IsArray:
+ try:
+ FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+
+ try:
+ Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
+ except Exception:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+
+ indicator = self.GetIndicator(index, FieldName,Pcd)
+ if IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
+ CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' memcpy (&%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (indicator, ValueSize, ValueSize)
+ elif isinstance(Value, str):
+ CApp = CApp + ' %s = %s; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ else:
+ if '[' in FieldName and ']' in FieldName:
+ Index = int(FieldName.split('[')[1].split(']')[0])
+ CApp = CApp + ' __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
+ if ValueSize > 4:
+ CApp = CApp + ' %s = %dULL; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ else:
+ CApp = CApp + ' %s = %d; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + "}\n"
+ return CApp
+
+ @staticmethod
+ def GenerateDefaultValueAssignStatement(Pcd):
+ CApp = ' Assign_%s_%s_Default_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ return CApp
+
+ def GetPcdDscRawDefaultValue(self,Pcd, SkuName,DefaultStoreName):
+ if Pcd.Type in PCD_DYNAMIC_TYPE_SET or Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
+ if (SkuName, DefaultStoreName) == (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT):
+ pcddefaultvalue = Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT) if Pcd.DefaultFromDSC else None
+ else:
+ pcddefaultvalue = Pcd.DscRawValue.get(SkuName, {}).get(DefaultStoreName)
+ else:
+ pcddefaultvalue = Pcd.DscRawValue.get(SkuName, {}).get(TAB_DEFAULT_STORES_DEFAULT)
+
+ return pcddefaultvalue
+ def GetPcdDscRawValueInfo(self,Pcd, SkuName,DefaultStoreName):
+ DscValueInfo = Pcd.DscRawValueInfo.get(SkuName, {}).get(DefaultStoreName)
+ if DscValueInfo:
+ dscfilepath,lineno = DscValueInfo
+ else:
+ dscfilepath = self.MetaFile.File
+ lineno = ""
+ return dscfilepath,lineno
+
+ def GenerateInitValueFunction(self, Pcd, SkuName, DefaultStoreName):
+ CApp = "// Value in Dsc for Sku: %s, DefaultStore %s\n" % (SkuName, DefaultStoreName)
+ CApp = CApp + "void Assign_%s_%s_%s_%s_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, SkuName, DefaultStoreName, Pcd.BaseDatumType)
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+ CApp = CApp + ' UINT32 PcdArraySize;\n'
+
+ CApp = CApp + "// SkuName: %s, DefaultStoreName: %s \n" % (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT)
+ inherit_OverrideValues = Pcd.SkuOverrideValues[SkuName]
+ dscfilepath,lineno = self.GetPcdDscRawValueInfo(Pcd, SkuName, DefaultStoreName)
+ if lineno:
+ valuefrom = "%s Line %s" % (dscfilepath,str(lineno))
+ else:
+ valuefrom = dscfilepath
+
+ pcddefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, SkuName, DefaultStoreName)
+ if pcddefaultvalue:
+ FieldList = pcddefaultvalue
+ IsArray = _IsFieldValueAnArray(FieldList)
+ if IsArray:
+ if "{CODE(" not in FieldList:
+ try:
+ FieldList = ValueExpressionEx(FieldList, TAB_VOID)(True)
+ except BadExpression:
+ EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DSC: %s" %
+ (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
+ Value, ValueSize = ParseFieldValue (FieldList)
+
+ if (SkuName, DefaultStoreName) == (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT):
+ if isinstance(Value, str):
+ if "{CODE(" in Value:
+ if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
+ pcdarraysize = Pcd.PcdArraySize()
+ CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType, valuefrom)
+ CApp = CApp+ ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ CApp = CApp + ' memcpy (Pcd, &%s_%s_%s_%s_Value,PcdArraySize);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ else:
+ CApp = CApp + ' Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ if Pcd.IsArray():
+ pcdarraysize = Pcd.PcdArraySize()
+ if "{CODE(" in pcddefaultvalue:
+ if Pcd.Capacity[-1] != "-1":
+ CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
+ CApp = CApp + ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ CApp = CApp + ' memcpy (Pcd, %s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ else:
+ if Pcd.Capacity[-1] != "-1":
+ CApp = CApp + '__STATIC_ASSERT(%d < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (ValueSize,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
+ CApp = CApp + ' PcdArraySize = %d;\n' % ValueSize
+ CApp = CApp + ' Value = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
+ CApp = CApp + ' memcpy (Pcd, Value, PcdArraySize);\n'
+ else:
+ if "{CODE(" in pcddefaultvalue:
+ CApp = CApp + ' PcdArraySize = %d < sizeof(%s) * %d ? %d: sizeof(%s) * %d;\n ' % (ValueSize,Pcd.BaseDatumType,pcdarraysize,ValueSize,Pcd.BaseDatumType,pcdarraysize)
+ CApp = CApp + ' memcpy (Pcd, &%s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ else:
+ CApp = CApp + ' Value = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DefaultFromDSC.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
+ CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
+ else:
+ if isinstance(Value, str):
+ if "{CODE(" in Value:
+ if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
+ pcdarraysize = Pcd.PcdArraySize()
+ CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
+ CApp = CApp + ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n '% (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ CApp = CApp + ' memcpy (Pcd, &%s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ else:
+ CApp = CApp + ' Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DscRawValue.get(SkuName, {}).get(DefaultStoreName))
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ if Pcd.IsArray():
+ pcdarraysize = Pcd.PcdArraySize()
+ if "{CODE(" in pcddefaultvalue:
+ if Pcd.Capacity[-1] != "-1":
+ CApp = CApp + '__STATIC_ASSERT(sizeof(%s_%s_%s_%s_Value) < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
+ CApp + ' PcdArraySize = sizeof(%s_%s_%s_%s_Value);\n ' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ CApp = CApp + ' memcpy (Pcd, %s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ else:
+ if Pcd.Capacity[-1] != "-1":
+ CApp = CApp + '__STATIC_ASSERT(%d < %d * sizeof(%s), "Pcd %s.%s Value in Dsc exceed the array capability %s"); // From %s \n' % (ValueSize,pcdarraysize,Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType,valuefrom)
+ CApp = CApp + ' PcdArraySize = %d;\n' % ValueSize
+ CApp = CApp + ' Value = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DscRawValue.get(TAB_DEFAULT, {}).get(TAB_DEFAULT_STORES_DEFAULT, Pcd.DefaultValue) if Pcd.DefaultFromDSC else Pcd.DefaultValue)
+ CApp = CApp + ' memcpy (Pcd, Value, PcdArraySize);\n'
+ else:
+ if "{CODE(" in pcddefaultvalue:
+ CApp = CApp + ' PcdArraySize = %d < sizeof(%s) * %d ? %d: sizeof(%s) * %d;\n ' % (ValueSize,Pcd.BaseDatumType,pcdarraysize,ValueSize,Pcd.BaseDatumType,pcdarraysize)
+ CApp = CApp + ' memcpy (Pcd, &%s_%s_%s_%s_Value, PcdArraySize);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,SkuName, DefaultStoreName)
+ else:
+ CApp = CApp + ' Value = %s; // From DSC Default Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), Pcd.DscRawValue.get(SkuName, {}).get(DefaultStoreName))
+ CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
+
+ inheritvalue = inherit_OverrideValues.get(DefaultStoreName)
+ if not inheritvalue:
+ inheritvalue = []
+ for index in inheritvalue:
+ FieldList = inheritvalue[index]
+ if not FieldList:
+ continue
+ if (SkuName, DefaultStoreName) == (TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT) or (( (SkuName, '') not in Pcd.ValueChain) and ( (SkuName, DefaultStoreName) not in Pcd.ValueChain )):
+ for FieldName in FieldList:
+ indicator = self.GetIndicator(index, FieldName,Pcd)
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
+ if IsArray:
+ try:
+ FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ try:
+ Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
+ except Exception:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
+ CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' memcpy (&%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (indicator, ValueSize, ValueSize)
+ else:
+ if '[' in FieldName and ']' in FieldName:
+ Index = int(FieldName.split('[')[1].split(']')[0])
+ CApp = CApp + ' __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
+ if ValueSize > 4:
+ CApp = CApp + ' %s = %dULL; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ else:
+ CApp = CApp + ' %s = %d; // From %s Line %d Value %s\n' % (indicator, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + "}\n"
+ return CApp
+
+ @staticmethod
+ def GenerateInitValueStatement(Pcd, SkuName, DefaultStoreName):
+ CApp = ' Assign_%s_%s_%s_%s_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, SkuName, DefaultStoreName)
+ return CApp
+
+ def GenerateCommandLineValue(self, Pcd):
+ CApp = "// Value in CommandLine\n"
+ CApp = CApp + "void Assign_%s_%s_CommandLine_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.BaseDatumType)
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+
+ pcddefaultvalue = Pcd.PcdValueFromComm
+ for FieldList in [pcddefaultvalue, Pcd.PcdFieldValueFromComm]:
+ if not FieldList:
+ continue
+ if pcddefaultvalue and FieldList == pcddefaultvalue:
+ IsArray = _IsFieldValueAnArray(FieldList)
+ if IsArray:
+ try:
+ FieldList = ValueExpressionEx(FieldList, TAB_VOID)(True)
+ except BadExpression:
+ EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from Command: %s" %
+ (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
+ Value, ValueSize = ParseFieldValue (FieldList)
+
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd = %s; // From Command Line \n' % (Value)
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' Value = %s; // From Command Line.\n' % (DscBuildData.IntToCString(Value, ValueSize))
+ CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
+ continue
+ for FieldName in FieldList:
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
+ if IsArray:
+ try:
+ FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ except:
+ print("error")
+ try:
+ Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
+ except Exception:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
+ CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
+ else:
+ if '[' in FieldName and ']' in FieldName:
+ Index = int(FieldName.split('[')[1].split(']')[0])
+ CApp = CApp + ' __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
+ if ValueSize > 4:
+ CApp = CApp + ' Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ else:
+ CApp = CApp + ' Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + "}\n"
+ return CApp
+
+ def GenerateModuleScopeValue(self, Pcd):
+ CApp = "// Value in Dsc Module scope \n"
+ for ModuleGuid in Pcd.PcdFiledValueFromDscComponent:
+
+ CApp = CApp + "void Assign_%s_%s_%s_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, ModuleGuid,Pcd.BaseDatumType)
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+ pcddefaultvalue, file_path,lineNo = Pcd.PcdValueFromComponents.get(ModuleGuid,(None,None,None))
+
+ if pcddefaultvalue:
+ IsArray = _IsFieldValueAnArray(pcddefaultvalue)
+ if IsArray:
+ try:
+ FieldList = ValueExpressionEx(pcddefaultvalue, TAB_VOID)(True)
+ except BadExpression:
+ EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from %s Line %s: %s" %
+ (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, file_path, lineNo, FieldList))
+ Value, ValueSize = ParseFieldValue (FieldList)
+
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd = %s; // From %s Line %s \n' % (Value, file_path, lineNo)
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' Value = %s; // From %s Line %s.\n' % (DscBuildData.IntToCString(Value, ValueSize), file_path, lineNo)
+ CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
+
+
+ PcdFiledValue = Pcd.PcdFiledValueFromDscComponent.get(ModuleGuid)
+ for index in PcdFiledValue:
+ FieldList = PcdFiledValue[index]
+ if not FieldList:
+ continue
+ for FieldName in FieldList:
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
+ if IsArray:
+ try:
+ FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ except:
+ print("error")
+ try:
+ Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
+ except Exception:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
+ CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
+ else:
+ if '[' in FieldName and ']' in FieldName:
+ Index = int(FieldName.split('[')[1].split(']')[0])
+ CApp = CApp + ' __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
+ if ValueSize > 4:
+ CApp = CApp + ' Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ else:
+ CApp = CApp + ' Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + "}\n"
+ return CApp
+
+ @staticmethod
+ def GenerateCommandLineValueStatement(Pcd):
+ CApp = ' Assign_%s_%s_CommandLine_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ return CApp
+ def GenerateFdfValue(self,Pcd):
+ CApp = "// Value in Fdf\n"
+ CApp = CApp + "void Assign_%s_%s_Fdf_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.BaseDatumType)
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+
+ pcddefaultvalue = Pcd.PcdValueFromFdf
+ for FieldList in [pcddefaultvalue,Pcd.PcdFieldValueFromFdf]:
+ if not FieldList:
+ continue
+ if pcddefaultvalue and FieldList == pcddefaultvalue:
+ IsArray = _IsFieldValueAnArray(FieldList)
+ if IsArray:
+ try:
+ FieldList = ValueExpressionEx(FieldList, TAB_VOID)(True)
+ except BadExpression:
+ EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from Fdf: %s" %
+ (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldList))
+ Value, ValueSize = ParseFieldValue (FieldList)
+
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd = %s; // From Fdf \n' % (Value)
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' Value = %s; // From Fdf .\n' % (DscBuildData.IntToCString(Value, ValueSize))
+ CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
+ continue
+ for FieldName in FieldList:
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
+ if IsArray:
+ try:
+ FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ except:
+ print("error")
+ try:
+ Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
+ except Exception:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName,FieldName)),FieldList[FieldName][1], FieldList[FieldName][2]))
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
+ CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
+ else:
+ if '[' in FieldName and ']' in FieldName:
+ Index = int(FieldName.split('[')[1].split(']')[0])
+ CApp = CApp + ' __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
+ if ValueSize > 4:
+ CApp = CApp + ' Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ else:
+ CApp = CApp + ' Pcd->%s = %d; // From %s Line %s Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + "}\n"
+ return CApp
+
+ @staticmethod
+ def GenerateFdfValueStatement(Pcd):
+ CApp = ' Assign_%s_%s_Fdf_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ return CApp
+
+ @staticmethod
+ def GenerateModuleValueStatement(module_guid, Pcd):
+ CApp = " Assign_%s_%s_%s_Value(Pcd);\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, module_guid)
+ return CApp
+ def GenerateModuleScopeInitializeFunc(self,SkuName, Pcd, InitByteValue, CApp):
+ for module_guid in Pcd.PcdFiledValueFromDscComponent:
+ CApp = CApp + 'void\n'
+ CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ CApp = CApp + ' void\n'
+ CApp = CApp + ' )\n'
+ CApp = CApp + '{\n'
+ CApp = CApp + ' UINT32 Size;\n'
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+ CApp = CApp + ' UINT32 OriginalSize;\n'
+ CApp = CApp + ' VOID *OriginalPcd;\n'
+
+ CApp = CApp + ' %s *Pcd; // From %s Line %d \n' % (Pcd.BaseDatumType,Pcd.PkgPath, Pcd.PcdDefineLineNo)
+
+ CApp = CApp + '\n'
+
+ PcdDefaultValue = StringToArray(Pcd.DefaultValueFromDec.strip())
+ InitByteValue += '%s.%s.%s.%s|%s|%s\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DatumType, PcdDefaultValue)
+ #
+ # Get current PCD value and size
+ #
+ CApp = CApp + ' OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+
+ #
+ # Determine the size of the PCD. For simple structures, sizeof(TYPE) provides
+ # the correct value. For structures with a flexible array member, the flexible
+ # array member is detected, and the size is based on the highest index used with
+ # the flexible array member. The flexible array member must be the last field
+ # in a structure. The size formula for this case is:
+ # OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1)
+ #
+ CApp = CApp + DscBuildData.GenerateSizeStatments(Pcd,SkuName,TAB_DEFAULT_STORES_DEFAULT)
+ if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
+ CApp = CApp + ' OriginalSize = OriginalSize < sizeof(%s) * %d? OriginalSize:sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize(),Pcd.BaseDatumType,Pcd.PcdArraySize())
+ CApp = CApp + ' Size = sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize())
+
+ #
+ # Allocate and zero buffer for the PCD
+ # Must handle cases where current value is smaller, larger, or same size
+ # Always keep that larger one as the current size
+ #
+ CApp = CApp + ' Size = (OriginalSize > Size ? OriginalSize : Size);\n'
+ CApp = CApp + ' Pcd = (%s *)malloc (Size);\n' % (Pcd.BaseDatumType,)
+ CApp = CApp + ' memset (Pcd, 0, Size);\n'
+
+ #
+ # Copy current PCD value into allocated buffer.
+ #
+ CApp = CApp + ' memcpy (Pcd, OriginalPcd, OriginalSize);\n'
+
+ #
+ # Assign field values in PCD
+ #
+ CApp = CApp + DscBuildData.GenerateDefaultValueAssignStatement(Pcd)
+
+ CApp = CApp + "// SkuName: %s, DefaultStoreName: STANDARD \n" % self.SkuIdMgr.SystemSkuId
+ CApp = CApp + DscBuildData.GenerateInitValueStatement(Pcd, self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT)
+ CApp = CApp + DscBuildData.GenerateModuleValueStatement(module_guid,Pcd)
+ CApp = CApp + DscBuildData.GenerateFdfValueStatement(Pcd)
+ CApp = CApp + DscBuildData.GenerateCommandLineValueStatement(Pcd)
+
+ #
+ # Set new PCD value and size
+ #
+ CApp = CApp + ' PcdSetPtr (%s, %s, %s, %s, Size, (void *)Pcd);\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+
+ #
+ # Free PCD
+ #
+ CApp = CApp + ' free (Pcd);\n'
+ CApp = CApp + '}\n'
+ CApp = CApp + '\n'
+ return InitByteValue,CApp
+
+ def GenerateInitializeFunc(self, SkuName, DefaultStore, Pcd, InitByteValue, CApp):
+ OverrideValues = {DefaultStore:{}}
+ if Pcd.SkuOverrideValues:
+ OverrideValues = Pcd.SkuOverrideValues[SkuName]
+ if not OverrideValues:
+ OverrideValues = {TAB_DEFAULT_STORES_DEFAULT:Pcd.DefaultValues}
+ for DefaultStoreName in OverrideValues:
+ CApp = CApp + 'void\n'
+ CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ CApp = CApp + ' void\n'
+ CApp = CApp + ' )\n'
+ CApp = CApp + '{\n'
+ CApp = CApp + ' UINT32 Size;\n'
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+ CApp = CApp + ' UINT32 OriginalSize;\n'
+ CApp = CApp + ' VOID *OriginalPcd;\n'
+
+ CApp = CApp + ' %s *Pcd; // From %s Line %d \n' % (Pcd.BaseDatumType,Pcd.PkgPath, Pcd.PcdDefineLineNo)
+
+ CApp = CApp + '\n'
+
+ PcdDefaultValue = StringToArray(Pcd.DefaultValueFromDec.strip())
+
+ InitByteValue += '%s.%s.%s.%s|%s|%s\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DatumType, PcdDefaultValue)
+
+ #
+ # Get current PCD value and size
+ #
+ CApp = CApp + ' OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+
+ #
+ # Determine the size of the PCD. For simple structures, sizeof(TYPE) provides
+ # the correct value. For structures with a flexible array member, the flexible
+ # array member is detected, and the size is based on the highest index used with
+ # the flexible array member. The flexible array member must be the last field
+ # in a structure. The size formula for this case is:
+ # OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1)
+ #
+ CApp = CApp + DscBuildData.GenerateSizeStatments(Pcd,SkuName,DefaultStoreName)
+ if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
+ CApp = CApp + ' OriginalSize = OriginalSize < sizeof(%s) * %d? OriginalSize:sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize(),Pcd.BaseDatumType,Pcd.PcdArraySize())
+ CApp = CApp + ' Size = sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize())
+
+ #
+ # Allocate and zero buffer for the PCD
+ # Must handle cases where current value is smaller, larger, or same size
+ # Always keep that larger one as the current size
+ #
+ CApp = CApp + ' Size = (OriginalSize > Size ? OriginalSize : Size);\n'
+ CApp = CApp + ' Pcd = (%s *)malloc (Size);\n' % (Pcd.BaseDatumType,)
+ CApp = CApp + ' memset (Pcd, 0, Size);\n'
+
+ #
+ # Copy current PCD value into allocated buffer.
+ #
+ CApp = CApp + ' memcpy (Pcd, OriginalPcd, OriginalSize);\n'
+
+ #
+ # Assign field values in PCD
+ #
+ CApp = CApp + DscBuildData.GenerateDefaultValueAssignStatement(Pcd)
+ if Pcd.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
+ for skuname in self.SkuIdMgr.GetSkuChain(SkuName):
+ storeset = [DefaultStoreName] if DefaultStoreName == TAB_DEFAULT_STORES_DEFAULT else [TAB_DEFAULT_STORES_DEFAULT, DefaultStoreName]
+ for defaultstorenameitem in storeset:
+ CApp = CApp + "// SkuName: %s, DefaultStoreName: %s \n" % (skuname, defaultstorenameitem)
+ CApp = CApp + DscBuildData.GenerateInitValueStatement(Pcd, skuname, defaultstorenameitem)
+ if skuname == SkuName:
+ break
+ else:
+ CApp = CApp + "// SkuName: %s, DefaultStoreName: STANDARD \n" % self.SkuIdMgr.SystemSkuId
+ CApp = CApp + DscBuildData.GenerateInitValueStatement(Pcd, self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT)
+ CApp = CApp + DscBuildData.GenerateFdfValueStatement(Pcd)
+ CApp = CApp + DscBuildData.GenerateCommandLineValueStatement(Pcd)
+ #
+ # Set new PCD value and size
+ #
+ CApp = CApp + ' PcdSetPtr (%s, %s, %s, %s, Size, (void *)Pcd);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+
+ #
+ # Free PCD
+ #
+ CApp = CApp + ' free (Pcd);\n'
+ CApp = CApp + '}\n'
+ CApp = CApp + '\n'
+ return InitByteValue, CApp
+
+ def GenerateArrayAssignment(self, Pcd):
+ CApp = ""
+ if not Pcd:
+ return CApp
+ Demesion = ""
+ for d in Pcd.Capacity:
+ Demesion += "[]"
+
+ Value = Pcd.DefaultValueFromDec
+ if "{CODE(" in Pcd.DefaultValueFromDec:
+ realvalue = Pcd.DefaultValueFromDec.strip()[6:-2] # "{CODE(").rstrip(")}"
+ CApp += "static %s %s_%s_INIT_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,Demesion,realvalue)
+
+ if Pcd.Type in PCD_DYNAMIC_TYPE_SET | PCD_DYNAMIC_EX_TYPE_SET:
+ for skuname in Pcd.SkuInfoList:
+ skuinfo = Pcd.SkuInfoList[skuname]
+ if skuinfo.VariableName:
+ for defaultstore in skuinfo.DefaultStoreDict:
+ pcddscrawdefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, skuname, defaultstore)
+ if pcddscrawdefaultvalue:
+ Value = skuinfo.DefaultStoreDict[defaultstore]
+ if "{CODE(" in Value:
+ realvalue = Value.strip()[6:-2] # "{CODE(").rstrip(")}"
+ CApp += "static %s %s_%s_%s_%s_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,defaultstore,Demesion,realvalue)
+ else:
+ pcddscrawdefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, skuname, TAB_DEFAULT_STORES_DEFAULT)
+ if pcddscrawdefaultvalue:
+ Value = skuinfo.DefaultValue
+ if "{CODE(" in Value:
+ realvalue = Value.strip()[6:-2] # "{CODE(").rstrip(")}"
+ CApp += "static %s %s_%s_%s_%s_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,skuname,TAB_DEFAULT_STORES_DEFAULT,Demesion,realvalue)
+ else:
+ pcddscrawdefaultvalue = self.GetPcdDscRawDefaultValue(Pcd, TAB_DEFAULT, TAB_DEFAULT_STORES_DEFAULT)
+ if pcddscrawdefaultvalue:
+ if "{CODE(" in Pcd.DefaultValue:
+ realvalue = Pcd.DefaultValue.strip()[6:-2] # "{CODE(").rstrip(")}"
+ CApp += "static %s %s_%s_DEFAULT_STANDARD_Value%s = %s;\n" % (Pcd.BaseDatumType,Pcd.TokenSpaceGuidCName,Pcd.TokenCName,Demesion,realvalue)
+
+ return CApp
+
+ def SkuOverrideValuesEmpty(self,OverrideValues):
+ if not OverrideValues:
+ return True
+ for key in OverrideValues:
+ if OverrideValues[key]:
+ return False
+ return True
+
+ def ParseCCFlags(self, ccflag):
+ ccflags = set()
+ ccflaglist = ccflag.split(" ")
+ i = 0
+ while i < len(ccflaglist):
+ item = ccflaglist[i].strip()
+ if item in (r"/D", r"/U","-D","-U"):
+ ccflags.add(" ".join((ccflaglist[i],ccflaglist[i+1])))
+ i = i+1
+ elif item.startswith((r"/D", r"/U","-D","-U")):
+ ccflags.add(item)
+ i +=1
+ return ccflags
+ def GenerateByteArrayValue (self, StructuredPcds):
+ #
+ # Generate/Compile/Run C application to determine if there are any flexible array members
+ #
+ if not StructuredPcds:
+ return
+
+ InitByteValue = ""
+ CApp = PcdMainCHeader
+
+ IncludeFiles = set()
+ for PcdName in StructuredPcds:
+ Pcd = StructuredPcds[PcdName]
+ for IncludeFile in Pcd.StructuredPcdIncludeFile:
+ if IncludeFile not in IncludeFiles:
+ IncludeFiles.add(IncludeFile)
+ CApp = CApp + '#include <%s>\n' % (IncludeFile)
+ CApp = CApp + '\n'
+ for Pcd in StructuredPcds.values():
+ CApp = CApp + self.GenerateArrayAssignment(Pcd)
+ for PcdName in sorted(StructuredPcds.keys()):
+ Pcd = StructuredPcds[PcdName]
+
+ #create void void Cal_tocken_cname_Size functions
+ CApp = CApp + self.GenerateSizeFunction(Pcd)
+
+ #create void Assign_ functions
+
+ # From DEC
+ CApp = CApp + self.GenerateDefaultValueAssignFunction(Pcd)
+ # From Fdf
+ CApp = CApp + self.GenerateFdfValue(Pcd)
+ # From CommandLine
+ CApp = CApp + self.GenerateCommandLineValue(Pcd)
+
+ # From Dsc Global setting
+ if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
+ CApp = CApp + self.GenerateInitValueFunction(Pcd, self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT)
+ else:
+ for SkuName in self.SkuIdMgr.SkuOverrideOrder():
+ if SkuName not in Pcd.SkuOverrideValues:
+ continue
+ for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
+ CApp = CApp + self.GenerateInitValueFunction(Pcd, SkuName, DefaultStoreName)
+
+ # From Dsc module scope setting
+ CApp = CApp + self.GenerateModuleScopeValue(Pcd)
+
+ #create Initialize_ functions
+ if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
+ InitByteValue, CApp = self.GenerateInitializeFunc(self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT, Pcd, InitByteValue, CApp)
+ InitByteValue, CApp = self.GenerateModuleScopeInitializeFunc(self.SkuIdMgr.SystemSkuId,Pcd,InitByteValue,CApp)
+ else:
+ for SkuName in self.SkuIdMgr.SkuOverrideOrder():
+ if SkuName not in Pcd.SkuOverrideValues:
+ continue
+ for DefaultStoreName in Pcd.DefaultStoreName:
+ Pcd = StructuredPcds[PcdName]
+ InitByteValue, CApp = self.GenerateInitializeFunc(SkuName, DefaultStoreName, Pcd, InitByteValue, CApp)
+
+ CApp = CApp + 'VOID\n'
+ CApp = CApp + 'PcdEntryPoint(\n'
+ CApp = CApp + ' VOID\n'
+ CApp = CApp + ' )\n'
+ CApp = CApp + '{\n'
+ for Pcd in StructuredPcds.values():
+ if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD], self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
+ CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ for ModuleGuid in Pcd.PcdFiledValueFromDscComponent:
+ CApp += " Initialize_%s_%s_%s_%s();\n" % (ModuleGuid,TAB_DEFAULT_STORES_DEFAULT ,Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ else:
+ for SkuName in self.SkuIdMgr.SkuOverrideOrder():
+ if SkuName not in self.SkuIdMgr.AvailableSkuIdSet:
+ continue
+ for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
+ CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ CApp = CApp + '}\n'
+
+ CApp = CApp + PcdMainCEntry + '\n'
+
+ if not os.path.exists(self.OutputPath):
+ os.makedirs(self.OutputPath)
+ CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
+ SaveFileOnChange(CAppBaseFileName + '.c', CApp, False)
+
+ # start generating makefile
+ MakeApp = PcdMakefileHeader
+ if sys.platform == "win32":
+ MakeApp = MakeApp + 'APPFILE = %s\%s.exe\n' % (self.OutputPath, PcdValueInitName) + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s\%s.obj %s.obj\n' % (self.OutputPath, PcdValueInitName, os.path.join(self.OutputPath, PcdValueCommonName)) + 'INC = '
+ else:
+ MakeApp = MakeApp + PcdGccMakefile
+ MakeApp = MakeApp + 'APPFILE = %s/%s\n' % (self.OutputPath, PcdValueInitName) + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s/%s.o %s.o\n' % (self.OutputPath, PcdValueInitName, os.path.join(self.OutputPath, PcdValueCommonName)) + \
+ 'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'TOOL_INCLUDE +='
+
+ IncSearchList = []
+ PlatformInc = OrderedDict()
+ for Cache in self._Bdb._CACHE_.values():
+ if Cache.MetaFile.Ext.lower() != '.dec':
+ continue
+ if Cache.Includes:
+ if str(Cache.MetaFile.Path) not in PlatformInc:
+ PlatformInc[str(Cache.MetaFile.Path)] = []
+ PlatformInc[str(Cache.MetaFile.Path)].append (os.path.dirname(Cache.MetaFile.Path))
+ PlatformInc[str(Cache.MetaFile.Path)].extend (Cache.CommonIncludes)
+
+ PcdDependDEC = []
+ for Pcd in StructuredPcds.values():
+ for PackageDec in Pcd.PackageDecs:
+ Package = os.path.normpath(mws.join(GlobalData.gWorkspace, PackageDec))
+ if not os.path.exists(Package):
+ EdkLogger.error('Build', RESOURCE_NOT_AVAILABLE, "The dependent Package %s of PCD %s.%s is not exist." % (PackageDec, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
+ if Package not in PcdDependDEC:
+ PcdDependDEC.append(Package)
+
+ if PlatformInc and PcdDependDEC:
+ for pkg in PcdDependDEC:
+ if pkg in PlatformInc:
+ for inc in PlatformInc[pkg]:
+ #
+ # Get list of files in potential -I include path
+ #
+ FileList = os.listdir (str(inc))
+ #
+ # Skip -I include path if one of the include files required
+ # by PcdValueInit.c are present in the include paths from
+ # the DEC file. PcdValueInit.c must use the standard include
+ # files from the host compiler.
+ #
+ if 'stdio.h' in FileList:
+ continue
+ if 'stdlib.h' in FileList:
+ continue
+ if 'string.h' in FileList:
+ continue
+ MakeApp += '-I' + str(inc) + ' '
+ IncSearchList.append(inc)
+ MakeApp = MakeApp + '\n'
+
+ CC_FLAGS = LinuxCFLAGS
+ if sys.platform == "win32":
+ CC_FLAGS = WindowsCFLAGS
+ BuildOptions = OrderedDict()
+ for Options in self.BuildOptions:
+ if Options[2] != EDKII_NAME:
+ continue
+ Family = Options[0]
+ if Family and Family != self.ToolChainFamily:
+ continue
+ Target, Tag, Arch, Tool, Attr = Options[1].split("_")
+ if Tool != 'CC':
+ continue
+ if Attr != "FLAGS":
+ continue
+ if Target == TAB_STAR or Target == self._Target:
+ if Tag == TAB_STAR or Tag == self._Toolchain:
+ if 'COMMON' not in BuildOptions:
+ BuildOptions['COMMON'] = set()
+ if Arch == TAB_STAR:
+ BuildOptions['COMMON']|= self.ParseCCFlags(self.BuildOptions[Options])
+ if Arch in self.SupArchList:
+ if Arch not in BuildOptions:
+ BuildOptions[Arch] = set()
+ BuildOptions[Arch] |= self.ParseCCFlags(self.BuildOptions[Options])
+
+ if BuildOptions:
+ ArchBuildOptions = {arch:flags for arch,flags in BuildOptions.items() if arch != 'COMMON'}
+ if len(ArchBuildOptions.keys()) == 1:
+ BuildOptions['COMMON'] |= (list(ArchBuildOptions.values())[0])
+ elif len(ArchBuildOptions.keys()) > 1:
+ CommonBuildOptions = reduce(lambda x,y: x&y, ArchBuildOptions.values())
+ BuildOptions['COMMON'] |= CommonBuildOptions
+ ValueList = [item for item in BuildOptions['COMMON'] if item.startswith((r"/U","-U"))]
+ ValueList.extend([item for item in BuildOptions['COMMON'] if item.startswith((r"/D", "-D"))])
+ CC_FLAGS += " ".join(ValueList)
+ MakeApp += CC_FLAGS
+
+ if sys.platform == "win32":
+ MakeApp = MakeApp + PcdMakefileEnd
+ MakeApp = MakeApp + AppTarget % ("""\tcopy $(APPLICATION) $(APPFILE) /y """)
+ else:
+ MakeApp = MakeApp + AppTarget % ("""\tcp $(APPLICATION) $(APPFILE) """)
+ MakeApp = MakeApp + '\n'
+ IncludeFileFullPaths = []
+ for includefile in IncludeFiles:
+ for includepath in IncSearchList:
+ includefullpath = os.path.join(str(includepath), includefile)
+ if os.path.exists(includefullpath):
+ IncludeFileFullPaths.append(os.path.normpath(includefullpath))
+ break
+ SearchPathList = []
+ SearchPathList.append(os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "BaseTools/Source/C/Include")))
+ SearchPathList.append(os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "BaseTools/Source/C/Common")))
+ SearchPathList.extend(str(item) for item in IncSearchList)
+ IncFileList = GetDependencyList(IncludeFileFullPaths, SearchPathList)
+ for include_file in IncFileList:
+ MakeApp += "$(OBJECTS) : %s\n" % include_file
+ if sys.platform == "win32":
+ PcdValueCommonPath = os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "Source\C\Common\PcdValueCommon.c"))
+ MakeApp = MakeApp + '%s\PcdValueCommon.c : %s\n' % (self.OutputPath, PcdValueCommonPath)
+ MakeApp = MakeApp + '\tcopy /y %s $@\n' % (PcdValueCommonPath)
+ else:
+ PcdValueCommonPath = os.path.normpath(mws.join(GlobalData.gGlobalDefines["EDK_TOOLS_PATH"], "Source/C/Common/PcdValueCommon.c"))
+ MakeApp = MakeApp + '%s/PcdValueCommon.c : %s\n' % (self.OutputPath, PcdValueCommonPath)
+ MakeApp = MakeApp + '\tcp -f %s %s/PcdValueCommon.c\n' % (PcdValueCommonPath, self.OutputPath)
+ MakeFileName = os.path.join(self.OutputPath, 'Makefile')
+ MakeApp += "$(OBJECTS) : %s\n" % MakeFileName
+ SaveFileOnChange(MakeFileName, MakeApp, False)
+
+ # start generating input file
+ InputValueFile = os.path.join(self.OutputPath, 'Input.txt')
+ OutputValueFile = os.path.join(self.OutputPath, 'Output.txt')
+ SaveFileOnChange(InputValueFile, InitByteValue, False)
+
+ Dest_PcdValueInitExe = PcdValueInitName
+ if not sys.platform == "win32":
+ Dest_PcdValueInitExe = os.path.join(self.OutputPath, PcdValueInitName)
+ else:
+ Dest_PcdValueInitExe = os.path.join(self.OutputPath, PcdValueInitName) +".exe"
+
+ #start building the structure pcd value tool
+ Messages = ''
+ if sys.platform == "win32":
+ MakeCommand = 'nmake -f %s' % (MakeFileName)
+ returncode, StdOut, StdErr = DscBuildData.ExecuteCommand (MakeCommand)
+ Messages = StdOut
+ else:
+ MakeCommand = 'make -f %s' % (MakeFileName)
+ returncode, StdOut, StdErr = DscBuildData.ExecuteCommand (MakeCommand)
+ Messages = StdErr
+
+ EdkLogger.verbose ('%s\n%s\n%s' % (MakeCommand, StdOut, StdErr))
+ Messages = Messages.split('\n')
+ MessageGroup = []
+ if returncode != 0:
+ CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
+ File = open (CAppBaseFileName + '.c', 'r')
+ FileData = File.readlines()
+ File.close()
+ for Message in Messages:
+ if " error" in Message or "warning" in Message:
+ try:
+ FileInfo = Message.strip().split('(')
+ if len (FileInfo) > 1:
+ FileName = FileInfo [0]
+ FileLine = FileInfo [1].split (')')[0]
+ else:
+ FileInfo = Message.strip().split(':')
+ if len(FileInfo) < 2:
+ continue
+ FileName = FileInfo [0]
+ FileLine = FileInfo [1]
+ except:
+ continue
+ if "PcdValueInit.c" not in FileName:
+ continue
+ if FileLine.isdigit():
+ error_line = FileData[int (FileLine) - 1]
+ if r"//" in error_line:
+ c_line, dsc_line = error_line.split(r"//")
+ else:
+ dsc_line = error_line
+ message_itmes = Message.split(":")
+ Index = 0
+ if "PcdValueInit.c" not in Message:
+ if not MessageGroup:
+ MessageGroup.append(Message)
+ break
+ else:
+ for item in message_itmes:
+ if "PcdValueInit.c" in item:
+ Index = message_itmes.index(item)
+ message_itmes[Index] = dsc_line.strip()
+ break
+ MessageGroup.append(":".join(message_itmes[Index:]).strip())
+ continue
+ else:
+ MessageGroup.append(Message)
+ if MessageGroup:
+ EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "\n".join(MessageGroup) )
+ else:
+ EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s\n%s\n%s' % (MakeCommand, StdOut, StdErr))
+
+ #start executing the structure pcd value tool
+ if DscBuildData.NeedUpdateOutput(OutputValueFile, Dest_PcdValueInitExe, InputValueFile):
+ Command = Dest_PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile)
+ returncode, StdOut, StdErr = DscBuildData.ExecuteCommand (Command)
+ EdkLogger.verbose ('%s\n%s\n%s' % (Command, StdOut, StdErr))
+ if returncode != 0:
+ EdkLogger.warn('Build', COMMAND_FAILURE, 'Can not collect output from command: %s\n%s\n' % (Command, StdOut, StdErr))
+
+ #start update structure pcd final value
+ File = open (OutputValueFile, 'r')
+ FileBuffer = File.readlines()
+ File.close()
+
+ StructurePcdSet = []
+ for Pcd in FileBuffer:
+ PcdValue = Pcd.split ('|')
+ PcdInfo = PcdValue[0].split ('.')
+ StructurePcdSet.append((PcdInfo[0], PcdInfo[1], PcdInfo[2], PcdInfo[3], PcdValue[2].strip()))
+ return StructurePcdSet
+
+ @staticmethod
+ def NeedUpdateOutput(OutputFile, ValueCFile, StructureInput):
+ if not os.path.exists(OutputFile):
+ return True
+ if os.stat(OutputFile).st_mtime <= os.stat(ValueCFile).st_mtime:
+ return True
+ if os.stat(OutputFile).st_mtime <= os.stat(StructureInput).st_mtime:
+ return True
+ return False
+
+ ## Retrieve dynamic PCD settings
+ #
+ # @param Type PCD type
+ #
+ # @retval a dict object contains settings of given PCD type
+ #
+ def _GetDynamicPcd(self, Type):
+
+
+ Pcds = OrderedDict()
+ #
+ # tdict is a special dict kind of type, used for selecting correct
+ # PCD settings for certain ARCH and SKU
+ #
+ PcdDict = tdict(True, 4)
+ PcdList = []
+ # Find out all possible PCD candidates for self._Arch
+ RecordList = self._RawData[Type, self._Arch]
+ AvailableSkuIdSet = copy.copy(self.SkuIds)
+
+
+ for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4, Dummy5 in RecordList:
+ SkuName = SkuName.upper()
+ SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
+ if SkuName not in AvailableSkuIdSet:
+ EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
+ File=self.MetaFile, Line=Dummy5)
+ if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, Dummy5) not in PcdList:
+ PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
+ PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
+
+ # Remove redundant PCD candidates, per the ARCH and SKU
+ for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
+
+ Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
+ if Setting is None:
+ continue
+
+ PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
+ if MaxDatumSize:
+ if int(MaxDatumSize, 0) > 0xFFFF:
+ EdkLogger.error('build', FORMAT_INVALID, "The size value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)),
+ File=self.MetaFile, Line=Dummy4)
+ if int(MaxDatumSize, 0) < 0:
+ EdkLogger.error('build', FORMAT_INVALID, "The size value can't be set to negative value for %s." % ".".join((TokenSpaceGuid, PcdCName)),
+ File=self.MetaFile, Line=Dummy4)
+ SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', '', PcdValue)
+ if (PcdCName, TokenSpaceGuid) in Pcds:
+ pcdObject = Pcds[PcdCName, TokenSpaceGuid]
+ pcdObject.SkuInfoList[SkuName] = SkuInfo
+ if MaxDatumSize.strip():
+ CurrentMaxSize = int(MaxDatumSize.strip(), 0)
+ else:
+ CurrentMaxSize = 0
+ if pcdObject.MaxDatumSize:
+ PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
+ else:
+ PcdMaxSize = 0
+ if CurrentMaxSize > PcdMaxSize:
+ pcdObject.MaxDatumSize = str(CurrentMaxSize)
+ else:
+ Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
+ PcdCName,
+ TokenSpaceGuid,
+ self._PCD_TYPE_STRING_[Type],
+ DatumType,
+ PcdValue,
+ '',
+ MaxDatumSize,
+ OrderedDict({SkuName : SkuInfo}),
+ False,
+ None,
+ IsDsc=True)
+
+ if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][TAB_DEFAULT_STORES_DEFAULT] = PcdValue
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][TAB_DEFAULT_STORES_DEFAULT] = (self.MetaFile.File,Dummy4)
+
+ for pcd in Pcds.values():
+ pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
+ # Only fix the value while no value provided in DSC file.
+ for sku in pcd.SkuInfoList.values():
+ if not sku.DefaultValue:
+ sku.DefaultValue = pcdDecObject.DefaultValue
+ if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON not in pcd.SkuInfoList:
+ valuefromDec = pcdDecObject.DefaultValue
+ SkuInfo = SkuInfoClass(TAB_DEFAULT, '0', '', '', '', '', '', valuefromDec)
+ pcd.SkuInfoList[TAB_DEFAULT] = SkuInfo
+ elif TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
+ del pcd.SkuInfoList[TAB_COMMON]
+ elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ del pcd.SkuInfoList[TAB_COMMON]
+
+ list(map(self.FilterSkuSettings, Pcds.values()))
+
+ return Pcds
+
+ def FilterSkuSettings(self, PcdObj):
+
+ if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE:
+ if TAB_DEFAULT in PcdObj.SkuInfoList and self.SkuIdMgr.SystemSkuId not in PcdObj.SkuInfoList:
+ PcdObj.SkuInfoList[self.SkuIdMgr.SystemSkuId] = PcdObj.SkuInfoList[TAB_DEFAULT]
+ PcdObj.SkuInfoList = {TAB_DEFAULT:PcdObj.SkuInfoList[self.SkuIdMgr.SystemSkuId]}
+ PcdObj.SkuInfoList[TAB_DEFAULT].SkuIdName = TAB_DEFAULT
+ PcdObj.SkuInfoList[TAB_DEFAULT].SkuId = '0'
+
+ elif self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.DEFAULT:
+ PcdObj.SkuInfoList = {TAB_DEFAULT:PcdObj.SkuInfoList[TAB_DEFAULT]}
+
+ return PcdObj
+
+ @staticmethod
+ def CompareVarAttr(Attr1, Attr2):
+ if not Attr1 or not Attr2: # for empty string
+ return True
+ Attr1s = [attr.strip() for attr in Attr1.split(",")]
+ Attr1Set = set(Attr1s)
+ Attr2s = [attr.strip() for attr in Attr2.split(",")]
+ Attr2Set = set(Attr2s)
+ if Attr2Set == Attr1Set:
+ return True
+ else:
+ return False
+
+ def CompletePcdValues(self, PcdSet):
+ Pcds = OrderedDict()
+ DefaultStoreObj = DefaultStore(self._GetDefaultStores())
+ SkuIds = {skuname:skuid for skuname, skuid in self.SkuIdMgr.AvailableSkuIdSet.items() if skuname != TAB_COMMON}
+ DefaultStores = set(storename for pcdobj in PcdSet.values() for skuobj in pcdobj.SkuInfoList.values() for storename in skuobj.DefaultStoreDict)
+ for PcdCName, TokenSpaceGuid in PcdSet:
+ PcdObj = PcdSet[(PcdCName, TokenSpaceGuid)]
+
+ if PcdObj.Type not in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_DEFAULT],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_VPD],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_DEFAULT],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII],
+ self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_VPD]]:
+ Pcds[PcdCName, TokenSpaceGuid]= PcdObj
+ continue
+ PcdType = PcdObj.Type
+ if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ for skuid in PcdObj.SkuInfoList:
+ skuobj = PcdObj.SkuInfoList[skuid]
+ mindefaultstorename = DefaultStoreObj.GetMin(set(defaultstorename for defaultstorename in skuobj.DefaultStoreDict))
+ for defaultstorename in DefaultStores:
+ if defaultstorename not in skuobj.DefaultStoreDict:
+ skuobj.DefaultStoreDict[defaultstorename] = skuobj.DefaultStoreDict[mindefaultstorename]
+ skuobj.HiiDefaultValue = skuobj.DefaultStoreDict[mindefaultstorename]
+ for skuname, skuid in SkuIds.items():
+ if skuname not in PcdObj.SkuInfoList:
+ nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
+ while nextskuid not in PcdObj.SkuInfoList:
+ nextskuid = self.SkuIdMgr.GetNextSkuId(nextskuid)
+ PcdObj.SkuInfoList[skuname] = copy.deepcopy(PcdObj.SkuInfoList[nextskuid])
+ PcdObj.SkuInfoList[skuname].SkuId = skuid
+ PcdObj.SkuInfoList[skuname].SkuIdName = skuname
+ if PcdType in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:
+ PcdObj.DefaultValue = list(PcdObj.SkuInfoList.values())[0].HiiDefaultValue if self.SkuIdMgr.SkuUsageType == self.SkuIdMgr.SINGLE else PcdObj.SkuInfoList[TAB_DEFAULT].HiiDefaultValue
+ Pcds[PcdCName, TokenSpaceGuid]= PcdObj
+ return Pcds
+ ## Retrieve dynamic HII PCD settings
+ #
+ # @param Type PCD type
+ #
+ # @retval a dict object contains settings of given PCD type
+ #
+ def _GetDynamicHiiPcd(self, Type):
+
+ VariableAttrs = {}
+
+ Pcds = OrderedDict()
+ UserDefinedDefaultStores = []
+ #
+ # tdict is a special dict kind of type, used for selecting correct
+ # PCD settings for certain ARCH and SKU
+ #
+ PcdDict = tdict(True, 5)
+ PcdList = []
+ RecordList = self._RawData[Type, self._Arch]
+ # Find out all possible PCD candidates for self._Arch
+ AvailableSkuIdSet = copy.copy(self.SkuIds)
+ DefaultStoresDefine = self._GetDefaultStores()
+
+ for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, DefaultStore, Dummy4, Dummy5 in RecordList:
+ SkuName = SkuName.upper()
+ SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
+ DefaultStore = DefaultStore.upper()
+ if DefaultStore == TAB_COMMON:
+ DefaultStore = TAB_DEFAULT_STORES_DEFAULT
+ else:
+ #The end user define [DefaultStores] and [SKUID_IDENTIFIER.Menufacturing] in DSC
+ UserDefinedDefaultStores.append((PcdCName, TokenSpaceGuid))
+ if SkuName not in AvailableSkuIdSet:
+ EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
+ File=self.MetaFile, Line=Dummy5)
+ if DefaultStore not in DefaultStoresDefine:
+ EdkLogger.error('build', PARAMETER_INVALID, 'DefaultStores %s is not defined in [DefaultStores] section' % DefaultStore,
+ File=self.MetaFile, Line=Dummy5)
+ if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, DefaultStore, Dummy5) not in PcdList:
+ PcdList.append((PcdCName, TokenSpaceGuid, SkuName, DefaultStore, Dummy5))
+ PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid, DefaultStore] = Setting
+
+
+ # Remove redundant PCD candidates, per the ARCH and SKU
+ for index,(PcdCName, TokenSpaceGuid, SkuName, DefaultStore, Dummy4) in enumerate(PcdList):
+
+ Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid, DefaultStore]
+ if Setting is None:
+ continue
+ VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
+
+ rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute)
+ if not rt:
+ EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg),
+ ExtraData="[%s]" % VarAttribute)
+ ExceedMax = False
+ FormatCorrect = True
+ if VariableOffset.isdigit():
+ if int(VariableOffset, 10) > 0xFFFF:
+ ExceedMax = True
+ elif variablePattern.match(VariableOffset):
+ if int(VariableOffset, 16) > 0xFFFF:
+ ExceedMax = True
+ # For Offset written in "A.B"
+ elif VariableOffset.find('.') > -1:
+ VariableOffsetList = VariableOffset.split(".")
+ if not (len(VariableOffsetList) == 2
+ and IsValidWord(VariableOffsetList[0])
+ and IsValidWord(VariableOffsetList[1])):
+ FormatCorrect = False
+ else:
+ FormatCorrect = False
+ if not FormatCorrect:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid, PcdCName)))
+
+ if ExceedMax:
+ EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)))
+ if (VariableName, VariableGuid) not in VariableAttrs:
+ VariableAttrs[(VariableName, VariableGuid)] = VarAttribute
+ else:
+ if not DscBuildData.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute):
+ EdkLogger.error('Build', PCD_VARIABLE_ATTRIBUTES_CONFLICT_ERROR, "The variable %s.%s for DynamicHii PCDs has conflicting attributes [%s] and [%s] " % (VariableGuid, VariableName, VarAttribute, VariableAttrs[(VariableName, VariableGuid)]))
+
+ pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid]
+ if (PcdCName, TokenSpaceGuid) in Pcds:
+ pcdObject = Pcds[PcdCName, TokenSpaceGuid]
+ if SkuName in pcdObject.SkuInfoList:
+ Skuitem = pcdObject.SkuInfoList[SkuName]
+ Skuitem.DefaultStoreDict.update({DefaultStore:DefaultValue})
+ else:
+ SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute, DefaultStore={DefaultStore:DefaultValue})
+ pcdObject.SkuInfoList[SkuName] = SkuInfo
+ else:
+ SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute, DefaultStore={DefaultStore:DefaultValue})
+ PcdClassObj = PcdClassObject(
+ PcdCName,
+ TokenSpaceGuid,
+ self._PCD_TYPE_STRING_[Type],
+ '',
+ DefaultValue,
+ '',
+ '',
+ OrderedDict({SkuName : SkuInfo}),
+ False,
+ None,
+ pcdDecObject.validateranges,
+ pcdDecObject.validlists,
+ pcdDecObject.expressions,
+ IsDsc=True)
+ if (PcdCName, TokenSpaceGuid) in UserDefinedDefaultStores:
+ PcdClassObj.UserDefinedDefaultStoresFlag = True
+ Pcds[PcdCName, TokenSpaceGuid] = PcdClassObj
+
+ Pcds[PcdCName, TokenSpaceGuid].CustomAttribute['DscPosition'] = index
+ if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][DefaultStore] = DefaultValue
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][DefaultStore] = (self.MetaFile.File,Dummy4)
+ for pcd in Pcds.values():
+ pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
+ pcd.DatumType = pcdDecObject.DatumType
+ # Only fix the value while no value provided in DSC file.
+ for sku in pcd.SkuInfoList.values():
+ if (sku.HiiDefaultValue == "" or sku.HiiDefaultValue is None):
+ sku.HiiDefaultValue = pcdDecObject.DefaultValue
+ for default_store in sku.DefaultStoreDict:
+ sku.DefaultStoreDict[default_store]=pcdDecObject.DefaultValue
+ pcd.DefaultValue = pcdDecObject.DefaultValue
+ if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON not in pcd.SkuInfoList:
+ SkuInfoObj = list(pcd.SkuInfoList.values())[0]
+ valuefromDec = pcdDecObject.DefaultValue
+ SkuInfo = SkuInfoClass(TAB_DEFAULT, '0', SkuInfoObj.VariableName, SkuInfoObj.VariableGuid, SkuInfoObj.VariableOffset, valuefromDec, VariableAttribute=SkuInfoObj.VariableAttribute, DefaultStore={DefaultStore:valuefromDec})
+ pcd.SkuInfoList[TAB_DEFAULT] = SkuInfo
+ elif TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
+ del pcd.SkuInfoList[TAB_COMMON]
+ elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ del pcd.SkuInfoList[TAB_COMMON]
+
+ if pcd.MaxDatumSize.strip():
+ MaxSize = int(pcd.MaxDatumSize, 0)
+ else:
+ MaxSize = 0
+ if pcd.DatumType not in TAB_PCD_NUMERIC_TYPES:
+ for (_, skuobj) in pcd.SkuInfoList.items():
+ datalen = 0
+ skuobj.HiiDefaultValue = StringToArray(skuobj.HiiDefaultValue)
+ datalen = len(skuobj.HiiDefaultValue.split(","))
+ if datalen > MaxSize:
+ MaxSize = datalen
+ for defaultst in skuobj.DefaultStoreDict:
+ skuobj.DefaultStoreDict[defaultst] = StringToArray(skuobj.DefaultStoreDict[defaultst])
+ pcd.DefaultValue = StringToArray(pcd.DefaultValue)
+ pcd.MaxDatumSize = str(MaxSize)
+ rt, invalidhii = DscBuildData.CheckVariableNameAssignment(Pcds)
+ if not rt:
+ invalidpcd = ",".join(invalidhii)
+ EdkLogger.error('build', PCD_VARIABLE_INFO_ERROR, Message='The same HII PCD must map to the same EFI variable for all SKUs', File=self.MetaFile, ExtraData=invalidpcd)
+
+ list(map(self.FilterSkuSettings, Pcds.values()))
+
+ return Pcds
+
+ @staticmethod
+ def CheckVariableNameAssignment(Pcds):
+ invalidhii = []
+ for pcdname in Pcds:
+ pcd = Pcds[pcdname]
+ varnameset = set(sku.VariableName for (skuid, sku) in pcd.SkuInfoList.items())
+ if len(varnameset) > 1:
+ invalidhii.append(".".join((pcdname[1], pcdname[0])))
+ if len(invalidhii):
+ return False, invalidhii
+ else:
+ return True, []
+ ## Retrieve dynamic VPD PCD settings
+ #
+ # @param Type PCD type
+ #
+ # @retval a dict object contains settings of given PCD type
+ #
+ def _GetDynamicVpdPcd(self, Type):
+
+
+ Pcds = OrderedDict()
+ #
+ # tdict is a special dict kind of type, used for selecting correct
+ # PCD settings for certain ARCH and SKU
+ #
+ PcdDict = tdict(True, 4)
+ PcdList = []
+
+ # Find out all possible PCD candidates for self._Arch
+ RecordList = self._RawData[Type, self._Arch]
+ AvailableSkuIdSet = copy.copy(self.SkuIds)
+
+ for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4, Dummy5 in RecordList:
+ SkuName = SkuName.upper()
+ SkuName = TAB_DEFAULT if SkuName == TAB_COMMON else SkuName
+ if SkuName not in AvailableSkuIdSet:
+ EdkLogger.error('build', PARAMETER_INVALID, 'Sku %s is not defined in [SkuIds] section' % SkuName,
+ File=self.MetaFile, Line=Dummy5)
+ if "." not in TokenSpaceGuid and "[" not in PcdCName and (PcdCName, TokenSpaceGuid, SkuName, Dummy5) not in PcdList:
+ PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy5))
+ PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
+
+ # Remove redundant PCD candidates, per the ARCH and SKU
+ for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:
+ Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
+ if Setting is None:
+ continue
+ #
+ # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue
+ # For the Integer & Boolean type, the optional data can only be InitialValue.
+ # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype
+ # until the DEC parser has been called.
+ #
+ VpdOffset, MaxDatumSize, InitialValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
+ if MaxDatumSize:
+ if int(MaxDatumSize, 0) > 0xFFFF:
+ EdkLogger.error('build', FORMAT_INVALID, "The size value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)),
+ File=self.MetaFile, Line=Dummy4)
+ if int(MaxDatumSize, 0) < 0:
+ EdkLogger.error('build', FORMAT_INVALID, "The size value can't be set to negative value for %s." % ".".join((TokenSpaceGuid, PcdCName)),
+ File=self.MetaFile, Line=Dummy4)
+ SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName][0], '', '', '', '', VpdOffset, InitialValue)
+ if (PcdCName, TokenSpaceGuid) in Pcds:
+ pcdObject = Pcds[PcdCName, TokenSpaceGuid]
+ pcdObject.SkuInfoList[SkuName] = SkuInfo
+ if MaxDatumSize.strip():
+ CurrentMaxSize = int(MaxDatumSize.strip(), 0)
+ else:
+ CurrentMaxSize = 0
+ if pcdObject.MaxDatumSize:
+ PcdMaxSize = int(pcdObject.MaxDatumSize, 0)
+ else:
+ PcdMaxSize = 0
+ if CurrentMaxSize > PcdMaxSize:
+ pcdObject.MaxDatumSize = str(CurrentMaxSize)
+ else:
+ Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
+ PcdCName,
+ TokenSpaceGuid,
+ self._PCD_TYPE_STRING_[Type],
+ '',
+ InitialValue,
+ '',
+ MaxDatumSize,
+ OrderedDict({SkuName : SkuInfo}),
+ False,
+ None,
+ IsDsc=True)
+
+ if SkuName not in Pcds[PcdCName, TokenSpaceGuid].DscRawValue:
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName] = {}
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValue[SkuName][TAB_DEFAULT_STORES_DEFAULT] = InitialValue
+ Pcds[PcdCName, TokenSpaceGuid].DscRawValueInfo[SkuName][TAB_DEFAULT_STORES_DEFAULT] = (self.MetaFile.File,Dummy4)
+ for pcd in Pcds.values():
+ pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]
+ pcd.DatumType = pcdDecObject.DatumType
+ # Only fix the value while no value provided in DSC file.
+ for sku in pcd.SkuInfoList.values():
+ if not sku.DefaultValue:
+ sku.DefaultValue = pcdDecObject.DefaultValue
+ if TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON not in pcd.SkuInfoList:
+ SkuInfoObj = list(pcd.SkuInfoList.values())[0]
+ valuefromDec = pcdDecObject.DefaultValue
+ SkuInfo = SkuInfoClass(TAB_DEFAULT, '0', '', '', '', '', SkuInfoObj.VpdOffset, valuefromDec)
+ pcd.SkuInfoList[TAB_DEFAULT] = SkuInfo
+ elif TAB_DEFAULT not in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ pcd.SkuInfoList[TAB_DEFAULT] = pcd.SkuInfoList[TAB_COMMON]
+ del pcd.SkuInfoList[TAB_COMMON]
+ elif TAB_DEFAULT in pcd.SkuInfoList and TAB_COMMON in pcd.SkuInfoList:
+ del pcd.SkuInfoList[TAB_COMMON]
+
+ #For the same one VOID* pcd, if the default value type of one SKU is "Unicode string",
+ #the other SKUs are "OtherVOID*"(ASCII string or byte array),Then convert "Unicode string" to "byte array".
+ for pcd in Pcds.values():
+ PcdValueTypeSet = set()
+ for sku in pcd.SkuInfoList.values():
+ PcdValueTypeSet.add("UnicodeString" if sku.DefaultValue.startswith(('L"',"L'")) else "OtherVOID*")
+ if len(PcdValueTypeSet) > 1:
+ for sku in pcd.SkuInfoList.values():
+ sku.DefaultValue = StringToArray(sku.DefaultValue) if sku.DefaultValue.startswith(('L"',"L'")) else sku.DefaultValue
+
+ list(map(self.FilterSkuSettings, Pcds.values()))
+ return Pcds
+
+ ## Add external modules
+ #
+ # The external modules are mostly those listed in FDF file, which don't
+ # need "build".
+ #
+ # @param FilePath The path of module description file
+ #
+ def AddModule(self, FilePath):
+ FilePath = NormPath(FilePath)
+ if FilePath not in self.Modules:
+ Module = ModuleBuildClassObject()
+ Module.MetaFile = FilePath
+ self.Modules.append(Module)
+
+ @property
+ def ToolChainFamily(self):
+ self._ToolChainFamily = TAB_COMPILER_MSFT
+ TargetObj = TargetTxtDict()
+ TargetTxt = TargetObj.Target
+ BuildConfigurationFile = os.path.normpath(os.path.join(GlobalData.gConfDirectory, "target.txt"))
+ if os.path.isfile(BuildConfigurationFile) == True:
+ ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
+ if ToolDefinitionFile == '':
+ ToolDefinitionFile = "tools_def.txt"
+ ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))
+ if os.path.isfile(ToolDefinitionFile) == True:
+ ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
+ ToolDefinition = ToolDefObj.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]:
+ self._ToolChainFamily = TAB_COMPILER_MSFT
+ else:
+ self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self._Toolchain]
+ return self._ToolChainFamily
+
+ ## Add external PCDs
+ #
+ # The external PCDs are mostly those listed in FDF file to specify address
+ # or offset information.
+ #
+ # @param Name Name of the PCD
+ # @param Guid Token space guid of the PCD
+ # @param Value Value of the PCD
+ #
+ def AddPcd(self, Name, Guid, Value):
+ if (Name, Guid) not in self.Pcds:
+ self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
+ self.Pcds[Name, Guid].DefaultValue = Value
+
+ @property
+ def DecPcds(self):
+ if self._DecPcds is None:
+ FdfInfList = []
+ if GlobalData.gFdfParser:
+ FdfInfList = GlobalData.gFdfParser.Profile.InfList
+ PkgSet = set()
+ for Inf in FdfInfList:
+ ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)
+ if ModuleFile in self._Modules:
+ continue
+ ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
+ PkgSet.update(ModuleData.Packages)
+ if self.Packages:
+ PkgSet.update(self.Packages)
+ self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain, PkgSet)
+ self._GuidDict.update(GlobalData.gPlatformPcds)
+ return self._DecPcds
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/InfBuildData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/InfBuildData.py
new file mode 100755
index 00000000..8e67e984
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/InfBuildData.py
@@ -0,0 +1,1064 @@
+## @file
+# This file is used to create a database used by build tool
+#
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+from __future__ import absolute_import
+from Common.DataType import *
+from Common.Misc import *
+from Common.caching import cached_property, cached_class_function
+from types import *
+from .MetaFileParser import *
+from collections import OrderedDict
+from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject
+
+## Get Protocol value from given packages
+#
+# @param CName The CName of the GUID
+# @param PackageList List of packages looking-up in
+# @param Inffile The driver file
+#
+# @retval GuidValue if the CName is found in any given package
+# @retval None if the CName is not found in all given packages
+#
+def _ProtocolValue(CName, PackageList, Inffile = None):
+ for P in PackageList:
+ ProtocolKeys = list(P.Protocols.keys())
+ if Inffile and P._PrivateProtocols:
+ if not Inffile.startswith(P.MetaFile.Dir):
+ ProtocolKeys = [x for x in P.Protocols if x not in P._PrivateProtocols]
+ if CName in ProtocolKeys:
+ return P.Protocols[CName]
+ return None
+
+## Get PPI value from given packages
+#
+# @param CName The CName of the GUID
+# @param PackageList List of packages looking-up in
+# @param Inffile The driver file
+#
+# @retval GuidValue if the CName is found in any given package
+# @retval None if the CName is not found in all given packages
+#
+def _PpiValue(CName, PackageList, Inffile = None):
+ for P in PackageList:
+ PpiKeys = list(P.Ppis.keys())
+ if Inffile and P._PrivatePpis:
+ if not Inffile.startswith(P.MetaFile.Dir):
+ PpiKeys = [x for x in P.Ppis if x not in P._PrivatePpis]
+ if CName in PpiKeys:
+ return P.Ppis[CName]
+ return None
+
+## Module build information from INF file
+#
+# This class is used to retrieve information stored in database and convert them
+# into ModuleBuildClassObject form for easier use for AutoGen.
+#
+class InfBuildData(ModuleBuildClassObject):
+ # dict used to convert PCD type in database to string used by build tool
+ _PCD_TYPE_STRING_ = {
+ MODEL_PCD_FIXED_AT_BUILD : TAB_PCDS_FIXED_AT_BUILD,
+ MODEL_PCD_PATCHABLE_IN_MODULE : TAB_PCDS_PATCHABLE_IN_MODULE,
+ MODEL_PCD_FEATURE_FLAG : TAB_PCDS_FEATURE_FLAG,
+ MODEL_PCD_DYNAMIC : TAB_PCDS_DYNAMIC,
+ MODEL_PCD_DYNAMIC_DEFAULT : TAB_PCDS_DYNAMIC,
+ MODEL_PCD_DYNAMIC_HII : TAB_PCDS_DYNAMIC_HII,
+ MODEL_PCD_DYNAMIC_VPD : TAB_PCDS_DYNAMIC_VPD,
+ MODEL_PCD_DYNAMIC_EX : TAB_PCDS_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC_EX_DEFAULT : TAB_PCDS_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC_EX_HII : TAB_PCDS_DYNAMIC_EX_HII,
+ MODEL_PCD_DYNAMIC_EX_VPD : TAB_PCDS_DYNAMIC_EX_VPD,
+ }
+
+ # dict used to convert part of [Defines] to members of InfBuildData directly
+ _PROPERTY_ = {
+ #
+ # Required Fields
+ #
+ TAB_INF_DEFINES_BASE_NAME : "_BaseName",
+ TAB_INF_DEFINES_FILE_GUID : "_Guid",
+ TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType",
+ #
+ # Optional Fields
+ #
+ # TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
+ TAB_INF_DEFINES_COMPONENT_TYPE : "_ComponentType",
+ TAB_INF_DEFINES_MAKEFILE_NAME : "_MakefileName",
+ # TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
+ TAB_INF_DEFINES_DPX_SOURCE :"_DxsFile",
+ TAB_INF_DEFINES_VERSION_NUMBER : "_Version",
+ TAB_INF_DEFINES_VERSION_STRING : "_Version",
+ TAB_INF_DEFINES_VERSION : "_Version",
+ TAB_INF_DEFINES_PCD_IS_DRIVER : "_PcdIsDriver",
+ TAB_INF_DEFINES_SHADOW : "_Shadow"
+ }
+
+ # regular expression for converting XXX_FLAGS in [nmake] section to new type
+ _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE)
+ # dict used to convert old tool name used in [nmake] section to new ones
+ _TOOL_CODE_ = {
+ "C" : "CC",
+ BINARY_FILE_TYPE_LIB : "SLINK",
+ "LINK" : "DLINK",
+ }
+
+
+ ## Constructor of InfBuildData
+ #
+ # Initialize object of InfBuildData
+ #
+ # @param FilePath The path of platform description file
+ # @param RawData The raw data of DSC file
+ # @param BuildDataBase Database used to retrieve module/package information
+ # @param Arch The target architecture
+ # @param Platform The name of platform employing this module
+ # @param Macros Macros used for replacement in DSC file
+ #
+ def __init__(self, FilePath, RawData, BuildDatabase, Arch=TAB_ARCH_COMMON, Target=None, Toolchain=None):
+ self.MetaFile = FilePath
+ self._ModuleDir = FilePath.Dir
+ self._RawData = RawData
+ self._Bdb = BuildDatabase
+ self._Arch = Arch
+ self._Target = Target
+ self._Toolchain = Toolchain
+ self._Platform = TAB_COMMON
+ self._TailComments = None
+ self._BaseName = None
+ self._DxsFile = None
+ self._ModuleType = None
+ self._ComponentType = None
+ self._BuildType = None
+ self._Guid = None
+ self._Version = None
+ self._PcdIsDriver = None
+ self._BinaryModule = None
+ self._Shadow = None
+ self._MakefileName = None
+ self._CustomMakefile = None
+ self._Specification = None
+ self._LibraryClass = None
+ self._ModuleEntryPointList = None
+ self._ModuleUnloadImageList = None
+ self._ConstructorList = None
+ self._DestructorList = None
+ self._Defs = OrderedDict()
+ self._ProtocolComments = None
+ self._PpiComments = None
+ self._GuidsUsedByPcd = OrderedDict()
+ self._GuidComments = None
+ self._PcdComments = None
+ self._BuildOptions = None
+ self._DependencyFileList = None
+ self.LibInstances = []
+ self.ReferenceModules = set()
+
+ def SetReferenceModule(self,Module):
+ self.ReferenceModules.add(Module)
+ return self
+
+ ## XXX[key] = value
+ def __setitem__(self, key, value):
+ self.__dict__[self._PROPERTY_[key]] = value
+
+ ## value = XXX[key]
+ def __getitem__(self, key):
+ return self.__dict__[self._PROPERTY_[key]]
+
+ ## "in" test support
+ def __contains__(self, key):
+ return key in self._PROPERTY_
+
+ ## Get current effective macros
+ @cached_property
+ def _Macros(self):
+ RetVal = {}
+ return RetVal
+
+ ## Get architecture
+ @cached_property
+ def Arch(self):
+ return self._Arch
+
+ ## Return the name of platform employing this module
+ @cached_property
+ def Platform(self):
+ return self._Platform
+
+ @cached_property
+ def HeaderComments(self):
+ return [a[0] for a in self._RawData[MODEL_META_DATA_HEADER_COMMENT]]
+
+ @cached_property
+ def TailComments(self):
+ return [a[0] for a in self._RawData[MODEL_META_DATA_TAIL_COMMENT]]
+
+ ## Retrieve all information in [Defines] section
+ #
+ # (Retrieving all [Defines] information in one-shot is just to save time.)
+ #
+ @cached_class_function
+ def _GetHeaderInfo(self):
+ RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
+ for Record in RecordList:
+ Name, Value = Record[1], ReplaceMacro(Record[2], self._Macros, False)
+ # items defined _PROPERTY_ don't need additional processing
+ if Name in self:
+ self[Name] = Value
+ self._Defs[Name] = Value
+ self._Macros[Name] = Value
+ # some special items in [Defines] section need special treatment
+ elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
+ if Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
+ Name = 'UEFI_SPECIFICATION_VERSION'
+ if self._Specification is None:
+ self._Specification = OrderedDict()
+ self._Specification[Name] = GetHexVerValue(Value)
+ if self._Specification[Name] is None:
+ EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
+ "'%s' format is not supported for %s" % (Value, Name),
+ File=self.MetaFile, Line=Record[-1])
+ elif Name == 'LIBRARY_CLASS':
+ if self._LibraryClass is None:
+ self._LibraryClass = []
+ ValueList = GetSplitValueList(Value)
+ LibraryClass = ValueList[0]
+ if len(ValueList) > 1:
+ SupModuleList = GetSplitValueList(ValueList[1], ' ')
+ else:
+ SupModuleList = SUP_MODULE_LIST
+ self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList))
+ elif Name == 'ENTRY_POINT':
+ if self._ModuleEntryPointList is None:
+ self._ModuleEntryPointList = []
+ self._ModuleEntryPointList.append(Value)
+ elif Name == 'UNLOAD_IMAGE':
+ if self._ModuleUnloadImageList is None:
+ self._ModuleUnloadImageList = []
+ if not Value:
+ continue
+ self._ModuleUnloadImageList.append(Value)
+ elif Name == 'CONSTRUCTOR':
+ if self._ConstructorList is None:
+ self._ConstructorList = []
+ if not Value:
+ continue
+ self._ConstructorList.append(Value)
+ elif Name == 'DESTRUCTOR':
+ if self._DestructorList is None:
+ self._DestructorList = []
+ if not Value:
+ continue
+ self._DestructorList.append(Value)
+ elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE:
+ TokenList = GetSplitValueList(Value)
+ if self._CustomMakefile is None:
+ self._CustomMakefile = {}
+ if len(TokenList) < 2:
+ self._CustomMakefile[TAB_COMPILER_MSFT] = TokenList[0]
+ self._CustomMakefile['GCC'] = TokenList[0]
+ else:
+ if TokenList[0] not in [TAB_COMPILER_MSFT, 'GCC']:
+ EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
+ "No supported family [%s]" % TokenList[0],
+ File=self.MetaFile, Line=Record[-1])
+ self._CustomMakefile[TokenList[0]] = TokenList[1]
+ else:
+ self._Defs[Name] = Value
+ self._Macros[Name] = Value
+
+ #
+ # Retrieve information in sections specific to Edk.x modules
+ #
+ if not self._ModuleType:
+ EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
+ "MODULE_TYPE is not given", File=self.MetaFile)
+ if self._ModuleType not in SUP_MODULE_LIST:
+ RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
+ for Record in RecordList:
+ Name = Record[1]
+ if Name == "MODULE_TYPE":
+ LineNo = Record[6]
+ break
+ EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
+ "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self._ModuleType, ' '.join(l for l in SUP_MODULE_LIST)),
+ File=self.MetaFile, Line=LineNo)
+ if (self._Specification is None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (int(self._Specification['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
+ if self._ModuleType == SUP_MODULE_SMM_CORE:
+ EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.MetaFile)
+ if (self._Specification is None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (int(self._Specification['PI_SPECIFICATION_VERSION'], 16) < 0x00010032):
+ if self._ModuleType == SUP_MODULE_MM_CORE_STANDALONE:
+ EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.MetaFile)
+ if self._ModuleType == SUP_MODULE_MM_STANDALONE:
+ EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "MM_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.MetaFile)
+ if 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \
+ and 'PCI_CLASS_CODE' in self._Defs and 'PCI_REVISION' in self._Defs:
+ self._BuildType = 'UEFI_OPTIONROM'
+ if 'PCI_COMPRESS' in self._Defs:
+ if self._Defs['PCI_COMPRESS'] not in ('TRUE', 'FALSE'):
+ EdkLogger.error("build", FORMAT_INVALID, "Expected TRUE/FALSE for PCI_COMPRESS: %s" % self.MetaFile)
+
+ elif 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
+ and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
+ self._BuildType = 'UEFI_HII'
+ else:
+ self._BuildType = self._ModuleType.upper()
+
+ if self._DxsFile:
+ File = PathClass(NormPath(self._DxsFile), self._ModuleDir, Arch=self._Arch)
+ # check the file validation
+ ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
+ File=self.MetaFile, Line=LineNo)
+ if not self._DependencyFileList:
+ self._DependencyFileList = []
+ self._DependencyFileList.append(File)
+
+ ## Retrieve file version
+ @cached_property
+ def AutoGenVersion(self):
+ RetVal = 0x00010000
+ RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
+ for Record in RecordList:
+ if Record[1] == TAB_INF_DEFINES_INF_VERSION:
+ if '.' in Record[2]:
+ ValueList = Record[2].split('.')
+ Major = '%04o' % int(ValueList[0], 0)
+ Minor = '%04o' % int(ValueList[1], 0)
+ RetVal = int('0x' + Major + Minor, 0)
+ else:
+ RetVal = int(Record[2], 0)
+ break
+ return RetVal
+
+ ## Retrieve BASE_NAME
+ @cached_property
+ def BaseName(self):
+ if self._BaseName is None:
+ self._GetHeaderInfo()
+ if self._BaseName is None:
+ EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile)
+ return self._BaseName
+
+ ## Retrieve DxsFile
+ @cached_property
+ def DxsFile(self):
+ if self._DxsFile is None:
+ self._GetHeaderInfo()
+ if self._DxsFile is None:
+ self._DxsFile = ''
+ return self._DxsFile
+
+ ## Retrieve MODULE_TYPE
+ @cached_property
+ def ModuleType(self):
+ if self._ModuleType is None:
+ self._GetHeaderInfo()
+ if self._ModuleType is None:
+ self._ModuleType = SUP_MODULE_BASE
+ if self._ModuleType not in SUP_MODULE_LIST:
+ self._ModuleType = SUP_MODULE_USER_DEFINED
+ return self._ModuleType
+
+ ## Retrieve COMPONENT_TYPE
+ @cached_property
+ def ComponentType(self):
+ if self._ComponentType is None:
+ self._GetHeaderInfo()
+ if self._ComponentType is None:
+ self._ComponentType = SUP_MODULE_USER_DEFINED
+ return self._ComponentType
+
+ ## Retrieve "BUILD_TYPE"
+ @cached_property
+ def BuildType(self):
+ if self._BuildType is None:
+ self._GetHeaderInfo()
+ if not self._BuildType:
+ self._BuildType = SUP_MODULE_BASE
+ return self._BuildType
+
+ ## Retrieve file guid
+ @cached_property
+ def Guid(self):
+ if self._Guid is None:
+ self._GetHeaderInfo()
+ if self._Guid is None:
+ self._Guid = '00000000-0000-0000-0000-000000000000'
+ return self._Guid
+
+ ## Retrieve module version
+ @cached_property
+ def Version(self):
+ if self._Version is None:
+ self._GetHeaderInfo()
+ if self._Version is None:
+ self._Version = '0.0'
+ return self._Version
+
+ ## Retrieve PCD_IS_DRIVER
+ @cached_property
+ def PcdIsDriver(self):
+ if self._PcdIsDriver is None:
+ self._GetHeaderInfo()
+ if self._PcdIsDriver is None:
+ self._PcdIsDriver = ''
+ return self._PcdIsDriver
+
+ ## Retrieve SHADOW
+ @cached_property
+ def Shadow(self):
+ if self._Shadow is None:
+ self._GetHeaderInfo()
+ if self._Shadow and self._Shadow.upper() == 'TRUE':
+ self._Shadow = True
+ else:
+ self._Shadow = False
+ return self._Shadow
+
+ ## Retrieve CUSTOM_MAKEFILE
+ @cached_property
+ def CustomMakefile(self):
+ if self._CustomMakefile is None:
+ self._GetHeaderInfo()
+ if self._CustomMakefile is None:
+ self._CustomMakefile = {}
+ return self._CustomMakefile
+
+ ## Retrieve EFI_SPECIFICATION_VERSION
+ @cached_property
+ def Specification(self):
+ if self._Specification is None:
+ self._GetHeaderInfo()
+ if self._Specification is None:
+ self._Specification = {}
+ return self._Specification
+
+ ## Retrieve LIBRARY_CLASS
+ @cached_property
+ def LibraryClass(self):
+ if self._LibraryClass is None:
+ self._GetHeaderInfo()
+ if self._LibraryClass is None:
+ self._LibraryClass = []
+ return self._LibraryClass
+
+ ## Retrieve ENTRY_POINT
+ @cached_property
+ def ModuleEntryPointList(self):
+ if self._ModuleEntryPointList is None:
+ self._GetHeaderInfo()
+ if self._ModuleEntryPointList is None:
+ self._ModuleEntryPointList = []
+ return self._ModuleEntryPointList
+
+ ## Retrieve UNLOAD_IMAGE
+ @cached_property
+ def ModuleUnloadImageList(self):
+ if self._ModuleUnloadImageList is None:
+ self._GetHeaderInfo()
+ if self._ModuleUnloadImageList is None:
+ self._ModuleUnloadImageList = []
+ return self._ModuleUnloadImageList
+
+ ## Retrieve CONSTRUCTOR
+ @cached_property
+ def ConstructorList(self):
+ if self._ConstructorList is None:
+ self._GetHeaderInfo()
+ if self._ConstructorList is None:
+ self._ConstructorList = []
+ return self._ConstructorList
+
+ ## Retrieve DESTRUCTOR
+ @cached_property
+ def DestructorList(self):
+ if self._DestructorList is None:
+ self._GetHeaderInfo()
+ if self._DestructorList is None:
+ self._DestructorList = []
+ return self._DestructorList
+
+ ## Retrieve definies other than above ones
+ @cached_property
+ def Defines(self):
+ self._GetHeaderInfo()
+ return self._Defs
+
+ ## Retrieve binary files
+ @cached_class_function
+ def _GetBinaries(self):
+ RetVal = []
+ RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
+ Macros = self._Macros
+ Macros['PROCESSOR'] = self._Arch
+ for Record in RecordList:
+ FileType = Record[0]
+ LineNo = Record[-1]
+ Target = TAB_COMMON
+ FeatureFlag = []
+ if Record[2]:
+ TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
+ if TokenList:
+ Target = TokenList[0]
+ if len(TokenList) > 1:
+ FeatureFlag = Record[1:]
+
+ File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
+ # check the file validation
+ ErrorCode, ErrorInfo = File.Validate()
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+ RetVal.append(File)
+ return RetVal
+
+ ## Retrieve binary files with error check.
+ @cached_property
+ def Binaries(self):
+ RetVal = self._GetBinaries()
+ if GlobalData.gIgnoreSource and not RetVal:
+ ErrorInfo = "The INF file does not contain any RetVal to use in creating the image\n"
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, ExtraData=ErrorInfo, File=self.MetaFile)
+
+ return RetVal
+
+ ## Retrieve source files
+ @cached_property
+ def Sources(self):
+ self._GetHeaderInfo()
+ # Ignore all source files in a binary build mode
+ if GlobalData.gIgnoreSource:
+ return []
+
+ RetVal = []
+ RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
+ Macros = self._Macros
+ for Record in RecordList:
+ LineNo = Record[-1]
+ ToolChainFamily = Record[1]
+ TagName = Record[2]
+ ToolCode = Record[3]
+
+ File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
+ '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
+ # check the file validation
+ ErrorCode, ErrorInfo = File.Validate()
+ if ErrorCode != 0:
+ EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+
+ RetVal.append(File)
+ # add any previously found dependency files to the source list
+ if self._DependencyFileList:
+ RetVal.extend(self._DependencyFileList)
+ return RetVal
+
+ ## Retrieve library classes employed by this module
+ @cached_property
+ def LibraryClasses(self):
+ RetVal = OrderedDict()
+ RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
+ for Record in RecordList:
+ Lib = Record[0]
+ Instance = Record[1]
+ if Instance:
+ Instance = NormPath(Instance, self._Macros)
+ RetVal[Lib] = Instance
+ else:
+ RetVal[Lib] = None
+ return RetVal
+
+ ## Retrieve library names (for Edk.x style of modules)
+ @cached_property
+ def Libraries(self):
+ RetVal = []
+ RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
+ for Record in RecordList:
+ LibraryName = ReplaceMacro(Record[0], self._Macros, False)
+ # in case of name with '.lib' extension, which is unusual in Edk.x inf
+ LibraryName = os.path.splitext(LibraryName)[0]
+ if LibraryName not in RetVal:
+ RetVal.append(LibraryName)
+ return RetVal
+
+ @cached_property
+ def ProtocolComments(self):
+ self.Protocols
+ return self._ProtocolComments
+
+ ## Retrieve protocols consumed/produced by this module
+ @cached_property
+ def Protocols(self):
+ RetVal = OrderedDict()
+ self._ProtocolComments = OrderedDict()
+ RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
+ for Record in RecordList:
+ CName = Record[0]
+ Value = _ProtocolValue(CName, self.Packages, self.MetaFile.Path)
+ if Value is None:
+ PackageList = "\n\t".join(str(P) for P in self.Packages)
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+ "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
+ ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+ RetVal[CName] = Value
+ CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
+ self._ProtocolComments[CName] = [a[0] for a in CommentRecords]
+ return RetVal
+
+ @cached_property
+ def PpiComments(self):
+ self.Ppis
+ return self._PpiComments
+
+ ## Retrieve PPIs consumed/produced by this module
+ @cached_property
+ def Ppis(self):
+ RetVal = OrderedDict()
+ self._PpiComments = OrderedDict()
+ RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
+ for Record in RecordList:
+ CName = Record[0]
+ Value = _PpiValue(CName, self.Packages, self.MetaFile.Path)
+ if Value is None:
+ PackageList = "\n\t".join(str(P) for P in self.Packages)
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+ "Value of PPI [%s] is not found under [Ppis] section in " % CName,
+ ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+ RetVal[CName] = Value
+ CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
+ self._PpiComments[CName] = [a[0] for a in CommentRecords]
+ return RetVal
+
+ @cached_property
+ def GuidComments(self):
+ self.Guids
+ return self._GuidComments
+
+ ## Retrieve GUIDs consumed/produced by this module
+ @cached_property
+ def Guids(self):
+ RetVal = OrderedDict()
+ self._GuidComments = OrderedDict()
+ RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
+ for Record in RecordList:
+ CName = Record[0]
+ Value = GuidValue(CName, self.Packages, self.MetaFile.Path)
+ if Value is None:
+ PackageList = "\n\t".join(str(P) for P in self.Packages)
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+ "Value of Guid [%s] is not found under [Guids] section in" % CName,
+ ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+ RetVal[CName] = Value
+ CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
+ self._GuidComments[CName] = [a[0] for a in CommentRecords]
+
+ for Type in [MODEL_PCD_FIXED_AT_BUILD,MODEL_PCD_PATCHABLE_IN_MODULE,MODEL_PCD_FEATURE_FLAG,MODEL_PCD_DYNAMIC,MODEL_PCD_DYNAMIC_EX]:
+ RecordList = self._RawData[Type, self._Arch, self._Platform]
+ for TokenSpaceGuid, _, _, _, _, _, LineNo in RecordList:
+ # get the guid value
+ if TokenSpaceGuid not in RetVal:
+ Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path)
+ if Value is None:
+ PackageList = "\n\t".join(str(P) for P in self.Packages)
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+ "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid,
+ ExtraData=PackageList, File=self.MetaFile, Line=LineNo)
+ RetVal[TokenSpaceGuid] = Value
+ self._GuidsUsedByPcd[TokenSpaceGuid] = Value
+ return RetVal
+
+ ## Retrieve include paths necessary for this module (for Edk.x style of modules)
+ @cached_property
+ def Includes(self):
+ RetVal = []
+ Macros = self._Macros
+ Macros['PROCESSOR'] = GlobalData.gEdkGlobal.get('PROCESSOR', self._Arch)
+ RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
+ for Record in RecordList:
+ File = NormPath(Record[0], Macros)
+ if File[0] == '.':
+ File = os.path.join(self._ModuleDir, File)
+ else:
+ File = mws.join(GlobalData.gWorkspace, File)
+ File = RealPath(os.path.normpath(File))
+ if File:
+ RetVal.append(File)
+ return RetVal
+
+ ## Retrieve packages this module depends on
+ @cached_property
+ def Packages(self):
+ RetVal = []
+ RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
+ Macros = self._Macros
+ for Record in RecordList:
+ File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
+ # check the file validation
+ ErrorCode, ErrorInfo = File.Validate('.dec')
+ if ErrorCode != 0:
+ LineNo = Record[-1]
+ EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
+ # parse this package now. we need it to get protocol/ppi/guid value
+ RetVal.append(self._Bdb[File, self._Arch, self._Target, self._Toolchain])
+ return RetVal
+
+ ## Retrieve PCD comments
+ @cached_property
+ def PcdComments(self):
+ self.Pcds
+ return self._PcdComments
+
+ ## Retrieve PCDs used in this module
+ @cached_property
+ def Pcds(self):
+ self._PcdComments = OrderedDict()
+ RetVal = OrderedDict()
+ RetVal.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
+ RetVal.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
+ RetVal.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
+ RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC))
+ RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
+ return RetVal
+
+ @cached_property
+ def ModulePcdList(self):
+ RetVal = self.Pcds
+ return RetVal
+ @cached_property
+ def LibraryPcdList(self):
+ if bool(self.LibraryClass):
+ return []
+ RetVal = {}
+ Pcds = set()
+ for Library in self.LibInstances:
+ PcdsInLibrary = OrderedDict()
+ for Key in Library.Pcds:
+ if Key in self.Pcds or Key in Pcds:
+ continue
+ Pcds.add(Key)
+ PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
+ RetVal[Library] = PcdsInLibrary
+ return RetVal
+ @cached_property
+ def PcdsName(self):
+ PcdsName = set()
+ for Type in (MODEL_PCD_FIXED_AT_BUILD,MODEL_PCD_PATCHABLE_IN_MODULE,MODEL_PCD_FEATURE_FLAG,MODEL_PCD_DYNAMIC,MODEL_PCD_DYNAMIC_EX):
+ RecordList = self._RawData[Type, self._Arch, self._Platform]
+ for TokenSpaceGuid, PcdCName, _, _, _, _, _ in RecordList:
+ PcdsName.add((PcdCName, TokenSpaceGuid))
+ return PcdsName
+
+ ## Retrieve build options specific to this module
+ @cached_property
+ def BuildOptions(self):
+ if self._BuildOptions is None:
+ self._BuildOptions = OrderedDict()
+ RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
+ for Record in RecordList:
+ ToolChainFamily = Record[0]
+ ToolChain = Record[1]
+ Option = Record[2]
+ if (ToolChainFamily, ToolChain) not in self._BuildOptions or Option.startswith('='):
+ self._BuildOptions[ToolChainFamily, ToolChain] = Option
+ else:
+ # concatenate the option string if they're for the same tool
+ OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
+ self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
+ return self._BuildOptions
+
+ ## Retrieve dependency expression
+ @cached_property
+ def Depex(self):
+ RetVal = tdict(False, 2)
+
+ # If the module has only Binaries and no Sources, then ignore [Depex]
+ if not self.Sources and self.Binaries:
+ return RetVal
+
+ RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
+ # PEIM and DXE drivers must have a valid [Depex] section
+ if len(self.LibraryClass) == 0 and len(RecordList) == 0:
+ if self.ModuleType == SUP_MODULE_DXE_DRIVER or self.ModuleType == SUP_MODULE_PEIM or self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER or \
+ self.ModuleType == SUP_MODULE_DXE_SAL_DRIVER or self.ModuleType == SUP_MODULE_DXE_RUNTIME_DRIVER:
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
+ % self.ModuleType, File=self.MetaFile)
+
+ if len(RecordList) != 0 and (self.ModuleType == SUP_MODULE_USER_DEFINED or self.ModuleType == SUP_MODULE_HOST_APPLICATION):
+ for Record in RecordList:
+ if Record[4] not in [SUP_MODULE_PEIM, SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_SMM_DRIVER]:
+ EdkLogger.error('build', FORMAT_INVALID,
+ "'%s' module must specify the type of [Depex] section" % self.ModuleType,
+ File=self.MetaFile)
+
+ TemporaryDictionary = OrderedDict()
+ for Record in RecordList:
+ DepexStr = ReplaceMacro(Record[0], self._Macros, False)
+ Arch = Record[3]
+ ModuleType = Record[4]
+ TokenList = DepexStr.split()
+ if (Arch, ModuleType) not in TemporaryDictionary:
+ TemporaryDictionary[Arch, ModuleType] = []
+ DepexList = TemporaryDictionary[Arch, ModuleType]
+ for Token in TokenList:
+ if Token in DEPEX_SUPPORTED_OPCODE_SET:
+ DepexList.append(Token)
+ elif Token.endswith(".inf"): # module file name
+ ModuleFile = os.path.normpath(Token)
+ Module = self.BuildDatabase[ModuleFile]
+ if Module is None:
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
+ ExtraData=Token, File=self.MetaFile, Line=Record[-1])
+ DepexList.append(Module.Guid)
+ else:
+ # it use the Fixed PCD format
+ if '.' in Token:
+ if tuple(Token.split('.')[::-1]) not in self.Pcds:
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "PCD [{}] used in [Depex] section should be listed in module PCD section".format(Token), File=self.MetaFile, Line=Record[-1])
+ else:
+ if self.Pcds[tuple(Token.split('.')[::-1])].DatumType != TAB_VOID:
+ EdkLogger.error('build', FORMAT_INVALID, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token), File=self.MetaFile, Line=Record[-1])
+ Value = Token
+ else:
+ # get the GUID value now
+ Value = _ProtocolValue(Token, self.Packages, self.MetaFile.Path)
+ if Value is None:
+ Value = _PpiValue(Token, self.Packages, self.MetaFile.Path)
+ if Value is None:
+ Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
+
+ if Value is None:
+ PackageList = "\n\t".join(str(P) for P in self.Packages)
+ EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
+ "Value of [%s] is not found in" % Token,
+ ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
+ DepexList.append(Value)
+ for Arch, ModuleType in TemporaryDictionary:
+ RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
+ return RetVal
+
+ ## Retrieve dependency expression
+ @cached_property
+ def DepexExpression(self):
+ RetVal = tdict(False, 2)
+ RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
+ TemporaryDictionary = OrderedDict()
+ for Record in RecordList:
+ DepexStr = ReplaceMacro(Record[0], self._Macros, False)
+ Arch = Record[3]
+ ModuleType = Record[4]
+ TokenList = DepexStr.split()
+ if (Arch, ModuleType) not in TemporaryDictionary:
+ TemporaryDictionary[Arch, ModuleType] = ''
+ for Token in TokenList:
+ TemporaryDictionary[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType] + Token.strip() + ' '
+ for Arch, ModuleType in TemporaryDictionary:
+ RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
+ return RetVal
+ def LocalPkg(self):
+ module_path = self.MetaFile.File
+ subdir = os.path.split(module_path)[0]
+ TopDir = ""
+ while subdir:
+ subdir,TopDir = os.path.split(subdir)
+
+ for file_name in os.listdir(os.path.join(self.MetaFile.Root,TopDir)):
+ if file_name.upper().endswith("DEC"):
+ pkg = os.path.join(TopDir,file_name)
+ return pkg
+ @cached_class_function
+ def GetGuidsUsedByPcd(self):
+ self.Guid
+ return self._GuidsUsedByPcd
+
+ ## Retrieve PCD for given type
+ def _GetPcd(self, Type):
+ Pcds = OrderedDict()
+ PcdDict = tdict(True, 4)
+ PcdList = []
+ RecordList = self._RawData[Type, self._Arch, self._Platform]
+ for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Id, LineNo in RecordList:
+ PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)
+ PcdList.append((PcdCName, TokenSpaceGuid))
+ CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Id]
+ Comments = []
+ for CmtRec in CommentRecords:
+ Comments.append(CmtRec[0])
+ self._PcdComments[TokenSpaceGuid, PcdCName] = Comments
+
+ # resolve PCD type, value, datum info, etc. by getting its definition from package
+ _GuidDict = self.Guids.copy()
+ for PcdCName, TokenSpaceGuid in PcdList:
+ PcdRealName = PcdCName
+ Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]
+ if Setting is None:
+ continue
+ ValueList = AnalyzePcdData(Setting)
+ DefaultValue = ValueList[0]
+ Pcd = PcdClassObject(
+ PcdCName,
+ TokenSpaceGuid,
+ '',
+ '',
+ DefaultValue,
+ '',
+ '',
+ {},
+ False,
+ self.Guids[TokenSpaceGuid]
+ )
+ if Type == MODEL_PCD_PATCHABLE_IN_MODULE and ValueList[1]:
+ # Patch PCD: TokenSpace.PcdCName|Value|Offset
+ Pcd.Offset = ValueList[1]
+
+ if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
+ for Package in self.Packages:
+ for key in Package.Pcds:
+ if (Package.Pcds[key].TokenCName, Package.Pcds[key].TokenSpaceGuidCName) == (PcdRealName, TokenSpaceGuid):
+ for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
+ Pcd_Type = item[0].split('_')[-1]
+ if Pcd_Type == Package.Pcds[key].Type:
+ Value = Package.Pcds[key]
+ Value.TokenCName = Package.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 Package.Pcds[key]
+ Package.Pcds[newkey] = Value
+ break
+ else:
+ pass
+ else:
+ pass
+
+ # get necessary info from package declaring this PCD
+ for Package in self.Packages:
+ #
+ # 'dynamic' in INF means its type is determined by platform;
+ # if platform doesn't give its type, use 'lowest' one in the
+ # following order, if any
+ #
+ # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
+ #
+ _GuidDict.update(Package.Guids)
+ PcdType = self._PCD_TYPE_STRING_[Type]
+ if Type == MODEL_PCD_DYNAMIC:
+ Pcd.Pending = True
+ for T in PCD_TYPE_LIST:
+ if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
+ for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
+ if str(item[0]).endswith(T) and (item[0], item[1], T) in Package.Pcds:
+ PcdType = T
+ PcdCName = item[0]
+ break
+ else:
+ pass
+ break
+ else:
+ if (PcdRealName, TokenSpaceGuid, T) in Package.Pcds:
+ PcdType = T
+ break
+
+ else:
+ Pcd.Pending = False
+ if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
+ for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
+ Pcd_Type = item[0].split('_')[-1]
+ if Pcd_Type == PcdType:
+ PcdCName = item[0]
+ break
+ else:
+ pass
+ else:
+ pass
+
+ if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
+ PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
+ Pcd.Type = PcdType
+ Pcd.TokenValue = PcdInPackage.TokenValue
+
+ #
+ # Check whether the token value exist or not.
+ #
+ if Pcd.TokenValue is None or Pcd.TokenValue == "":
+ EdkLogger.error(
+ 'build',
+ FORMAT_INVALID,
+ "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdRealName, str(Package)),
+ File=self.MetaFile, Line=LineNo,
+ ExtraData=None
+ )
+ #
+ # Check hexadecimal token value length and format.
+ #
+ ReIsValidPcdTokenValue = re.compile(r"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re.DOTALL)
+ if Pcd.TokenValue.startswith("0x") or Pcd.TokenValue.startswith("0X"):
+ if ReIsValidPcdTokenValue.match(Pcd.TokenValue) is None:
+ EdkLogger.error(
+ 'build',
+ FORMAT_INVALID,
+ "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)),
+ File=self.MetaFile, Line=LineNo,
+ ExtraData=None
+ )
+
+ #
+ # Check decimal token value length and format.
+ #
+ else:
+ try:
+ TokenValueInt = int (Pcd.TokenValue, 10)
+ if (TokenValueInt < 0 or TokenValueInt > 4294967295):
+ EdkLogger.error(
+ 'build',
+ FORMAT_INVALID,
+ "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, as a decimal it should between: 0 - 4294967295!" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)),
+ File=self.MetaFile, Line=LineNo,
+ ExtraData=None
+ )
+ except:
+ EdkLogger.error(
+ 'build',
+ FORMAT_INVALID,
+ "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, it should be hexadecimal or decimal!" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)),
+ File=self.MetaFile, Line=LineNo,
+ ExtraData=None
+ )
+
+ Pcd.DatumType = PcdInPackage.DatumType
+ Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
+ Pcd.InfDefaultValue = Pcd.DefaultValue
+ if not Pcd.DefaultValue:
+ Pcd.DefaultValue = PcdInPackage.DefaultValue
+ else:
+ try:
+ Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue, Pcd.DatumType, _GuidDict)(True)
+ except BadExpression as Value:
+ EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid, PcdRealName, Pcd.DefaultValue, Value),
+ File=self.MetaFile, Line=LineNo)
+ break
+ else:
+ EdkLogger.error(
+ 'build',
+ FORMAT_INVALID,
+ "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdRealName, self.MetaFile),
+ File=self.MetaFile, Line=LineNo,
+ ExtraData="\t%s" % '\n\t'.join(str(P) for P in self.Packages)
+ )
+ Pcds[PcdCName, TokenSpaceGuid] = Pcd
+
+ return Pcds
+
+ ## check whether current module is binary module
+ @property
+ def IsBinaryModule(self):
+ if (self.Binaries and not self.Sources) or GlobalData.gIgnoreSource:
+ return True
+ return False
+def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
+ for Key in CopyFromDict:
+ CopyToDict[Key].extend(CopyFromDict[Key])
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaDataTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaDataTable.py
new file mode 100755
index 00000000..22f8c7fe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaDataTable.py
@@ -0,0 +1,306 @@
+## @file
+# This file is used to create/update/query/erase table for files
+#
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+import Common.LongFilePathOs as os
+
+import Common.EdkLogger as EdkLogger
+from CommonDataClass import DataClass
+from CommonDataClass.DataClass import FileClass
+
+## Convert to SQL required string format
+def ConvertToSqlString(StringList):
+ return list(map(lambda s: "'" + s.replace("'", "''") + "'", StringList))
+
+## TableFile
+#
+# This class defined a common table
+#
+# @param object: Inherited from object class
+#
+# @param Cursor: Cursor of the database
+# @param TableName: Name of the table
+#
+class Table(object):
+ _COLUMN_ = ''
+ _ID_STEP_ = 1
+ _ID_MAX_ = 0x80000000
+ _DUMMY_ = 0
+
+ def __init__(self, Db, Name='', IdBase=0, Temporary=False):
+ self.Db = Db
+ self.Table = Name
+ self.IdBase = int(IdBase)
+ self.ID = int(IdBase)
+ self.Temporary = Temporary
+ self.Contents = []
+
+ def __str__(self):
+ return self.Table
+
+ ## Create table
+ #
+ # Create a table
+ #
+ def Create(self, NewTable=True):
+ self.Db.CreateEmptyTable(self.Table)
+ self.ID = self.GetId()
+
+ ## Insert table
+ #
+ # Insert a record into a table
+ #
+ def Insert(self, *Args):
+ self.ID = self.ID + self._ID_STEP_
+ if self.ID >= (self.IdBase + self._ID_MAX_):
+ self.ID = self.IdBase + self._ID_STEP_
+ row = [self.ID]
+ row.extend(Args)
+ self.Contents.append(row)
+
+ return self.ID
+
+
+ ## Get count
+ #
+ # Get a count of all records of the table
+ #
+ # @retval Count: Total count of all records
+ #
+ def GetCount(self):
+ tab = self.Db.GetTable(self.Table)
+ return len(tab)
+
+
+ def GetId(self):
+ tab = self.Db.GetTable(self.Table)
+ Id = max([int(item[0]) for item in tab])
+ if Id is None:
+ Id = self.IdBase
+ return Id
+
+ ## Init the ID of the table
+ #
+ # Init the ID of the table
+ #
+ def InitID(self):
+ self.ID = self.GetId()
+
+ ## Exec
+ #
+ # Exec Sql Command, return result
+ #
+ # @param SqlCommand: The SqlCommand to be executed
+ #
+ # @retval RecordSet: The result after executed
+ #
+ def Exec(self, SqlCommand):
+ EdkLogger.debug(EdkLogger.DEBUG_5, SqlCommand)
+ self.Db.execute(SqlCommand)
+ RecordSet = self.Db.fetchall()
+ return RecordSet
+
+ def SetEndFlag(self):
+ Tab = self.Db.GetTable(self.Table)
+ Tab.append(self._DUMMY_)
+
+
+ def IsIntegral(self):
+ tab = self.Db.GetTable(self.Table)
+ Id = min([int(item[0]) for item in tab])
+ if Id != -1:
+ return False
+ return True
+
+ def GetAll(self):
+ tab = self.Db.GetTable(self.Table)
+ return tab
+
+
+## TableFile
+#
+# This class defined a table used for file
+#
+# @param object: Inherited from object class
+#
+class TableFile(Table):
+ _COLUMN_ = '''
+ ID INTEGER PRIMARY KEY,
+ Name VARCHAR NOT NULL,
+ ExtName VARCHAR,
+ Path VARCHAR,
+ FullPath VARCHAR NOT NULL,
+ Model INTEGER DEFAULT 0,
+ TimeStamp SINGLE NOT NULL,
+ FromItem REAL NOT NULL
+ '''
+ def __init__(self, Cursor):
+ Table.__init__(self, Cursor, 'File')
+
+ ## Insert table
+ #
+ # Insert a record into table File
+ #
+ # @param Name: Name of a File
+ # @param ExtName: ExtName of a File
+ # @param Path: Path of a File
+ # @param FullPath: FullPath of a File
+ # @param Model: Model of a File
+ # @param TimeStamp: TimeStamp of a File
+ #
+ def Insert(self, Name, ExtName, Path, FullPath, Model, TimeStamp, FromItem=0):
+ (Name, ExtName, Path, FullPath) = ConvertToSqlString((Name, ExtName, Path, FullPath))
+ return Table.Insert(
+ self,
+ Name,
+ ExtName,
+ Path,
+ FullPath,
+ Model,
+ TimeStamp,
+ FromItem
+ )
+
+ ## InsertFile
+ #
+ # Insert one file to table
+ #
+ # @param FileFullPath: The full path of the file
+ # @param Model: The model of the file
+ #
+ # @retval FileID: The ID after record is inserted
+ #
+ def InsertFile(self, File, Model, FromItem=''):
+ if FromItem:
+ return self.Insert(
+ File.Name,
+ File.Ext,
+ File.Dir,
+ File.Path,
+ Model,
+ File.TimeStamp,
+ FromItem
+ )
+ return self.Insert(
+ File.Name,
+ File.Ext,
+ File.Dir,
+ File.Path,
+ Model,
+ File.TimeStamp
+ )
+
+ ## Get type of a given file
+ #
+ # @param FileId ID of a file
+ #
+ # @retval file_type Model value of given file in the table
+ #
+ def GetFileType(self, FileId):
+ QueryScript = "select Model from %s where ID = '%s'" % (self.Table, FileId)
+ RecordList = self.Exec(QueryScript)
+ if len(RecordList) == 0:
+ return None
+ return RecordList[0][0]
+
+ ## Get file timestamp of a given file
+ #
+ # @param FileId ID of file
+ #
+ # @retval timestamp TimeStamp value of given file in the table
+ #
+ def GetFileTimeStamp(self, FileId):
+ QueryScript = "select TimeStamp from %s where ID = '%s'" % (self.Table, FileId)
+ RecordList = self.Exec(QueryScript)
+ if len(RecordList) == 0:
+ return None
+ return RecordList[0][0]
+
+ ## Update the timestamp of a given file
+ #
+ # @param FileId ID of file
+ # @param TimeStamp Time stamp of file
+ #
+ def SetFileTimeStamp(self, FileId, TimeStamp):
+ self.Exec("update %s set TimeStamp=%s where ID='%s'" % (self.Table, TimeStamp, FileId))
+
+ ## Get list of file with given type
+ #
+ # @param FileType Type value of file
+ #
+ # @retval file_list List of files with the given type
+ #
+ def GetFileList(self, FileType):
+ RecordList = self.Exec("select FullPath from %s where Model=%s" % (self.Table, FileType))
+ if len(RecordList) == 0:
+ return []
+ return [R[0] for R in RecordList]
+
+## TableDataModel
+#
+# This class defined a table used for data model
+#
+# @param object: Inherited from object class
+#
+#
+class TableDataModel(Table):
+ _COLUMN_ = """
+ ID INTEGER PRIMARY KEY,
+ CrossIndex INTEGER NOT NULL,
+ Name VARCHAR NOT NULL,
+ Description VARCHAR
+ """
+ def __init__(self, Cursor):
+ Table.__init__(self, Cursor, 'DataModel')
+
+ ## Insert table
+ #
+ # Insert a record into table DataModel
+ #
+ # @param ID: ID of a ModelType
+ # @param CrossIndex: CrossIndex of a ModelType
+ # @param Name: Name of a ModelType
+ # @param Description: Description of a ModelType
+ #
+ def Insert(self, CrossIndex, Name, Description):
+ (Name, Description) = ConvertToSqlString((Name, Description))
+ return Table.Insert(self, CrossIndex, Name, Description)
+
+ ## Init table
+ #
+ # Create all default records of table DataModel
+ #
+ def InitTable(self):
+ EdkLogger.verbose("\nInitialize table DataModel started ...")
+ Count = self.GetCount()
+ if Count is not None and Count != 0:
+ return
+ for Item in DataClass.MODEL_LIST:
+ CrossIndex = Item[1]
+ Name = Item[0]
+ Description = Item[0]
+ self.Insert(CrossIndex, Name, Description)
+ EdkLogger.verbose("Initialize table DataModel ... DONE!")
+
+ ## Get CrossIndex
+ #
+ # Get a model's cross index from its name
+ #
+ # @param ModelName: Name of the model
+ # @retval CrossIndex: CrossIndex of the model
+ #
+ def GetCrossIndex(self, ModelName):
+ CrossIndex = -1
+ SqlCommand = """select CrossIndex from DataModel where name = '""" + ModelName + """'"""
+ self.Db.execute(SqlCommand)
+ for Item in self.Db:
+ CrossIndex = Item[0]
+
+ return CrossIndex
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py
new file mode 100755
index 00000000..333d56f3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py
@@ -0,0 +1,45 @@
+## @file
+# This file is used to check format of comments
+#
+# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+from CommonDataClass.DataClass import (
+ MODEL_PCD_PATCHABLE_IN_MODULE,
+ MODEL_PCD_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC,
+ MODEL_EFI_GUID,
+ MODEL_EFI_PPI,
+ MODEL_EFI_PROTOCOL
+)
+from Common.BuildToolError import FORMAT_INVALID
+import Common.EdkLogger as EdkLogger
+
+UsageList = ("PRODUCES", "PRODUCED", "ALWAYS_PRODUCES", "ALWAYS_PRODUCED", "SOMETIMES_PRODUCES",
+ "SOMETIMES_PRODUCED", "CONSUMES", "CONSUMED", "ALWAYS_CONSUMES", "ALWAYS_CONSUMED",
+ "SOMETIMES_CONSUMES", "SOMETIMES_CONSUMED", "SOMETIME_CONSUMES")
+ErrorMsgMap = {
+ MODEL_EFI_GUID : "The usage for this GUID is not listed in this INF: %s[%d]:%s",
+ MODEL_EFI_PPI : "The usage for this PPI is not listed in this INF: %s[%d]:%s.",
+ MODEL_EFI_PROTOCOL : "The usage for this Protocol is not listed in this INF: %s[%d]:%s.",
+ MODEL_PCD_DYNAMIC : "The usage for this PCD is not listed in this INF: %s[%d]:%s."
+}
+
+def CheckInfComment(SectionType, Comments, InfFile, LineNo, ValueList):
+ if SectionType in [MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_EX, MODEL_PCD_DYNAMIC]:
+ CheckUsage(Comments, UsageList, InfFile, LineNo, ValueList[0]+'.'+ValueList[1], ErrorMsgMap[MODEL_PCD_DYNAMIC])
+ elif SectionType in [MODEL_EFI_GUID, MODEL_EFI_PPI]:
+ CheckUsage(Comments, UsageList, InfFile, LineNo, ValueList[0], ErrorMsgMap[SectionType])
+ elif SectionType == MODEL_EFI_PROTOCOL:
+ CheckUsage(Comments, UsageList + ("TO_START", "BY_START"), InfFile, LineNo, ValueList[0], ErrorMsgMap[SectionType])
+
+def CheckUsage(Comments, Usages, InfFile, LineNo, Value, ErrorMsg):
+ for Comment in Comments:
+ for Word in Comment[0].replace('#', ' ').split():
+ if Word in Usages:
+ return
+ EdkLogger.error(
+ "Parser", FORMAT_INVALID,
+ ErrorMsg % (InfFile, LineNo, Value)
+ )
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileParser.py
new file mode 100755
index 00000000..4cc253e1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileParser.py
@@ -0,0 +1,2193 @@
+## @file
+# This file is used to parse meta files
+#
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import print_function
+from __future__ import absolute_import
+import Common.LongFilePathOs as os
+import re
+import time
+import copy
+from hashlib import md5
+
+import Common.EdkLogger as EdkLogger
+import Common.GlobalData as GlobalData
+
+from CommonDataClass.DataClass import *
+from Common.DataType import *
+from Common.StringUtils import *
+from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue, StructPattern
+from Common.Expression import *
+from CommonDataClass.Exceptions import *
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from collections import defaultdict
+from .MetaFileTable import MetaFileStorage
+from .MetaFileCommentParser import CheckInfComment
+from Common.DataType import TAB_COMMENT_EDK_START, TAB_COMMENT_EDK_END
+
+## RegEx for finding file versions
+hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')
+decVersionPattern = re.compile(r'\d+\.\d+')
+CODEPattern = re.compile(r"{CODE\([a-fA-F0-9Xx\{\},\s]*\)}")
+
+## A decorator used to parse macro definition
+def ParseMacro(Parser):
+ def MacroParser(self):
+ Match = GlobalData.gMacroDefPattern.match(self._CurrentLine)
+ if not Match:
+ # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
+ Parser(self)
+ return
+
+ TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
+ # Syntax check
+ if not TokenList[0]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ if len(TokenList) < 2:
+ TokenList.append('')
+
+ Type = Match.group(1)
+ Name, Value = TokenList
+ # Global macros can be only defined via environment variable
+ if Name in GlobalData.gGlobalDefines:
+ EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ # Only upper case letters, digit and '_' are allowed
+ if not GlobalData.gMacroNamePattern.match(Name):
+ EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
+ Value = ReplaceMacro(Value, self._Macros)
+ if Type in self.DataType:
+ self._ItemType = self.DataType[Type]
+ else:
+ self._ItemType = MODEL_META_DATA_DEFINE
+ # DEFINE defined macros
+ if Type == TAB_DSC_DEFINES_DEFINE:
+ #
+ # First judge whether this DEFINE is in conditional directive statements or not.
+ #
+ if isinstance(self, DscParser) and self._InDirective > -1:
+ pass
+ else:
+ if isinstance(self, DecParser):
+ if MODEL_META_DATA_HEADER in self._SectionType:
+ self._FileLocalMacros[Name] = Value
+ else:
+ self._ConstructSectionMacroDict(Name, Value)
+ elif self._SectionType == MODEL_META_DATA_HEADER:
+ self._FileLocalMacros[Name] = Value
+ else:
+ self._ConstructSectionMacroDict(Name, Value)
+
+ # EDK_GLOBAL defined macros
+ elif not isinstance(self, DscParser):
+ EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ elif self._SectionType != MODEL_META_DATA_HEADER:
+ EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
+ EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
+ self._ValueList = [Type, Name, Value]
+
+ return MacroParser
+
+## Base class of parser
+#
+# This class is used for derivation purpose. The specific parser for one kind
+# type file must derive this class and implement some public interfaces.
+#
+# @param FilePath The path of platform description file
+# @param FileType The raw data of DSC file
+# @param Table Database used to retrieve module/package information
+# @param Macros Macros used for replacement in file
+# @param Owner Owner ID (for sub-section parsing)
+# @param From ID from which the data comes (for !INCLUDE directive)
+#
+class MetaFileParser(object):
+ # data type (file content) for specific file type
+ DataType = {}
+
+ # Parser objects used to implement singleton
+ MetaFiles = {}
+
+ ## Factory method
+ #
+ # One file, one parser object. This factory method makes sure that there's
+ # only one object constructed for one meta file.
+ #
+ # @param Class class object of real AutoGen class
+ # (InfParser, DecParser or DscParser)
+ # @param FilePath The path of meta file
+ # @param *args The specific class related parameters
+ # @param **kwargs The specific class related dict parameters
+ #
+ def __new__(Class, FilePath, *args, **kwargs):
+ if FilePath in Class.MetaFiles:
+ return Class.MetaFiles[FilePath]
+ else:
+ ParserObject = super(MetaFileParser, Class).__new__(Class)
+ Class.MetaFiles[FilePath] = ParserObject
+ return ParserObject
+
+ ## Constructor of MetaFileParser
+ #
+ # Initialize object of MetaFileParser
+ #
+ # @param FilePath The path of platform description file
+ # @param FileType The raw data of DSC file
+ # @param Arch Default Arch value for filtering sections
+ # @param Table Database used to retrieve module/package information
+ # @param Owner Owner ID (for sub-section parsing)
+ # @param From ID from which the data comes (for !INCLUDE directive)
+ #
+ def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
+ self._Table = Table
+ self._RawTable = Table
+ self._Arch = Arch
+ self._FileType = FileType
+ self.MetaFile = FilePath
+ self._FileDir = self.MetaFile.Dir
+ self._Defines = {}
+ self._Packages = []
+ self._FileLocalMacros = {}
+ self._SectionsMacroDict = defaultdict(dict)
+
+ # for recursive parsing
+ self._Owner = [Owner]
+ self._From = From
+
+ # parsr status for parsing
+ self._ValueList = ['', '', '', '', '']
+ self._Scope = []
+ self._LineIndex = 0
+ self._CurrentLine = ''
+ self._SectionType = MODEL_UNKNOWN
+ self._SectionName = ''
+ self._InSubsection = False
+ self._SubsectionType = MODEL_UNKNOWN
+ self._SubsectionName = ''
+ self._ItemType = MODEL_UNKNOWN
+ self._LastItem = -1
+ self._Enabled = 0
+ self._Finished = False
+ self._PostProcessed = False
+ # Different version of meta-file has different way to parse.
+ self._Version = 0
+ self._GuidDict = {} # for Parser PCD value {GUID(gTokeSpaceGuidName)}
+
+ self._PcdCodeValue = ""
+ self._PcdDataTypeCODE = False
+ self._CurrentPcdName = ""
+
+ ## Store the parsed data in table
+ def _Store(self, *Args):
+ return self._Table.Insert(*Args)
+
+ ## Virtual method for starting parse
+ def Start(self):
+ raise NotImplementedError
+
+ ## Notify a post-process is needed
+ def DoPostProcess(self):
+ self._PostProcessed = False
+
+ ## Set parsing complete flag in both class and table
+ def _Done(self):
+ self._Finished = True
+ self._Table.SetEndFlag()
+
+ def _PostProcess(self):
+ self._PostProcessed = True
+
+ ## Get the parse complete flag
+ @property
+ def Finished(self):
+ return self._Finished
+
+ ## Set the complete flag
+ @Finished.setter
+ def Finished(self, Value):
+ self._Finished = Value
+
+ ## Remove records that do not match given Filter Arch
+ def _FilterRecordList(self, RecordList, FilterArch):
+ NewRecordList = []
+ for Record in RecordList:
+ Arch = Record[3]
+ if Arch == TAB_ARCH_COMMON or Arch == FilterArch:
+ NewRecordList.append(Record)
+ return NewRecordList
+
+ ## Use [] style to query data in table, just for readability
+ #
+ # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
+ #
+ def __getitem__(self, DataInfo):
+ if not isinstance(DataInfo, type(())):
+ DataInfo = (DataInfo,)
+
+ # Parse the file first, if necessary
+ self.StartParse()
+
+ # No specific ARCH or Platform given, use raw data
+ if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):
+ return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)
+
+ # Do post-process if necessary
+ if not self._PostProcessed:
+ self._PostProcess()
+
+ return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])
+
+ def StartParse(self):
+ if not self._Finished:
+ if self._RawTable.IsIntegrity():
+ self._Finished = True
+ else:
+ self._Table = self._RawTable
+ self._PostProcessed = False
+ self.Start()
+ ## Data parser for the common format in different type of file
+ #
+ # The common format in the meatfile is like
+ #
+ # xxx1 | xxx2 | xxx3
+ #
+ @ParseMacro
+ def _CommonParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
+ self._ValueList[0:len(TokenList)] = TokenList
+
+ ## Data parser for the format in which there's path
+ #
+ # Only path can have macro used. So we need to replace them before use.
+ #
+ @ParseMacro
+ def _PathParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
+ self._ValueList[0:len(TokenList)] = TokenList
+ # Don't do macro replacement for dsc file at this point
+ if not isinstance(self, DscParser):
+ Macros = self._Macros
+ self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
+
+ ## Skip unsupported data
+ def _Skip(self):
+ EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
+ Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
+ self._ValueList[0:1] = [self._CurrentLine]
+
+ ## Skip unsupported data for UserExtension Section
+ def _SkipUserExtension(self):
+ self._ValueList[0:1] = [self._CurrentLine]
+
+ ## Section header parser
+ #
+ # The section header is always in following format:
+ #
+ # [section_name.arch<.platform|module_type>]
+ #
+ def _SectionHeaderParser(self):
+ self._Scope = []
+ self._SectionName = ''
+ ArchList = set()
+ for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
+ if Item == '':
+ continue
+ ItemList = GetSplitValueList(Item, TAB_SPLIT, 3)
+ # different section should not mix in one section
+ if self._SectionName != '' and self._SectionName != ItemList[0].upper():
+ EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
+ File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
+ self._SectionName = ItemList[0].upper()
+ if self._SectionName in self.DataType:
+ self._SectionType = self.DataType[self._SectionName]
+ # Check if the section name is valid
+ if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH_SET and len(ItemList) > 3:
+ EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
+ self.MetaFile, self._LineIndex + 1, self._CurrentLine)
+ elif self._Version >= 0x00010005:
+ EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
+ self.MetaFile, self._LineIndex + 1, self._CurrentLine)
+ else:
+ self._SectionType = MODEL_UNKNOWN
+
+ # S1 is always Arch
+ if len(ItemList) > 1:
+ S1 = ItemList[1].upper()
+ else:
+ S1 = TAB_ARCH_COMMON
+ S1 = ReplaceMacro(S1, self._Macros)
+ ArchList.add(S1)
+
+ # S2 may be Platform or ModuleType
+ if len(ItemList) > 2:
+ if self._SectionName.upper() in SECTIONS_HAVE_ITEM_PCD_SET:
+ S2 = ItemList[2]
+ else:
+ S2 = ItemList[2].upper()
+ else:
+ S2 = TAB_COMMON
+ if len(ItemList) > 3:
+ S3 = ItemList[3]
+ else:
+ S3 = TAB_COMMON
+ self._Scope.append([S1, S2, S3])
+
+ # 'COMMON' must not be used with specific ARCHs at the same section
+ if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
+ EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
+ File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
+ # If the section information is needed later, it should be stored in database
+ self._ValueList[0] = self._SectionName
+
+ ## [packages] section parser
+ @ParseMacro
+ def _PackageParser(self):
+ self._CurrentLine = CleanString(self._CurrentLine)
+ self._Packages.append(self._CurrentLine)
+ self._ValueList[0] = self._CurrentLine
+
+ ## [defines] section parser
+ @ParseMacro
+ def _DefineParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
+ self._ValueList[1:len(TokenList)] = TokenList
+ if not self._ValueList[1]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ if not self._ValueList[2]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
+ self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
+ Name, Value = self._ValueList[1], self._ValueList[2]
+ MacroUsed = GlobalData.gMacroRefPattern.findall(Value)
+ if len(MacroUsed) != 0:
+ for Macro in MacroUsed:
+ if Macro in GlobalData.gGlobalDefines:
+ EdkLogger.error("Parser", FORMAT_INVALID, "Global macro %s is not permitted." % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ else:
+ EdkLogger.error("Parser", FORMAT_INVALID, "%s not defined" % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ # Sometimes, we need to make differences between EDK and EDK2 modules
+ if Name == 'INF_VERSION':
+ if hexVersionPattern.match(Value):
+ self._Version = int(Value, 0)
+ elif decVersionPattern.match(Value):
+ ValueList = Value.split('.')
+ Major = int(ValueList[0], 0)
+ Minor = int(ValueList[1], 0)
+ if Major > 0xffff or Minor > 0xffff:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ self._Version = int('0x{0:04x}{1:04x}'.format(Major, Minor), 0)
+ else:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
+ if isinstance(self, InfParser) and self._Version < 0x00010005:
+ # EDK module allows using defines as macros
+ self._FileLocalMacros[Name] = Value
+ self._Defines[Name] = Value
+
+ ## [BuildOptions] section parser
+ @ParseMacro
+ def _BuildOptionParser(self):
+ self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
+ TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
+ if len(TokenList2) == 2:
+ self._ValueList[0] = TokenList2[0] # toolchain family
+ self._ValueList[1] = TokenList2[1] # keys
+ else:
+ self._ValueList[1] = TokenList[0]
+ if len(TokenList) == 2 and not isinstance(self, DscParser): # value
+ self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
+
+ if self._ValueList[1].count('_') != 4:
+ EdkLogger.error(
+ 'Parser',
+ FORMAT_INVALID,
+ "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
+ ExtraData=self._CurrentLine,
+ File=self.MetaFile,
+ Line=self._LineIndex + 1
+ )
+ def GetValidExpression(self, TokenSpaceGuid, PcdCName):
+ return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)
+
+ @property
+ def _Macros(self):
+ Macros = {}
+ Macros.update(self._FileLocalMacros)
+ Macros.update(self._GetApplicableSectionMacro())
+ return Macros
+
+ ## Construct section Macro dict
+ def _ConstructSectionMacroDict(self, Name, Value):
+ ScopeKey = [(Scope[0], Scope[1], Scope[2]) for Scope in self._Scope]
+ ScopeKey = tuple(ScopeKey)
+ #
+ # DecParser SectionType is a list, will contain more than one item only in Pcd Section
+ # As Pcd section macro usage is not allowed, so here it is safe
+ #
+ if isinstance(self, DecParser):
+ SectionDictKey = self._SectionType[0], ScopeKey
+ else:
+ SectionDictKey = self._SectionType, ScopeKey
+
+ self._SectionsMacroDict[SectionDictKey][Name] = Value
+
+ ## Get section Macros that are applicable to current line, which may come from other sections
+ ## that share the same name while scope is wider
+ def _GetApplicableSectionMacro(self):
+ Macros = {}
+
+ ComComMacroDict = {}
+ ComSpeMacroDict = {}
+ SpeSpeMacroDict = {}
+
+ ActiveSectionType = self._SectionType
+ if isinstance(self, DecParser):
+ ActiveSectionType = self._SectionType[0]
+
+ for (SectionType, Scope) in self._SectionsMacroDict:
+ if SectionType != ActiveSectionType:
+ continue
+
+ for ActiveScope in self._Scope:
+ Scope0, Scope1, Scope2= ActiveScope[0], ActiveScope[1], ActiveScope[2]
+ if(Scope0, Scope1, Scope2) not in Scope:
+ break
+ else:
+ SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
+
+ for ActiveScope in self._Scope:
+ Scope0, Scope1, Scope2 = ActiveScope[0], ActiveScope[1], ActiveScope[2]
+ if(Scope0, Scope1, Scope2) not in Scope and (Scope0, TAB_COMMON, TAB_COMMON) not in Scope and (TAB_COMMON, Scope1, TAB_COMMON) not in Scope:
+ break
+ else:
+ ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
+
+ if (TAB_COMMON, TAB_COMMON, TAB_COMMON) in Scope:
+ ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
+
+ Macros.update(ComComMacroDict)
+ Macros.update(ComSpeMacroDict)
+ Macros.update(SpeSpeMacroDict)
+
+ return Macros
+
+ def ProcessMultipleLineCODEValue(self,Content):
+ CODEBegin = False
+ CODELine = ""
+ continuelinecount = 0
+ newContent = []
+ for Index in range(0, len(Content)):
+ Line = Content[Index]
+ if CODEBegin:
+ CODELine = CODELine + Line
+ continuelinecount +=1
+ if ")}" in Line:
+ newContent.append(CODELine)
+ for _ in range(continuelinecount):
+ newContent.append("")
+ CODEBegin = False
+ CODELine = ""
+ continuelinecount = 0
+ else:
+ if not Line:
+ newContent.append(Line)
+ continue
+ if "{CODE(" not in Line:
+ newContent.append(Line)
+ continue
+ elif CODEPattern.findall(Line):
+ newContent.append(Line)
+ continue
+ else:
+ CODEBegin = True
+ CODELine = Line
+
+ return newContent
+
+ _SectionParser = {}
+
+## INF file parser class
+#
+# @param FilePath The path of platform description file
+# @param FileType The raw data of DSC file
+# @param Table Database used to retrieve module/package information
+# @param Macros Macros used for replacement in file
+#
+class InfParser(MetaFileParser):
+ # INF file supported data types (one type per section)
+ DataType = {
+ TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
+ TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
+ TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
+ TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
+ TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
+ TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
+ TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
+ TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
+ TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
+ TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
+ TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
+ TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
+ TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
+ TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
+ TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
+ TAB_GUIDS.upper() : MODEL_EFI_GUID,
+ TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
+ TAB_PPIS.upper() : MODEL_EFI_PPI,
+ TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
+ TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
+ TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
+ }
+
+ ## Constructor of InfParser
+ #
+ # Initialize object of InfParser
+ #
+ # @param FilePath The path of module description file
+ # @param FileType The raw data of DSC file
+ # @param Arch Default Arch value for filtering sections
+ # @param Table Database used to retrieve module/package information
+ #
+ def __init__(self, FilePath, FileType, Arch, Table):
+ # prevent re-initialization
+ if hasattr(self, "_Table"):
+ return
+ MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)
+ self.PcdsDict = {}
+
+ ## Parser starter
+ def Start(self):
+ NmakeLine = ''
+ Content = ''
+ try:
+ with open(str(self.MetaFile), 'r') as File:
+ Content = File.readlines()
+ except:
+ EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
+
+ # parse the file line by line
+ IsFindBlockComment = False
+ GetHeaderComment = False
+ TailComments = []
+ SectionComments = []
+ Comments = []
+
+ for Index in range(0, len(Content)):
+ # skip empty, commented, block commented lines
+ Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)
+ NextLine = ''
+ if Index + 1 < len(Content):
+ NextLine, NextComment = CleanString2(Content[Index + 1])
+ if Line == '':
+ if Comment:
+ Comments.append((Comment, Index + 1))
+ elif GetHeaderComment:
+ SectionComments.extend(Comments)
+ Comments = []
+ continue
+ if Line.find(TAB_COMMENT_EDK_START) > -1:
+ IsFindBlockComment = True
+ continue
+ if Line.find(TAB_COMMENT_EDK_END) > -1:
+ IsFindBlockComment = False
+ continue
+ if IsFindBlockComment:
+ continue
+
+ self._LineIndex = Index
+ self._CurrentLine = Line
+
+ # section header
+ if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
+ if not GetHeaderComment:
+ for Cmt, LNo in Comments:
+ self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,
+ TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)
+ GetHeaderComment = True
+ else:
+ TailComments.extend(SectionComments + Comments)
+ Comments = []
+ self._SectionHeaderParser()
+ # Check invalid sections
+ if self._Version < 0x00010005:
+ if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
+ MODEL_EFI_LIBRARY_CLASS,
+ MODEL_META_DATA_PACKAGE,
+ MODEL_PCD_FIXED_AT_BUILD,
+ MODEL_PCD_PATCHABLE_IN_MODULE,
+ MODEL_PCD_FEATURE_FLAG,
+ MODEL_PCD_DYNAMIC_EX,
+ MODEL_PCD_DYNAMIC,
+ MODEL_EFI_GUID,
+ MODEL_EFI_PROTOCOL,
+ MODEL_EFI_PPI,
+ MODEL_META_DATA_USER_EXTENSION]:
+ EdkLogger.error('Parser', FORMAT_INVALID,
+ "Section [%s] is not allowed in inf file without version" % (self._SectionName),
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ elif self._SectionType in [MODEL_EFI_INCLUDE,
+ MODEL_EFI_LIBRARY_INSTANCE,
+ MODEL_META_DATA_NMAKE]:
+ EdkLogger.error('Parser', FORMAT_INVALID,
+ "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ continue
+ # merge two lines specified by '\' in section NMAKE
+ elif self._SectionType == MODEL_META_DATA_NMAKE:
+ if Line[-1] == '\\':
+ if NextLine == '':
+ self._CurrentLine = NmakeLine + Line[0:-1]
+ NmakeLine = ''
+ else:
+ if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
+ self._CurrentLine = NmakeLine + Line[0:-1]
+ NmakeLine = ''
+ else:
+ NmakeLine = NmakeLine + ' ' + Line[0:-1]
+ continue
+ else:
+ self._CurrentLine = NmakeLine + Line
+ NmakeLine = ''
+
+ # section content
+ self._ValueList = ['', '', '']
+ # parse current line, result will be put in self._ValueList
+ self._SectionParser[self._SectionType](self)
+ if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
+ self._ItemType = -1
+ Comments = []
+ continue
+ if Comment:
+ Comments.append((Comment, Index + 1))
+ if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:
+ CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)
+ #
+ # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
+ # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
+ #
+ for Arch, Platform, _ in self._Scope:
+ LastItem = self._Store(self._SectionType,
+ self._ValueList[0],
+ self._ValueList[1],
+ self._ValueList[2],
+ Arch,
+ Platform,
+ self._Owner[-1],
+ self._LineIndex + 1,
+ - 1,
+ self._LineIndex + 1,
+ - 1,
+ 0
+ )
+ for Comment, LineNo in Comments:
+ self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,
+ LastItem, LineNo, -1, LineNo, -1, 0)
+ Comments = []
+ SectionComments = []
+ TailComments.extend(SectionComments + Comments)
+ if IsFindBlockComment:
+ EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
+ File=self.MetaFile)
+
+ # If there are tail comments in INF file, save to database whatever the comments are
+ for Comment in TailComments:
+ self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', TAB_COMMON,
+ TAB_COMMON, self._Owner[-1], -1, -1, -1, -1, 0)
+ self._Done()
+
+ ## Data parser for the format in which there's path
+ #
+ # Only path can have macro used. So we need to replace them before use.
+ #
+ def _IncludeParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
+ self._ValueList[0:len(TokenList)] = TokenList
+ Macros = self._Macros
+ if Macros:
+ for Index in range(0, len(self._ValueList)):
+ Value = self._ValueList[Index]
+ if not Value:
+ continue
+ self._ValueList[Index] = ReplaceMacro(Value, Macros)
+
+ ## Parse [Sources] section
+ #
+ # Only path can have macro used. So we need to replace them before use.
+ #
+ @ParseMacro
+ def _SourceFileParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
+ self._ValueList[0:len(TokenList)] = TokenList
+ Macros = self._Macros
+ # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
+ if 'COMPONENT_TYPE' in Macros:
+ if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
+ self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
+ if self._Defines['BASE_NAME'] == 'Microcode':
+ pass
+ self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
+
+ ## Parse [Binaries] section
+ #
+ # Only path can have macro used. So we need to replace them before use.
+ #
+ @ParseMacro
+ def _BinaryFileParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
+ if len(TokenList) < 2:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
+ ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if not TokenList[0]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
+ ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if not TokenList[1]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
+ ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ self._ValueList[0:len(TokenList)] = TokenList
+ self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
+
+ ## [nmake] section parser (Edk.x style only)
+ def _NmakeParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
+ self._ValueList[0:len(TokenList)] = TokenList
+ # remove macros
+ self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
+ # remove self-reference in macro setting
+ #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
+
+ ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
+ @ParseMacro
+ def _PcdParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
+ ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
+ if len(ValueList) != 2:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
+ ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ self._ValueList[0:1] = ValueList
+ if len(TokenList) > 1:
+ self._ValueList[2] = TokenList[1]
+ if self._ValueList[0] == '' or self._ValueList[1] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
+ ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+ # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
+ if self._ValueList[2] != '':
+ InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
+ if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
+ self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1)
+ elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
+ self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1)
+ elif isinstance(InfPcdValueList[0], str) and InfPcdValueList[0].find('$(') >= 0:
+ Value = ReplaceExprMacro(InfPcdValueList[0],self._Macros)
+ if Value != '0':
+ self._ValueList[2] = Value
+ if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
+ self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
+ elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
+ EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
+ ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+ ## [depex] section parser
+ @ParseMacro
+ def _DepexParser(self):
+ self._ValueList[0:1] = [self._CurrentLine]
+
+ _SectionParser = {
+ MODEL_UNKNOWN : MetaFileParser._Skip,
+ MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
+ MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
+ MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
+ MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
+ MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
+ MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
+ MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
+ MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
+ MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
+ MODEL_PCD_FEATURE_FLAG : _PcdParser,
+ MODEL_PCD_DYNAMIC_EX : _PcdParser,
+ MODEL_PCD_DYNAMIC : _PcdParser,
+ MODEL_EFI_SOURCE_FILE : _SourceFileParser,
+ MODEL_EFI_GUID : MetaFileParser._CommonParser,
+ MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
+ MODEL_EFI_PPI : MetaFileParser._CommonParser,
+ MODEL_EFI_DEPEX : _DepexParser,
+ MODEL_EFI_BINARY_FILE : _BinaryFileParser,
+ MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
+ }
+
+## DSC file parser class
+#
+# @param FilePath The path of platform description file
+# @param FileType The raw data of DSC file
+# @param Table Database used to retrieve module/package information
+# @param Macros Macros used for replacement in file
+# @param Owner Owner ID (for sub-section parsing)
+# @param From ID from which the data comes (for !INCLUDE directive)
+#
+class DscParser(MetaFileParser):
+ # DSC file supported data types (one type per section)
+ DataType = {
+ TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
+ TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,
+ TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
+ TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
+ TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
+ TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
+ TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
+ TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
+ TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
+ TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
+ TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
+ TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
+ TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
+ TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
+ TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
+ TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
+ TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
+ TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
+ TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,
+ TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
+ TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
+ TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
+ TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
+ TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
+ TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
+ TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
+ TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
+ TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,
+ }
+
+ # Valid names in define section
+ DefineKeywords = [
+ "DSC_SPECIFICATION",
+ "PLATFORM_NAME",
+ "PLATFORM_GUID",
+ "PLATFORM_VERSION",
+ "SKUID_IDENTIFIER",
+ "PCD_INFO_GENERATION",
+ "PCD_VAR_CHECK_GENERATION",
+ "SUPPORTED_ARCHITECTURES",
+ "BUILD_TARGETS",
+ "OUTPUT_DIRECTORY",
+ "FLASH_DEFINITION",
+ "BUILD_NUMBER",
+ "RFC_LANGUAGES",
+ "ISO_LANGUAGES",
+ "TIME_STAMP_FILE",
+ "VPD_TOOL_GUID",
+ "FIX_LOAD_TOP_MEMORY_ADDRESS",
+ "PREBUILD",
+ "POSTBUILD"
+ ]
+
+ SubSectionDefineKeywords = [
+ "FILE_GUID"
+ ]
+
+ SymbolPattern = ValueExpression.SymbolPattern
+
+ IncludedFiles = set()
+
+ ## Constructor of DscParser
+ #
+ # Initialize object of DscParser
+ #
+ # @param FilePath The path of platform description file
+ # @param FileType The raw data of DSC file
+ # @param Arch Default Arch value for filtering sections
+ # @param Table Database used to retrieve module/package information
+ # @param Owner Owner ID (for sub-section parsing)
+ # @param From ID from which the data comes (for !INCLUDE directive)
+ #
+ def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
+ # prevent re-initialization
+ if hasattr(self, "_Table") and self._Table is Table:
+ return
+ MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)
+ self._Version = 0x00010005 # Only EDK2 dsc file is supported
+ # to store conditional directive evaluation result
+ self._DirectiveStack = []
+ self._DirectiveEvalStack = []
+ self._Enabled = 1
+
+ #
+ # Specify whether current line is in uncertain condition
+ #
+ self._InDirective = -1
+
+ # Final valid replacable symbols
+ self._Symbols = {}
+ #
+ # Map the ID between the original table and new table to track
+ # the owner item
+ #
+ self._IdMapping = {-1:-1}
+
+ self._Content = None
+
+ ## Parser starter
+ def Start(self):
+ Content = ''
+ try:
+ with open(str(self.MetaFile), 'r') as File:
+ Content = File.readlines()
+ except:
+ EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
+
+ OwnerId = {}
+
+ Content = self.ProcessMultipleLineCODEValue(Content)
+
+ for Index in range(0, len(Content)):
+ Line = CleanString(Content[Index])
+ # skip empty line
+ if Line == '':
+ continue
+
+ self._CurrentLine = Line
+ self._LineIndex = Index
+ if self._InSubsection and self._Owner[-1] == -1:
+ self._Owner.append(self._LastItem)
+
+ # section header
+ if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
+ self._SectionType = MODEL_META_DATA_SECTION_HEADER
+ # subsection ending
+ elif Line[0] == '}' and self._InSubsection:
+ self._InSubsection = False
+ self._SubsectionType = MODEL_UNKNOWN
+ self._SubsectionName = ''
+ self._Owner[-1] = -1
+ OwnerId.clear()
+ continue
+ # subsection header
+ elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
+ self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
+ # directive line
+ elif Line[0] == '!':
+ TokenList = GetSplitValueList(Line, ' ', 1)
+ if TokenList[0] == TAB_INCLUDE:
+ for Arch, ModuleType, DefaultStore in self._Scope:
+ if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
+ self._Owner[-1] = OwnerId[Arch]
+ self._DirectiveParser()
+ else:
+ self._DirectiveParser()
+ continue
+ if Line[0] == TAB_OPTION_START and not self._InSubsection:
+ EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)
+
+ if self._InSubsection:
+ SectionType = self._SubsectionType
+ else:
+ SectionType = self._SectionType
+ self._ItemType = SectionType
+
+ self._ValueList = ['', '', '']
+ # "SET pcd = pcd_expression" syntax is not supported in Dsc file.
+ if self._CurrentLine.upper().strip().startswith("SET "):
+ EdkLogger.error('Parser', FORMAT_INVALID, '''"SET pcd = pcd_expression" syntax is not support in Dsc file''',
+ ExtraData=self._CurrentLine,
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ self._SectionParser[SectionType](self)
+ if self._ValueList is None:
+ continue
+ #
+ # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
+ # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
+ #
+ for Arch, ModuleType, DefaultStore in self._Scope:
+ Owner = self._Owner[-1]
+ if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
+ Owner = OwnerId[Arch]
+ self._LastItem = self._Store(
+ self._ItemType,
+ self._ValueList[0],
+ self._ValueList[1],
+ self._ValueList[2],
+ Arch,
+ ModuleType,
+ DefaultStore,
+ Owner,
+ self._From,
+ self._LineIndex + 1,
+ - 1,
+ self._LineIndex + 1,
+ - 1,
+ self._Enabled
+ )
+ if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
+ OwnerId[Arch] = self._LastItem
+
+ if self._DirectiveStack:
+ Type, Line, Text = self._DirectiveStack[-1]
+ EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
+ ExtraData=Text, File=self.MetaFile, Line=Line)
+ self._Done()
+
+ ## <subsection_header> parser
+ def _SubsectionHeaderParser(self):
+ self._SubsectionName = self._CurrentLine[1:-1].upper()
+ if self._SubsectionName in self.DataType:
+ self._SubsectionType = self.DataType[self._SubsectionName]
+ else:
+ self._SubsectionType = MODEL_UNKNOWN
+ EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
+ Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
+ self._ValueList[0] = self._SubsectionName
+
+ ## Directive statement parser
+ def _DirectiveParser(self):
+ self._ValueList = ['', '', '']
+ TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
+ self._ValueList[0:len(TokenList)] = TokenList
+
+ # Syntax check
+ DirectiveName = self._ValueList[0].upper()
+ if DirectiveName not in self.DataType:
+ EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+ if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
+ self._InDirective += 1
+
+ if DirectiveName in ['!ENDIF']:
+ self._InDirective -= 1
+
+ if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
+ EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
+ File=self.MetaFile, Line=self._LineIndex + 1,
+ ExtraData=self._CurrentLine)
+
+ ItemType = self.DataType[DirectiveName]
+ Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]
+ if ItemType == MODEL_META_DATA_INCLUDE:
+ Scope = self._Scope
+ elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:
+ Scope = self._Scope
+ if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
+ # Remove all directives between !if and !endif, including themselves
+ while self._DirectiveStack:
+ # Remove any !else or !elseif
+ DirectiveInfo = self._DirectiveStack.pop()
+ if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
+ break
+ else:
+ EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
+ File=self.MetaFile, Line=self._LineIndex + 1,
+ ExtraData=self._CurrentLine)
+ elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:
+ # Break if there's a !else is followed by a !elseif
+ if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
+ self._DirectiveStack and \
+ self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
+ EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
+ File=self.MetaFile, Line=self._LineIndex + 1,
+ ExtraData=self._CurrentLine)
+ self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
+
+ #
+ # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
+ # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
+ #
+ for Arch, ModuleType, DefaultStore in Scope:
+ self._LastItem = self._Store(
+ ItemType,
+ self._ValueList[0],
+ self._ValueList[1],
+ self._ValueList[2],
+ Arch,
+ ModuleType,
+ DefaultStore,
+ self._Owner[-1],
+ self._From,
+ self._LineIndex + 1,
+ - 1,
+ self._LineIndex + 1,
+ - 1,
+ 0
+ )
+
+ ## [defines] section parser
+ @ParseMacro
+ def _DefineParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
+ self._ValueList[1:len(TokenList)] = TokenList
+
+ # Syntax check
+ if not self._ValueList[1]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ if not self._ValueList[2]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ if (not self._ValueList[1] in self.DefineKeywords and
+ (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
+ EdkLogger.error('Parser', FORMAT_INVALID,
+ "Unknown keyword found: %s. "
+ "If this is a macro you must "
+ "add it as a DEFINE in the DSC" % self._ValueList[1],
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ if not self._InSubsection:
+ self._Defines[self._ValueList[1]] = self._ValueList[2]
+ self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
+
+ @ParseMacro
+ def _SkuIdParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
+ if len(TokenList) not in (2, 3):
+ EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ self._ValueList[0:len(TokenList)] = TokenList
+ @ParseMacro
+ def _DefaultStoresParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
+ if len(TokenList) != 2:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ self._ValueList[0:len(TokenList)] = TokenList
+
+ ## Parse Edk style of library modules
+ @ParseMacro
+ def _LibraryInstanceParser(self):
+ self._ValueList[0] = self._CurrentLine
+
+
+ def _DecodeCODEData(self):
+ pass
+ ## PCD sections parser
+ #
+ # [PcdsFixedAtBuild]
+ # [PcdsPatchableInModule]
+ # [PcdsFeatureFlag]
+ # [PcdsDynamicEx
+ # [PcdsDynamicExDefault]
+ # [PcdsDynamicExVpd]
+ # [PcdsDynamicExHii]
+ # [PcdsDynamic]
+ # [PcdsDynamicDefault]
+ # [PcdsDynamicVpd]
+ # [PcdsDynamicHii]
+ #
+ @ParseMacro
+ def _PcdParser(self):
+ if self._PcdDataTypeCODE:
+ self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine
+ if self._CurrentLine.endswith(")}"):
+ self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue))
+ self._PcdDataTypeCODE = False
+ self._PcdCodeValue = ""
+ else:
+ self._ValueList = None
+ return
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
+ self._CurrentPcdName = TokenList[0]
+ if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):
+ self._PcdDataTypeCODE = True
+ self._PcdCodeValue = TokenList[1].strip()
+
+ if self._PcdDataTypeCODE:
+ if self._CurrentLine.endswith(")}"):
+ self._PcdDataTypeCODE = False
+ self._PcdCodeValue = ""
+ else:
+ self._ValueList = None
+ return
+ self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
+ PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)
+ if len(PcdNameTockens) == 2:
+ self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]
+ elif len(PcdNameTockens) == 3:
+ self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]
+ elif len(PcdNameTockens) > 3:
+ self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])
+ if len(TokenList) == 2:
+ self._ValueList[2] = TokenList[1]
+ if self._ValueList[0] == '' or self._ValueList[1] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
+ ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if self._ValueList[2] == '':
+ #
+ # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default
+ #
+ if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
+ return
+ EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
+ ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+ # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
+ ValueList = GetSplitValueList(self._ValueList[2])
+ if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \
+ and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
+ EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
+ # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string
+ if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:
+ DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
+ if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:
+ EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+
+ # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
+ DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
+ if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
+ self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
+ elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
+ self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
+
+
+ ## [components] section parser
+ @ParseMacro
+ def _ComponentParser(self):
+ if self._CurrentLine[-1] == '{':
+ self._ValueList[0] = self._CurrentLine[0:-1].strip()
+ self._InSubsection = True
+ self._SubsectionType = MODEL_UNKNOWN
+ else:
+ self._ValueList[0] = self._CurrentLine
+
+ ## [LibraryClasses] section
+ @ParseMacro
+ def _LibraryClassParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
+ if len(TokenList) < 2:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
+ ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if TokenList[0] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
+ ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if TokenList[1] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
+ ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+ self._ValueList[0:len(TokenList)] = TokenList
+
+
+ ## [BuildOptions] section parser
+ @ParseMacro
+ def _BuildOptionParser(self):
+ self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
+ TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
+ if len(TokenList2) == 2:
+ self._ValueList[0] = TokenList2[0] # toolchain family
+ self._ValueList[1] = TokenList2[1] # keys
+ else:
+ self._ValueList[1] = TokenList[0]
+ if len(TokenList) == 2: # value
+ self._ValueList[2] = TokenList[1]
+
+ if self._ValueList[1].count('_') != 4:
+ EdkLogger.error(
+ 'Parser',
+ FORMAT_INVALID,
+ "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
+ ExtraData=self._CurrentLine,
+ File=self.MetaFile,
+ Line=self._LineIndex + 1
+ )
+
+ ## Override parent's method since we'll do all macro replacements in parser
+ @property
+ def _Macros(self):
+ Macros = {}
+ Macros.update(self._FileLocalMacros)
+ Macros.update(self._GetApplicableSectionMacro())
+ Macros.update(GlobalData.gEdkGlobal)
+ Macros.update(GlobalData.gPlatformDefines)
+ Macros.update(GlobalData.gCommandLineDefines)
+ # PCD cannot be referenced in macro definition
+ if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
+ Macros.update(self._Symbols)
+ if GlobalData.BuildOptionPcd:
+ for Item in GlobalData.BuildOptionPcd:
+ if isinstance(Item, tuple):
+ continue
+ PcdName, TmpValue = Item.split("=")
+ TmpValue = BuildOptionValue(TmpValue, self._GuidDict)
+ Macros[PcdName.strip()] = TmpValue
+ return Macros
+
+ def _PostProcess(self):
+ Processer = {
+ MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
+ MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
+ MODEL_META_DATA_HEADER : self.__ProcessDefine,
+ MODEL_META_DATA_DEFINE : self.__ProcessDefine,
+ MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
+ MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
+ MODEL_META_DATA_PACKAGE : self.__ProcessPackages,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
+ MODEL_EFI_SKU_ID : self.__ProcessSkuId,
+ MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,
+ MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
+ MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
+ MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
+ MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
+ MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
+ MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
+ MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
+ MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
+ MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
+ MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
+ MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
+ MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
+ MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
+ MODEL_UNKNOWN : self._Skip,
+ MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,
+ }
+
+ self._Table = MetaFileStorage(self._RawTable.DB, self.MetaFile, MODEL_FILE_DSC, True)
+ self._DirectiveStack = []
+ self._DirectiveEvalStack = []
+ self._FileWithError = self.MetaFile
+ self._FileLocalMacros = {}
+ self._SectionsMacroDict.clear()
+ GlobalData.gPlatformDefines = {}
+
+ # Get all macro and PCD which has straitforward value
+ self.__RetrievePcdValue()
+ self._Content = self._RawTable.GetAll()
+ self._ContentIndex = 0
+ self._InSubsection = False
+ while self._ContentIndex < len(self._Content) :
+ Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \
+ LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
+
+ if self._From < 0:
+ self._FileWithError = self.MetaFile
+
+ self._ContentIndex += 1
+
+ self._Scope = [[S1, S2, S3]]
+ #
+ # For !include directive, handle it specially,
+ # merge arch and module type in case of duplicate items
+ #
+ while self._ItemType == MODEL_META_DATA_INCLUDE:
+ if self._ContentIndex >= len(self._Content):
+ break
+ Record = self._Content[self._ContentIndex]
+ if LineStart == Record[10] and LineEnd == Record[12]:
+ if [Record[5], Record[6], Record[7]] not in self._Scope:
+ self._Scope.append([Record[5], Record[6], Record[7]])
+ self._ContentIndex += 1
+ else:
+ break
+
+ self._LineIndex = LineStart - 1
+ self._ValueList = [V1, V2, V3]
+
+ if Owner > 0 and Owner in self._IdMapping:
+ self._InSubsection = True
+ else:
+ self._InSubsection = False
+ try:
+ Processer[self._ItemType]()
+ except EvaluationException as Excpt:
+ #
+ # Only catch expression evaluation error here. We need to report
+ # the precise number of line on which the error occurred
+ #
+ if hasattr(Excpt, 'Pcd'):
+ if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
+ Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
+ EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
+ " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
+ " of the DSC file, and it is currently defined in this section:"
+ " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
+ File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+ Line=self._LineIndex + 1)
+ else:
+ EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
+ File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+ Line=self._LineIndex + 1)
+ else:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
+ File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+ Line=self._LineIndex + 1)
+ except MacroException as Excpt:
+ EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
+ File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+ Line=self._LineIndex + 1)
+
+ if self._ValueList is None:
+ continue
+
+ NewOwner = self._IdMapping.get(Owner, -1)
+ self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
+ self._LastItem = self._Store(
+ self._ItemType,
+ self._ValueList[0],
+ self._ValueList[1],
+ self._ValueList[2],
+ S1,
+ S2,
+ S3,
+ NewOwner,
+ self._From,
+ self._LineIndex + 1,
+ - 1,
+ self._LineIndex + 1,
+ - 1,
+ self._Enabled
+ )
+ self._IdMapping[Id] = self._LastItem
+
+ GlobalData.gPlatformDefines.update(self._FileLocalMacros)
+ self._PostProcessed = True
+ self._Content = None
+ def _ProcessError(self):
+ if not self._Enabled:
+ return
+ EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)
+
+ def __ProcessSectionHeader(self):
+ self._SectionName = self._ValueList[0]
+ if self._SectionName in self.DataType:
+ self._SectionType = self.DataType[self._SectionName]
+ else:
+ self._SectionType = MODEL_UNKNOWN
+
+ def __ProcessSubsectionHeader(self):
+ self._SubsectionName = self._ValueList[0]
+ if self._SubsectionName in self.DataType:
+ self._SubsectionType = self.DataType[self._SubsectionName]
+ else:
+ self._SubsectionType = MODEL_UNKNOWN
+
+ def __RetrievePcdValue(self):
+ try:
+ with open(str(self.MetaFile), 'r') as File:
+ Content = File.readlines()
+ except:
+ EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
+
+ GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
+ for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
+ MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
+ MODEL_PCD_DYNAMIC_EX_VPD):
+ Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
+ for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:
+ Name = TokenSpaceGuid + '.' + PcdName
+ if Name not in GlobalData.gPlatformOtherPcds:
+ PcdLine = Line
+ while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
+ Line -= 1
+ GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
+
+ def __ProcessDefine(self):
+ if not self._Enabled:
+ return
+
+ Type, Name, Value = self._ValueList
+ Value = ReplaceMacro(Value, self._Macros, False)
+ #
+ # If it is <Defines>, return
+ #
+ if self._InSubsection:
+ self._ValueList = [Type, Name, Value]
+ return
+
+ if self._ItemType == MODEL_META_DATA_DEFINE:
+ if self._SectionType == MODEL_META_DATA_HEADER:
+ self._FileLocalMacros[Name] = Value
+ else:
+ self._ConstructSectionMacroDict(Name, Value)
+ elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
+ GlobalData.gEdkGlobal[Name] = Value
+
+ #
+ # Keyword in [Defines] section can be used as Macros
+ #
+ if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
+ self._FileLocalMacros[Name] = Value
+
+ self._ValueList = [Type, Name, Value]
+
+ def __ProcessDirective(self):
+ Result = None
+ if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
+ Macros = self._Macros
+ Macros.update(GlobalData.gGlobalDefines)
+ try:
+ Result = ValueExpression(self._ValueList[1], Macros)()
+ except SymbolNotFound as Exc:
+ EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
+ Result = False
+ except WrnExpression as Excpt:
+ #
+ # Catch expression evaluation warning here. We need to report
+ # the precise number of line and return the evaluation result
+ #
+ EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
+ File=self._FileWithError, ExtraData=' '.join(self._ValueList),
+ Line=self._LineIndex + 1)
+ Result = Excpt.result
+
+ if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
+ self._DirectiveStack.append(self._ItemType)
+ if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
+ Result = bool(Result)
+ else:
+ Macro = self._ValueList[1]
+ Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
+ Result = Macro in self._Macros
+ if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
+ Result = not Result
+ self._DirectiveEvalStack.append(Result)
+ elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
+ self._DirectiveStack.append(self._ItemType)
+ self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
+ self._DirectiveEvalStack.append(bool(Result))
+ elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
+ self._DirectiveStack.append(self._ItemType)
+ self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
+ self._DirectiveEvalStack.append(True)
+ elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
+ # Back to the nearest !if/!ifdef/!ifndef
+ while self._DirectiveStack:
+ self._DirectiveEvalStack.pop()
+ Directive = self._DirectiveStack.pop()
+ if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
+ MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
+ break
+ elif self._ItemType == MODEL_META_DATA_INCLUDE:
+ # The included file must be relative to workspace or same directory as DSC file
+ __IncludeMacros = {}
+ #
+ # Allow using system environment variables in path after !include
+ #
+ __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
+ #
+ # Allow using MACROs comes from [Defines] section to keep compatible.
+ #
+ __IncludeMacros.update(self._Macros)
+
+ IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
+ #
+ # First search the include file under the same directory as DSC file
+ #
+ IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
+ if self._Enabled:
+ ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
+ if ErrorCode != 0:
+ #
+ # Also search file under the WORKSPACE directory
+ #
+ IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
+ ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
+ if ErrorCode != 0:
+ EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
+ Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
+
+ self._FileWithError = IncludedFile1
+
+ FromItem = self._Content[self._ContentIndex - 1][0]
+ if self._InSubsection:
+ Owner = self._Content[self._ContentIndex - 1][8]
+ else:
+ Owner = self._Content[self._ContentIndex - 1][0]
+ IncludedFileTable = MetaFileStorage(self._RawTable.DB, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)
+ Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,
+ Owner=Owner, From=FromItem)
+
+ self.IncludedFiles.add (IncludedFile1)
+
+ # set the parser status with current status
+ Parser._SectionName = self._SectionName
+ Parser._SubsectionType = self._SubsectionType
+ Parser._InSubsection = self._InSubsection
+ Parser._SectionType = self._SectionType
+ Parser._Scope = self._Scope
+ Parser._Enabled = self._Enabled
+ # Parse the included file
+ Parser.StartParse()
+ # Insert all records in the table for the included file into dsc file table
+ Records = IncludedFileTable.GetAll()
+ if Records:
+ self._Content[self._ContentIndex:self._ContentIndex] = Records
+ self._Content.pop(self._ContentIndex - 1)
+ self._ValueList = None
+ self._ContentIndex -= 1
+
+ def __ProcessPackages(self):
+ self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
+
+ def __ProcessSkuId(self):
+ self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
+ for Value in self._ValueList]
+ def __ProcessDefaultStores(self):
+ self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
+ for Value in self._ValueList]
+
+ def __ProcessLibraryInstance(self):
+ self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
+
+ def __ProcessLibraryClass(self):
+ self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
+
+ def __ProcessPcd(self):
+ if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
+ self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
+ return
+
+ ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
+ if not Valid:
+ if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
+ if ValList[1] != TAB_VOID and StructPattern.match(ValList[1]) is None and ValList[2]:
+ EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. The datum type info should be VOID* or a valid struct name.", File=self._FileWithError,
+ Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
+ EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,
+ ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
+ PcdValue = ValList[Index]
+ if PcdValue and "." not in self._ValueList[0]:
+ try:
+ ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
+ except WrnExpression as Value:
+ ValList[Index] = Value.result
+ except:
+ pass
+
+ if ValList[Index] == 'True':
+ ValList[Index] = '1'
+ if ValList[Index] == 'False':
+ ValList[Index] = '0'
+
+ if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):
+ GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
+ self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
+ try:
+ self._ValueList[2] = '|'.join(ValList)
+ except Exception:
+ print(ValList)
+
+ def __ProcessComponent(self):
+ self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
+
+ def __ProcessBuildOption(self):
+ self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
+ for Value in self._ValueList]
+
+ def DisableOverrideComponent(self,module_id):
+ for ori_id in self._IdMapping:
+ if self._IdMapping[ori_id] == module_id:
+ self._RawTable.DisableComponent(ori_id)
+
+ _SectionParser = {
+ MODEL_META_DATA_HEADER : _DefineParser,
+ MODEL_EFI_SKU_ID : _SkuIdParser,
+ MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,
+ MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
+ MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
+ MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
+ MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
+ MODEL_PCD_FEATURE_FLAG : _PcdParser,
+ MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
+ MODEL_PCD_DYNAMIC_HII : _PcdParser,
+ MODEL_PCD_DYNAMIC_VPD : _PcdParser,
+ MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
+ MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
+ MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
+ MODEL_META_DATA_COMPONENT : _ComponentParser,
+ MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
+ MODEL_UNKNOWN : MetaFileParser._Skip,
+ MODEL_META_DATA_PACKAGE : MetaFileParser._PackageParser,
+ MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
+ MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
+ MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
+ }
+
+## DEC file parser class
+#
+# @param FilePath The path of platform description file
+# @param FileType The raw data of DSC file
+# @param Table Database used to retrieve module/package information
+# @param Macros Macros used for replacement in file
+#
+class DecParser(MetaFileParser):
+ # DEC file supported data types (one type per section)
+ DataType = {
+ TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
+ TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
+ TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
+ TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
+ TAB_GUIDS.upper() : MODEL_EFI_GUID,
+ TAB_PPIS.upper() : MODEL_EFI_PPI,
+ TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
+ TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
+ TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
+ TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
+ TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
+ TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
+ TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
+ }
+
+ ## Constructor of DecParser
+ #
+ # Initialize object of DecParser
+ #
+ # @param FilePath The path of platform description file
+ # @param FileType The raw data of DSC file
+ # @param Arch Default Arch value for filtering sections
+ # @param Table Database used to retrieve module/package information
+ #
+ def __init__(self, FilePath, FileType, Arch, Table):
+ # prevent re-initialization
+ if hasattr(self, "_Table"):
+ return
+ MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)
+ self._Comments = []
+ self._Version = 0x00010005 # Only EDK2 dec file is supported
+ self._AllPCDs = [] # Only for check duplicate PCD
+ self._AllPcdDict = {}
+
+ self._CurrentStructurePcdName = ""
+ self._include_flag = False
+ self._package_flag = False
+
+ self._RestofValue = ""
+
+ ## Parser starter
+ def Start(self):
+ Content = ''
+ try:
+ with open(str(self.MetaFile), 'r') as File:
+ Content = File.readlines()
+ except:
+ EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
+
+ Content = self.ProcessMultipleLineCODEValue(Content)
+
+ self._DefinesCount = 0
+ for Index in range(0, len(Content)):
+ Line, Comment = CleanString2(Content[Index])
+ self._CurrentLine = Line
+ self._LineIndex = Index
+
+ # save comment for later use
+ if Comment:
+ self._Comments.append((Comment, self._LineIndex + 1))
+ # skip empty line
+ if Line == '':
+ continue
+
+ # section header
+ if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
+ self._SectionHeaderParser()
+ if self._SectionName == TAB_DEC_DEFINES.upper():
+ self._DefinesCount += 1
+ self._Comments = []
+ continue
+ if self._SectionType == MODEL_UNKNOWN:
+ EdkLogger.error("Parser", FORMAT_INVALID,
+ ""
+ "Not able to determine \"%s\" in which section."%self._CurrentLine,
+ self.MetaFile, self._LineIndex + 1)
+ elif len(self._SectionType) == 0:
+ self._Comments = []
+ continue
+
+ # section content
+ self._ValueList = ['', '', '']
+ self._SectionParser[self._SectionType[0]](self)
+ if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
+ self._ItemType = -1
+ self._Comments = []
+ continue
+
+ #
+ # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
+ # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
+ #
+ for Arch, ModuleType, Type in self._Scope:
+ self._LastItem = self._Store(
+ Type,
+ self._ValueList[0],
+ self._ValueList[1],
+ self._ValueList[2],
+ Arch,
+ ModuleType,
+ self._Owner[-1],
+ self._LineIndex + 1,
+ - 1,
+ self._LineIndex + 1,
+ - 1,
+ 0
+ )
+ for Comment, LineNo in self._Comments:
+ self._Store(
+ MODEL_META_DATA_COMMENT,
+ Comment,
+ self._ValueList[0],
+ self._ValueList[1],
+ Arch,
+ ModuleType,
+ self._LastItem,
+ LineNo,
+ - 1,
+ LineNo,
+ - 1,
+ 0
+ )
+ self._Comments = []
+ if self._DefinesCount > 1:
+ EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )
+ if self._DefinesCount == 0:
+ EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)
+ self._Done()
+
+
+ ## Section header parser
+ #
+ # The section header is always in following format:
+ #
+ # [section_name.arch<.platform|module_type>]
+ #
+ def _SectionHeaderParser(self):
+ self._Scope = []
+ self._SectionName = ''
+ self._SectionType = []
+ ArchList = set()
+ PrivateList = set()
+ Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)
+ for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
+ if Item == '':
+ EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
+ "section name can NOT be empty or incorrectly use separator comma",
+ self.MetaFile, self._LineIndex + 1, self._CurrentLine)
+ ItemList = Item.split(TAB_SPLIT)
+
+ # different types of PCD are permissible in one section
+ self._SectionName = ItemList[0].upper()
+ if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):
+ EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",
+ self.MetaFile, self._LineIndex + 1, self._CurrentLine)
+ if self._SectionName in self.DataType:
+ if self.DataType[self._SectionName] not in self._SectionType:
+ self._SectionType.append(self.DataType[self._SectionName])
+ else:
+ EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
+ self.MetaFile, self._LineIndex + 1, self._CurrentLine)
+
+ if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
+ EdkLogger.error(
+ 'Parser',
+ FORMAT_INVALID,
+ "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
+ File=self.MetaFile,
+ Line=self._LineIndex + 1,
+ ExtraData=self._CurrentLine
+ )
+ # S1 is always Arch
+ if len(ItemList) > 1:
+ S1 = ItemList[1].upper()
+ else:
+ S1 = TAB_ARCH_COMMON
+ ArchList.add(S1)
+ # S2 may be Platform or ModuleType
+ if len(ItemList) > 2:
+ S2 = ItemList[2].upper()
+ # only Includes, GUIDs, PPIs, Protocols section have Private tag
+ if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:
+ if S2 != 'PRIVATE':
+ EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',
+ File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
+ else:
+ S2 = TAB_COMMON
+ PrivateList.add(S2)
+ if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
+ self._Scope.append([S1, S2, self.DataType[self._SectionName]])
+
+ # 'COMMON' must not be used with specific ARCHs at the same section
+ if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
+ EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
+ File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
+
+ # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
+ if TAB_COMMON in PrivateList and len(PrivateList) > 1:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
+ File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
+
+ ## [guids], [ppis] and [protocols] section parser
+ @ParseMacro
+ def _GuidParser(self):
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
+ if len(TokenList) < 2:
+ EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
+ ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if TokenList[0] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
+ ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if TokenList[1] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
+ ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
+ ExtraData=self._CurrentLine + \
+ " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ self._ValueList[0] = TokenList[0]
+ self._ValueList[1] = TokenList[1]
+ if self._ValueList[0] not in self._GuidDict:
+ self._GuidDict[self._ValueList[0]] = self._ValueList[1]
+
+ def ParsePcdName(self,namelist):
+ if "[" in namelist[1]:
+ pcdname = namelist[1][:namelist[1].index("[")]
+ arrayindex = namelist[1][namelist[1].index("["):]
+ namelist[1] = pcdname
+ if len(namelist) == 2:
+ namelist.append(arrayindex)
+ else:
+ namelist[2] = ".".join((arrayindex,namelist[2]))
+ return namelist
+
+ ## PCD sections parser
+ #
+ # [PcdsFixedAtBuild]
+ # [PcdsPatchableInModule]
+ # [PcdsFeatureFlag]
+ # [PcdsDynamicEx
+ # [PcdsDynamic]
+ #
+ @ParseMacro
+ def _PcdParser(self):
+
+ if self._CurrentStructurePcdName:
+ self._ValueList[0] = self._CurrentStructurePcdName
+
+ if "|" not in self._CurrentLine:
+ if "<HeaderFiles>" == self._CurrentLine:
+ self._include_flag = True
+ self._package_flag = False
+ self._ValueList = None
+ return
+ if "<Packages>" == self._CurrentLine:
+ self._package_flag = True
+ self._ValueList = None
+ self._include_flag = False
+ return
+
+ if self._include_flag:
+ self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
+ self._ValueList[2] = self._CurrentLine
+ if self._package_flag and "}" != self._CurrentLine:
+ self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
+ self._ValueList[2] = self._CurrentLine
+ if self._CurrentLine == "}":
+ self._package_flag = False
+ self._include_flag = False
+ self._ValueList = None
+ return
+ else:
+ PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)
+ PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))
+ if len(PcdNames) == 2:
+ if PcdNames[1].strip().endswith("]"):
+ PcdName = PcdNames[1][:PcdNames[1].index('[')]
+ Index = PcdNames[1][PcdNames[1].index('['):]
+ self._ValueList[0] = TAB_SPLIT.join((PcdNames[0],PcdName))
+ self._ValueList[1] = Index
+ self._ValueList[2] = PcdTockens[1]
+ else:
+ self._CurrentStructurePcdName = ""
+ else:
+ if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):
+ EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])
+ self._ValueList[2] = PcdTockens[1]
+ if not self._CurrentStructurePcdName:
+ if self._PcdDataTypeCODE:
+ if ")}" in self._CurrentLine:
+ ValuePart,RestofValue = self._CurrentLine.split(")}")
+ self._PcdCodeValue = self._PcdCodeValue + "\n " + ValuePart
+ self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue,RestofValue))
+ self._PcdDataTypeCODE = False
+ self._PcdCodeValue = ""
+ else:
+ self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine
+ self._ValueList = None
+ return
+ TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
+ self._CurrentPcdName = TokenList[0]
+ if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):
+ if ")}" in self._CurrentLine:
+ self._PcdDataTypeCODE = False
+ self._PcdCodeValue = ""
+ else:
+ self._PcdDataTypeCODE = True
+ self._PcdCodeValue = TokenList[1].strip()
+ self._ValueList = None
+ return
+
+ self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
+ ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
+ # check PCD information
+ if self._ValueList[0] == '' or self._ValueList[1] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ # check format of token space GUID CName
+ if not ValueRe.match(self._ValueList[0]):
+ EdkLogger.error('Parser', FORMAT_INVALID, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ # check format of PCD CName
+ if not ValueRe.match(self._ValueList[1]):
+ EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ # check PCD datum information
+ if len(TokenList) < 2 or TokenList[1] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+
+ ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
+ PtrValue = ValueRe.findall(TokenList[1])
+
+ # Has VOID* type string, may contain "|" character in the string.
+ if len(PtrValue) != 0:
+ ptrValueList = re.sub(ValueRe, '', TokenList[1])
+ ValueList = AnalyzePcdExpression(ptrValueList)
+ ValueList[0] = PtrValue[0]
+ else:
+ ValueList = AnalyzePcdExpression(TokenList[1])
+
+
+ # check if there's enough datum information given
+ if len(ValueList) != 3:
+ EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ # check default value
+ if ValueList[0] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ # check datum type
+ if ValueList[1] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+ # check token of the PCD
+ if ValueList[2] == '':
+ EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
+ ExtraData=self._CurrentLine + \
+ " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+ PcdValue = ValueList[0]
+ if PcdValue:
+ try:
+ self._GuidDict.update(self._AllPcdDict)
+ ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
+ except BadExpression as Value:
+ EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ # check format of default value against the datum type
+ IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
+ if not IsValid:
+ EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
+ File=self.MetaFile, Line=self._LineIndex + 1)
+
+ if Cause == "StructurePcd":
+ self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])
+ self._ValueList[0] = self._CurrentStructurePcdName
+ self._ValueList[1] = ValueList[1].strip()
+
+ if ValueList[0] in ['True', 'true', 'TRUE']:
+ ValueList[0] = '1'
+ elif ValueList[0] in ['False', 'false', 'FALSE']:
+ ValueList[0] = '0'
+
+ # check for duplicate PCD definition
+ if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
+ EdkLogger.error('Parser', FORMAT_INVALID,
+ "The same PCD name and GUID have been already defined",
+ ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
+ else:
+ self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
+ self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]
+
+ self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
+
+ _SectionParser = {
+ MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
+ MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
+ MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
+ MODEL_EFI_GUID : _GuidParser,
+ MODEL_EFI_PPI : _GuidParser,
+ MODEL_EFI_PROTOCOL : _GuidParser,
+ MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
+ MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
+ MODEL_PCD_FEATURE_FLAG : _PcdParser,
+ MODEL_PCD_DYNAMIC : _PcdParser,
+ MODEL_PCD_DYNAMIC_EX : _PcdParser,
+ MODEL_UNKNOWN : MetaFileParser._Skip,
+ MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
+ }
+
+##
+#
+# This acts like the main() function for the script, unless it is 'import'ed into another
+# script.
+#
+if __name__ == '__main__':
+ pass
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py
new file mode 100755
index 00000000..7635d893
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py
@@ -0,0 +1,430 @@
+## @file
+# This file is used to create/update/query/erase a meta file table
+#
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+import uuid
+
+import Common.EdkLogger as EdkLogger
+from Common.BuildToolError import FORMAT_INVALID
+
+from CommonDataClass.DataClass import MODEL_FILE_DSC, MODEL_FILE_DEC, MODEL_FILE_INF, \
+ MODEL_FILE_OTHERS
+from Common.DataType import *
+
+class MetaFileTable():
+ # TRICK: use file ID as the part before '.'
+ _ID_STEP_ = 1
+ _ID_MAX_ = 99999999
+
+ ## Constructor
+ def __init__(self, DB, MetaFile, FileType, Temporary, FromItem=None):
+ self.MetaFile = MetaFile
+ self.TableName = ""
+ self.DB = DB
+ self._NumpyTab = None
+
+ self.CurrentContent = []
+ DB.TblFile.append([MetaFile.Name,
+ MetaFile.Ext,
+ MetaFile.Dir,
+ MetaFile.Path,
+ FileType,
+ MetaFile.TimeStamp,
+ FromItem])
+ self.FileId = len(DB.TblFile)
+ self.ID = self.FileId * 10**8
+ if Temporary:
+ self.TableName = "_%s_%s_%s" % (FileType, len(DB.TblFile), uuid.uuid4().hex)
+ else:
+ self.TableName = "_%s_%s" % (FileType, len(DB.TblFile))
+
+ def IsIntegrity(self):
+ Result = False
+ try:
+ TimeStamp = self.MetaFile.TimeStamp
+ if not self.CurrentContent:
+ Result = False
+ else:
+ Result = self.CurrentContent[-1][0] < 0
+ except Exception as Exc:
+ EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc))
+ return False
+ return Result
+
+ def SetEndFlag(self):
+ self.CurrentContent.append(self._DUMMY_)
+
+ def GetAll(self):
+ return [item for item in self.CurrentContent if item[0] >= 0 and item[-1]>=0]
+
+## Python class representation of table storing module data
+class ModuleTable(MetaFileTable):
+ _COLUMN_ = '''
+ ID REAL PRIMARY KEY,
+ Model INTEGER NOT NULL,
+ Value1 TEXT NOT NULL,
+ Value2 TEXT,
+ Value3 TEXT,
+ Scope1 TEXT,
+ Scope2 TEXT,
+ BelongsToItem REAL NOT NULL,
+ StartLine INTEGER NOT NULL,
+ StartColumn INTEGER NOT NULL,
+ EndLine INTEGER NOT NULL,
+ EndColumn INTEGER NOT NULL,
+ Enabled INTEGER DEFAULT 0
+ '''
+ # used as table end flag, in case the changes to database is not committed to db file
+ _DUMMY_ = [-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1]
+
+ ## Constructor
+ def __init__(self, Db, MetaFile, Temporary):
+ MetaFileTable.__init__(self, Db, MetaFile, MODEL_FILE_INF, Temporary)
+
+ ## Insert a record into table Inf
+ #
+ # @param Model: Model of a Inf item
+ # @param Value1: Value1 of a Inf item
+ # @param Value2: Value2 of a Inf item
+ # @param Value3: Value3 of a Inf item
+ # @param Scope1: Arch of a Inf item
+ # @param Scope2 Platform os a Inf item
+ # @param BelongsToItem: The item belongs to which another item
+ # @param StartLine: StartLine of a Inf item
+ # @param StartColumn: StartColumn of a Inf item
+ # @param EndLine: EndLine of a Inf item
+ # @param EndColumn: EndColumn of a Inf item
+ # @param Enabled: If this item enabled
+ #
+ def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON,
+ BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0):
+
+ (Value1, Value2, Value3, Scope1, Scope2) = (Value1.strip(), Value2.strip(), Value3.strip(), Scope1.strip(), Scope2.strip())
+ self.ID = self.ID + self._ID_STEP_
+ if self.ID >= (MODEL_FILE_INF + self._ID_MAX_):
+ self.ID = MODEL_FILE_INF + self._ID_STEP_
+
+ row = [ self.ID,
+ Model,
+ Value1,
+ Value2,
+ Value3,
+ Scope1,
+ Scope2,
+ BelongsToItem,
+ StartLine,
+ StartColumn,
+ EndLine,
+ EndColumn,
+ Enabled
+ ]
+ self.CurrentContent.append(row)
+ return self.ID
+
+ ## Query table
+ #
+ # @param Model: The Model of Record
+ # @param Arch: The Arch attribute of Record
+ # @param Platform The Platform attribute of Record
+ #
+ # @retval: A recordSet of all found records
+ #
+ def Query(self, Model, Arch=None, Platform=None, BelongsToItem=None):
+
+ QueryTab = self.CurrentContent
+ result = [item for item in QueryTab if item[1] == Model and item[-1]>=0 ]
+
+ if Arch is not None and Arch != TAB_ARCH_COMMON:
+ ArchList = set(['COMMON'])
+ ArchList.add(Arch)
+ result = [item for item in result if item[5] in ArchList]
+
+ if Platform is not None and Platform != TAB_COMMON:
+ Platformlist = set( ['COMMON','DEFAULT'])
+ Platformlist.add(Platform)
+ result = [item for item in result if item[6] in Platformlist]
+
+ if BelongsToItem is not None:
+ result = [item for item in result if item[7] == BelongsToItem]
+
+ result = [ [r[2],r[3],r[4],r[5],r[6],r[0],r[8]] for r in result ]
+ return result
+
+## Python class representation of table storing package data
+class PackageTable(MetaFileTable):
+ _COLUMN_ = '''
+ ID REAL PRIMARY KEY,
+ Model INTEGER NOT NULL,
+ Value1 TEXT NOT NULL,
+ Value2 TEXT,
+ Value3 TEXT,
+ Scope1 TEXT,
+ Scope2 TEXT,
+ BelongsToItem REAL NOT NULL,
+ StartLine INTEGER NOT NULL,
+ StartColumn INTEGER NOT NULL,
+ EndLine INTEGER NOT NULL,
+ EndColumn INTEGER NOT NULL,
+ Enabled INTEGER DEFAULT 0
+ '''
+ # used as table end flag, in case the changes to database is not committed to db file
+ _DUMMY_ = [-1, -1, '====', '====', '====', '====', '====', -1, -1, -1, -1, -1, -1]
+
+ ## Constructor
+ def __init__(self, Cursor, MetaFile, Temporary):
+ MetaFileTable.__init__(self, Cursor, MetaFile, MODEL_FILE_DEC, Temporary)
+
+ ## Insert table
+ #
+ # Insert a record into table Dec
+ #
+ # @param Model: Model of a Dec item
+ # @param Value1: Value1 of a Dec item
+ # @param Value2: Value2 of a Dec item
+ # @param Value3: Value3 of a Dec item
+ # @param Scope1: Arch of a Dec item
+ # @param Scope2: Module type of a Dec item
+ # @param BelongsToItem: The item belongs to which another item
+ # @param StartLine: StartLine of a Dec item
+ # @param StartColumn: StartColumn of a Dec item
+ # @param EndLine: EndLine of a Dec item
+ # @param EndColumn: EndColumn of a Dec item
+ # @param Enabled: If this item enabled
+ #
+ def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON,
+ BelongsToItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=0):
+ (Value1, Value2, Value3, Scope1, Scope2) = (Value1.strip(), Value2.strip(), Value3.strip(), Scope1.strip(), Scope2.strip())
+ self.ID = self.ID + self._ID_STEP_
+
+ row = [ self.ID,
+ Model,
+ Value1,
+ Value2,
+ Value3,
+ Scope1,
+ Scope2,
+ BelongsToItem,
+ StartLine,
+ StartColumn,
+ EndLine,
+ EndColumn,
+ Enabled
+ ]
+ self.CurrentContent.append(row)
+ return self.ID
+
+ ## Query table
+ #
+ # @param Model: The Model of Record
+ # @param Arch: The Arch attribute of Record
+ #
+ # @retval: A recordSet of all found records
+ #
+ def Query(self, Model, Arch=None):
+
+ QueryTab = self.CurrentContent
+ result = [item for item in QueryTab if item[1] == Model and item[-1]>=0 ]
+
+ if Arch is not None and Arch != TAB_ARCH_COMMON:
+ ArchList = set(['COMMON'])
+ ArchList.add(Arch)
+ result = [item for item in result if item[5] in ArchList]
+
+ return [[r[2], r[3], r[4], r[5], r[6], r[0], r[8]] for r in result]
+
+ def GetValidExpression(self, TokenSpaceGuid, PcdCName):
+
+ QueryTab = self.CurrentContent
+ result = [[item[2], item[8]] for item in QueryTab if item[3] == TokenSpaceGuid and item[4] == PcdCName]
+ validateranges = []
+ validlists = []
+ expressions = []
+ try:
+ for row in result:
+ comment = row[0]
+
+ LineNum = row[1]
+ comment = comment.strip("#")
+ comment = comment.strip()
+ oricomment = comment
+ if comment.startswith("@ValidRange"):
+ comment = comment.replace("@ValidRange", "", 1)
+ validateranges.append(comment.split("|")[1].strip())
+ if comment.startswith("@ValidList"):
+ comment = comment.replace("@ValidList", "", 1)
+ validlists.append(comment.split("|")[1].strip())
+ if comment.startswith("@Expression"):
+ comment = comment.replace("@Expression", "", 1)
+ expressions.append(comment.split("|")[1].strip())
+ except Exception as Exc:
+ ValidType = ""
+ if oricomment.startswith("@ValidRange"):
+ ValidType = "@ValidRange"
+ if oricomment.startswith("@ValidList"):
+ ValidType = "@ValidList"
+ if oricomment.startswith("@Expression"):
+ ValidType = "@Expression"
+ EdkLogger.error('Parser', FORMAT_INVALID, "The syntax for %s of PCD %s.%s is incorrect" % (ValidType, TokenSpaceGuid, PcdCName),
+ ExtraData=oricomment, File=self.MetaFile, Line=LineNum)
+ return set(), set(), set()
+ return set(validateranges), set(validlists), set(expressions)
+
+## Python class representation of table storing platform data
+class PlatformTable(MetaFileTable):
+ _COLUMN_ = '''
+ ID REAL PRIMARY KEY,
+ Model INTEGER NOT NULL,
+ Value1 TEXT NOT NULL,
+ Value2 TEXT,
+ Value3 TEXT,
+ Scope1 TEXT,
+ Scope2 TEXT,
+ Scope3 TEXT,
+ BelongsToItem REAL NOT NULL,
+ FromItem REAL NOT NULL,
+ StartLine INTEGER NOT NULL,
+ StartColumn INTEGER NOT NULL,
+ EndLine INTEGER NOT NULL,
+ EndColumn INTEGER NOT NULL,
+ Enabled INTEGER DEFAULT 0
+ '''
+ # used as table end flag, in case the changes to database is not committed to db file
+ _DUMMY_ = [-1, -1, '====', '====', '====', '====', '====','====', -1, -1, -1, -1, -1, -1, -1]
+
+ ## Constructor
+ def __init__(self, Cursor, MetaFile, Temporary, FromItem=0):
+ MetaFileTable.__init__(self, Cursor, MetaFile, MODEL_FILE_DSC, Temporary, FromItem)
+
+ ## Insert table
+ #
+ # Insert a record into table Dsc
+ #
+ # @param Model: Model of a Dsc item
+ # @param Value1: Value1 of a Dsc item
+ # @param Value2: Value2 of a Dsc item
+ # @param Value3: Value3 of a Dsc item
+ # @param Scope1: Arch of a Dsc item
+ # @param Scope2: Module type of a Dsc item
+ # @param BelongsToItem: The item belongs to which another item
+ # @param FromItem: The item belongs to which dsc file
+ # @param StartLine: StartLine of a Dsc item
+ # @param StartColumn: StartColumn of a Dsc item
+ # @param EndLine: EndLine of a Dsc item
+ # @param EndColumn: EndColumn of a Dsc item
+ # @param Enabled: If this item enabled
+ #
+ def Insert(self, Model, Value1, Value2, Value3, Scope1=TAB_ARCH_COMMON, Scope2=TAB_COMMON, Scope3=TAB_DEFAULT_STORES_DEFAULT,BelongsToItem=-1,
+ FromItem=-1, StartLine=-1, StartColumn=-1, EndLine=-1, EndColumn=-1, Enabled=1):
+ (Value1, Value2, Value3, Scope1, Scope2, Scope3) = (Value1.strip(), Value2.strip(), Value3.strip(), Scope1.strip(), Scope2.strip(), Scope3.strip())
+ self.ID = self.ID + self._ID_STEP_
+
+ row = [ self.ID,
+ Model,
+ Value1,
+ Value2,
+ Value3,
+ Scope1,
+ Scope2,
+ Scope3,
+ BelongsToItem,
+ FromItem,
+ StartLine,
+ StartColumn,
+ EndLine,
+ EndColumn,
+ Enabled
+ ]
+ self.CurrentContent.append(row)
+ return self.ID
+
+
+ ## Query table
+ #
+ # @param Model: The Model of Record
+ # @param Scope1: Arch of a Dsc item
+ # @param Scope2: Module type of a Dsc item
+ # @param BelongsToItem: The item belongs to which another item
+ # @param FromItem: The item belongs to which dsc file
+ #
+ # @retval: A recordSet of all found records
+ #
+ def Query(self, Model, Scope1=None, Scope2=None, BelongsToItem=None, FromItem=None):
+
+ QueryTab = self.CurrentContent
+ result = [item for item in QueryTab if item[1] == Model and item[-1]>0 ]
+ if Scope1 is not None and Scope1 != TAB_ARCH_COMMON:
+ Sc1 = set(['COMMON'])
+ Sc1.add(Scope1)
+ result = [item for item in result if item[5] in Sc1]
+ Sc2 = set( ['COMMON','DEFAULT'])
+ if Scope2 and Scope2 != TAB_COMMON:
+ if '.' in Scope2:
+ Index = Scope2.index('.')
+ NewScope = TAB_COMMON + Scope2[Index:]
+ Sc2.add(NewScope)
+ Sc2.add(Scope2)
+ result = [item for item in result if item[6] in Sc2]
+
+ if BelongsToItem is not None:
+ result = [item for item in result if item[8] == BelongsToItem]
+ else:
+ result = [item for item in result if item[8] < 0]
+ if FromItem is not None:
+ result = [item for item in result if item[9] == FromItem]
+
+ result = [ [r[2],r[3],r[4],r[5],r[6],r[7],r[0],r[10]] for r in result ]
+ return result
+
+ def DisableComponent(self,comp_id):
+ for item in self.CurrentContent:
+ if item[0] == comp_id or item[8] == comp_id:
+ item[-1] = -1
+
+## Factory class to produce different storage for different type of meta-file
+class MetaFileStorage(object):
+ _FILE_TABLE_ = {
+ MODEL_FILE_INF : ModuleTable,
+ MODEL_FILE_DEC : PackageTable,
+ MODEL_FILE_DSC : PlatformTable,
+ MODEL_FILE_OTHERS : MetaFileTable,
+ }
+
+ _FILE_TYPE_ = {
+ ".inf" : MODEL_FILE_INF,
+ ".dec" : MODEL_FILE_DEC,
+ ".dsc" : MODEL_FILE_DSC,
+ }
+ _ObjectCache = {}
+ ## Constructor
+ def __new__(Class, Cursor, MetaFile, FileType=None, Temporary=False, FromItem=None):
+ # no type given, try to find one
+ key = (MetaFile.Path, FileType,Temporary,FromItem)
+ if key in Class._ObjectCache:
+ return Class._ObjectCache[key]
+ if not FileType:
+ if MetaFile.Type in self._FILE_TYPE_:
+ FileType = Class._FILE_TYPE_[MetaFile.Type]
+ else:
+ FileType = MODEL_FILE_OTHERS
+
+ # don't pass the type around if it's well known
+ if FileType == MODEL_FILE_OTHERS:
+ Args = (Cursor, MetaFile, FileType, Temporary)
+ else:
+ Args = (Cursor, MetaFile, Temporary)
+ if FromItem:
+ Args = Args + (FromItem,)
+
+ # create the storage object and return it to caller
+ reval = Class._FILE_TABLE_[FileType](*Args)
+ if not Temporary:
+ Class._ObjectCache[key] = reval
+ return reval
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
new file mode 100755
index 00000000..c888e6fc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
@@ -0,0 +1,256 @@
+## @file
+# Common routines used by workspace
+#
+# Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+from __future__ import absolute_import
+from collections import OrderedDict, defaultdict
+from Common.DataType import SUP_MODULE_USER_DEFINED
+from Common.DataType import SUP_MODULE_HOST_APPLICATION
+from .BuildClassObject import LibraryClassObject
+import Common.GlobalData as GlobalData
+from Workspace.BuildClassObject import StructurePcd
+from Common.BuildToolError import RESOURCE_NOT_AVAILABLE
+from Common.BuildToolError import OPTION_MISSING
+from Common.BuildToolError import BUILD_ERROR
+import Common.EdkLogger as EdkLogger
+
+class OrderedListDict(OrderedDict):
+ def __init__(self, *args, **kwargs):
+ super(OrderedListDict, self).__init__(*args, **kwargs)
+ self.default_factory = list
+
+ def __missing__(self, key):
+ self[key] = Value = self.default_factory()
+ return Value
+
+## Get all packages from platform for specified arch, target and toolchain
+#
+# @param Platform: DscBuildData instance
+# @param BuildDatabase: The database saves all data for all metafiles
+# @param Arch: Current arch
+# @param Target: Current target
+# @param Toolchain: Current toolchain
+# @retval: List of packages which are DecBuildData instances
+#
+def GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain):
+ PkgSet = set()
+ if Platform.Packages:
+ PkgSet.update(Platform.Packages)
+ for ModuleFile in Platform.Modules:
+ Data = BuildDatabase[ModuleFile, Arch, Target, Toolchain]
+ PkgSet.update(Data.Packages)
+ for Lib in GetLiabraryInstances(Data, Platform, BuildDatabase, Arch, Target, Toolchain):
+ PkgSet.update(Lib.Packages)
+ return list(PkgSet)
+
+## Get all declared PCD from platform for specified arch, target and toolchain
+#
+# @param Platform: DscBuildData instance
+# @param BuildDatabase: The database saves all data for all metafiles
+# @param Arch: Current arch
+# @param Target: Current target
+# @param Toolchain: Current toolchain
+# @retval: A dictionary contains instances of PcdClassObject with key (PcdCName, TokenSpaceGuid)
+# @retval: A dictionary contains real GUIDs of TokenSpaceGuid
+#
+def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain, additionalPkgs):
+ PkgList = GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain)
+ PkgList = set(PkgList)
+ PkgList |= additionalPkgs
+ DecPcds = {}
+ GuidDict = {}
+ for Pkg in PkgList:
+ Guids = Pkg.Guids
+ GuidDict.update(Guids)
+ for Pcd in Pkg.Pcds:
+ PcdCName = Pcd[0]
+ PcdTokenName = Pcd[1]
+ if GlobalData.MixedPcd:
+ for PcdItem in GlobalData.MixedPcd:
+ if (PcdCName, PcdTokenName) in GlobalData.MixedPcd[PcdItem]:
+ PcdCName = PcdItem[0]
+ break
+ if (PcdCName, PcdTokenName) not in DecPcds:
+ DecPcds[PcdCName, PcdTokenName] = Pkg.Pcds[Pcd]
+ return DecPcds, GuidDict
+
+## Get all dependent libraries for a module
+#
+# @param Module: InfBuildData instance
+# @param Platform: DscBuildData instance
+# @param BuildDatabase: The database saves all data for all metafiles
+# @param Arch: Current arch
+# @param Target: Current target
+# @param Toolchain: Current toolchain
+# @retval: List of dependent libraries which are InfBuildData instances
+#
+def GetLiabraryInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain):
+ return GetModuleLibInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain,Platform.MetaFile,EdkLogger)
+
+def GetModuleLibInstances(Module, Platform, BuildDatabase, Arch, Target, Toolchain, FileName = '', EdkLogger = None):
+ if Module.LibInstances:
+ return Module.LibInstances
+ ModuleType = Module.ModuleType
+
+ # add forced library instances (specified under LibraryClasses sections)
+ #
+ # If a module has a MODULE_TYPE of USER_DEFINED,
+ # do not link in NULL library class instances from the global [LibraryClasses.*] sections.
+ #
+ if Module.ModuleType != SUP_MODULE_USER_DEFINED:
+ for LibraryClass in Platform.LibraryClasses.GetKeys():
+ if LibraryClass.startswith("NULL") and Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
+ Module.LibraryClasses[LibraryClass] = Platform.LibraryClasses[LibraryClass, Module.ModuleType]
+
+ # add forced library instances (specified in module overrides)
+ for LibraryClass in Platform.Modules[str(Module)].LibraryClasses:
+ if LibraryClass.startswith("NULL"):
+ Module.LibraryClasses[LibraryClass] = Platform.Modules[str(Module)].LibraryClasses[LibraryClass]
+
+ # EdkII module
+ LibraryConsumerList = [Module]
+ Constructor = []
+ ConsumedByList = OrderedListDict()
+ LibraryInstance = OrderedDict()
+
+ if not Module.LibraryClass:
+ EdkLogger.verbose("")
+ EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), Arch))
+
+ while len(LibraryConsumerList) > 0:
+ M = LibraryConsumerList.pop()
+ for LibraryClassName in M.LibraryClasses:
+ if LibraryClassName not in LibraryInstance:
+ # override library instance for this module
+ LibraryPath = Platform.Modules[str(Module)].LibraryClasses.get(LibraryClassName,Platform.LibraryClasses[LibraryClassName, ModuleType])
+ if LibraryPath is None:
+ LibraryPath = M.LibraryClasses.get(LibraryClassName)
+ if LibraryPath is None:
+ if not Module.LibraryClass:
+ EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
+ "Instance of library class [%s] is not found" % LibraryClassName,
+ File=FileName,
+ ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), Arch, str(Module)))
+ else:
+ return []
+
+ LibraryModule = BuildDatabase[LibraryPath, Arch, Target, Toolchain]
+ # for those forced library instance (NULL library), add a fake library class
+ if LibraryClassName.startswith("NULL"):
+ LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))
+ elif LibraryModule.LibraryClass is None \
+ or len(LibraryModule.LibraryClass) == 0 \
+ or (ModuleType != SUP_MODULE_USER_DEFINED and ModuleType != SUP_MODULE_HOST_APPLICATION
+ and ModuleType not in LibraryModule.LibraryClass[0].SupModList):
+ # only USER_DEFINED can link against any library instance despite of its SupModList
+ if not Module.LibraryClass:
+ EdkLogger.error("build", OPTION_MISSING,
+ "Module type [%s] is not supported by library instance [%s]" \
+ % (ModuleType, LibraryPath), File=FileName,
+ ExtraData="consumed by [%s]" % str(Module))
+ else:
+ return []
+
+ LibraryInstance[LibraryClassName] = LibraryModule
+ LibraryConsumerList.append(LibraryModule)
+ if not Module.LibraryClass:
+ EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))
+ else:
+ LibraryModule = LibraryInstance[LibraryClassName]
+
+ if LibraryModule is None:
+ continue
+
+ if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:
+ Constructor.append(LibraryModule)
+
+ # don't add current module itself to consumer list
+ if M != Module:
+ if M in ConsumedByList[LibraryModule]:
+ continue
+ ConsumedByList[LibraryModule].append(M)
+ #
+ # Initialize the sorted output list to the empty set
+ #
+ SortedLibraryList = []
+ #
+ # Q <- Set of all nodes with no incoming edges
+ #
+ LibraryList = [] #LibraryInstance.values()
+ Q = []
+ for LibraryClassName in LibraryInstance:
+ M = LibraryInstance[LibraryClassName]
+ LibraryList.append(M)
+ if not ConsumedByList[M]:
+ Q.append(M)
+
+ #
+ # start the DAG algorithm
+ #
+ while True:
+ EdgeRemoved = True
+ while Q == [] and EdgeRemoved:
+ EdgeRemoved = False
+ # for each node Item with a Constructor
+ for Item in LibraryList:
+ if Item not in Constructor:
+ continue
+ # for each Node without a constructor with an edge e from Item to Node
+ for Node in ConsumedByList[Item]:
+ if Node in Constructor:
+ continue
+ # remove edge e from the graph if Node has no constructor
+ ConsumedByList[Item].remove(Node)
+ EdgeRemoved = True
+ if not ConsumedByList[Item]:
+ # insert Item into Q
+ Q.insert(0, Item)
+ break
+ if Q != []:
+ break
+ # DAG is done if there's no more incoming edge for all nodes
+ if Q == []:
+ break
+
+ # remove node from Q
+ Node = Q.pop()
+ # output Node
+ SortedLibraryList.append(Node)
+
+ # for each node Item with an edge e from Node to Item do
+ for Item in LibraryList:
+ if Node not in ConsumedByList[Item]:
+ continue
+ # remove edge e from the graph
+ ConsumedByList[Item].remove(Node)
+
+ if ConsumedByList[Item]:
+ continue
+ # insert Item into Q, if Item has no other incoming edges
+ Q.insert(0, Item)
+
+ #
+ # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle
+ #
+ for Item in LibraryList:
+ if ConsumedByList[Item] and Item in Constructor and len(Constructor) > 1:
+ if not Module.LibraryClass:
+ ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join(str(L) for L in ConsumedByList[Item])
+ EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),
+ ExtraData=ErrorMessage, File=FileName)
+ else:
+ return []
+ if Item not in SortedLibraryList:
+ SortedLibraryList.append(Item)
+
+ #
+ # Build the list of constructor and destructor names
+ # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order
+ #
+ SortedLibraryList.reverse()
+ Module.LibInstances = SortedLibraryList
+ SortedLibraryList = [lib.SetReferenceModule(Module) for lib in SortedLibraryList]
+ return SortedLibraryList
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
new file mode 100755
index 00000000..0764e272
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
@@ -0,0 +1,204 @@
+## @file
+# This file is used to create a database used by build tool
+#
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from Common.StringUtils import *
+from Common.DataType import *
+from Common.Misc import *
+from types import *
+
+from .MetaDataTable import *
+from .MetaFileTable import *
+from .MetaFileParser import *
+
+from Workspace.DecBuildData import DecBuildData
+from Workspace.DscBuildData import DscBuildData
+from Workspace.InfBuildData import InfBuildData
+
+## Database
+#
+# This class defined the build database for all modules, packages and platform.
+# It will call corresponding parser for the given file if it cannot find it in
+# the database.
+#
+# @param DbPath Path of database file
+# @param GlobalMacros Global macros used for replacement during file parsing
+# @param RenewDb=False Create new database file if it's already there
+#
+class WorkspaceDatabase(object):
+
+ #
+ # internal class used for call corresponding file parser and caching the result
+ # to avoid unnecessary re-parsing
+ #
+ class BuildObjectFactory(object):
+
+ _FILE_TYPE_ = {
+ ".inf" : MODEL_FILE_INF,
+ ".dec" : MODEL_FILE_DEC,
+ ".dsc" : MODEL_FILE_DSC,
+ }
+
+ # file parser
+ _FILE_PARSER_ = {
+ MODEL_FILE_INF : InfParser,
+ MODEL_FILE_DEC : DecParser,
+ MODEL_FILE_DSC : DscParser,
+ }
+
+ # convert to xxxBuildData object
+ _GENERATOR_ = {
+ MODEL_FILE_INF : InfBuildData,
+ MODEL_FILE_DEC : DecBuildData,
+ MODEL_FILE_DSC : DscBuildData,
+ }
+
+ _CACHE_ = {} # (FilePath, Arch) : <object>
+ def GetCache(self):
+ return self._CACHE_
+
+ # constructor
+ def __init__(self, WorkspaceDb):
+ self.WorkspaceDb = WorkspaceDb
+
+ # key = (FilePath, Arch=None)
+ def __contains__(self, Key):
+ FilePath = Key[0]
+ if len(Key) > 1:
+ Arch = Key[1]
+ else:
+ Arch = None
+ return (FilePath, Arch) in self._CACHE_
+
+ # key = (FilePath, Arch=None, Target=None, Toolchain=None)
+ def __getitem__(self, Key):
+ FilePath = Key[0]
+ KeyLength = len(Key)
+ if KeyLength > 1:
+ Arch = Key[1]
+ else:
+ Arch = None
+ if KeyLength > 2:
+ Target = Key[2]
+ else:
+ Target = None
+ if KeyLength > 3:
+ Toolchain = Key[3]
+ else:
+ Toolchain = None
+
+ # if it's generated before, just return the cached one
+ Key = (FilePath, Arch, Target, Toolchain)
+ if Key in self._CACHE_:
+ return self._CACHE_[Key]
+
+ # check file type
+ BuildObject = self.CreateBuildObject(FilePath, Arch, Target, Toolchain)
+ self._CACHE_[Key] = BuildObject
+ return BuildObject
+ def CreateBuildObject(self,FilePath, Arch, Target, Toolchain):
+ Ext = FilePath.Type
+ if Ext not in self._FILE_TYPE_:
+ return None
+ FileType = self._FILE_TYPE_[Ext]
+ if FileType not in self._GENERATOR_:
+ return None
+
+ # get the parser ready for this file
+ MetaFile = self._FILE_PARSER_[FileType](
+ FilePath,
+ FileType,
+ Arch,
+ MetaFileStorage(self.WorkspaceDb, FilePath, FileType)
+ )
+ # always do post-process, in case of macros change
+ MetaFile.DoPostProcess()
+ # object the build is based on
+ BuildObject = self._GENERATOR_[FileType](
+ FilePath,
+ MetaFile,
+ self,
+ Arch,
+ Target,
+ Toolchain
+ )
+ return BuildObject
+
+ # placeholder for file format conversion
+ class TransformObjectFactory:
+ def __init__(self, WorkspaceDb):
+ self.WorkspaceDb = WorkspaceDb
+
+ # key = FilePath, Arch
+ def __getitem__(self, Key):
+ pass
+
+ ## Constructor of WorkspaceDatabase
+ #
+ # @param DbPath Path of database file
+ # @param GlobalMacros Global macros used for replacement during file parsing
+ # @param RenewDb=False Create new database file if it's already there
+ #
+ def __init__(self):
+ self.DB = dict()
+ # create table for internal uses
+ self.TblDataModel = DataClass.MODEL_LIST
+ self.TblFile = []
+ self.Platform = None
+
+ # conversion object for build or file format conversion purpose
+ self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
+ self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
+
+
+ ## Summarize all packages in the database
+ def GetPackageList(self, Platform, Arch, TargetName, ToolChainTag):
+ self.Platform = Platform
+ PackageList = []
+ Pa = self.BuildObject[self.Platform, Arch, TargetName, ToolChainTag]
+ #
+ # Get Package related to Modules
+ #
+ for Module in Pa.Modules:
+ ModuleObj = self.BuildObject[Module, Arch, TargetName, ToolChainTag]
+ for Package in ModuleObj.Packages:
+ if Package not in PackageList:
+ PackageList.append(Package)
+ #
+ # Get Packages related to Libraries
+ #
+ for Lib in Pa.LibraryInstances:
+ LibObj = self.BuildObject[Lib, Arch, TargetName, ToolChainTag]
+ for Package in LibObj.Packages:
+ if Package not in PackageList:
+ PackageList.append(Package)
+ for Package in Pa.Packages:
+ if Package in PackageList:
+ continue
+ PackageList.append(Package)
+
+ return PackageList
+
+ def MapPlatform(self, Dscfile):
+ Platform = self.BuildObject[PathClass(Dscfile), TAB_COMMON]
+ if Platform is None:
+ EdkLogger.error('build', PARSER_ERROR, "Failed to parser DSC file: %s" % Dscfile)
+ return Platform
+
+BuildDB = WorkspaceDatabase()
+##
+#
+# This acts like the main() function for the script, unless it is 'import'ed into another
+# script.
+#
+if __name__ == '__main__':
+ pass
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/__init__.py
new file mode 100644
index 00000000..4183055e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/__init__.py
@@ -0,0 +1,9 @@
+## @file
+# Python 'Workspace' package initialization file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#