diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /BaseTools/Source/Python/Workspace | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'BaseTools/Source/Python/Workspace')
| -rw-r--r-- | BaseTools/Source/Python/Workspace/BuildClassObject.py | 1246 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/DecBuildData.py | 922 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/DscBuildData.py | 7344 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/InfBuildData.py | 2200 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/MetaDataTable.py | 612 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/MetaFileCommentParser.py | 90 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/MetaFileParser.py | 4394 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/MetaFileTable.py | 860 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/WorkspaceCommon.py | 520 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/WorkspaceDatabase.py | 408 | ||||
| -rw-r--r-- | BaseTools/Source/Python/Workspace/__init__.py | 18 |
11 files changed, 9307 insertions, 9307 deletions
diff --git a/BaseTools/Source/Python/Workspace/BuildClassObject.py b/BaseTools/Source/Python/Workspace/BuildClassObject.py index ef873720f4..7e8e36526e 100644 --- a/BaseTools/Source/Python/Workspace/BuildClassObject.py +++ b/BaseTools/Source/Python/Workspace/BuildClassObject.py @@ -1,623 +1,623 @@ -## @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
-from CommonDataClass.DataClass import *
-import Common.EdkLogger as EdkLogger
-import Common.GlobalData as GlobalData
-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'])
-
-class BuildData(object):
- # 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,
- }
-
- def UpdatePcdTypeDict(self):
- if GlobalData.gCommandLineDefines.get(TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX,"FALSE").upper() == "TRUE":
- self._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_EX,
- MODEL_PCD_DYNAMIC_DEFAULT : TAB_PCDS_DYNAMIC_EX,
- MODEL_PCD_DYNAMIC_HII : TAB_PCDS_DYNAMIC_EX_HII,
- MODEL_PCD_DYNAMIC_VPD : TAB_PCDS_DYNAMIC_EX_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,
- }
-
- ## 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)
-
-## 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(BuildData):
- 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 = {}
-
-## 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(BuildData):
- def __init__(self):
- self.MetaFile = ''
- self.PackageName = ''
- self.Guid = ''
- self.Version = ''
-
- self.Protocols = {}
- self.Ppis = {}
- self.Guids = {}
- self.Includes = []
- self.LibraryClasses = {}
- self.Pcds = {}
-
-## 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 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(BuildData):
- def __init__(self):
- self.MetaFile = ''
- self.PlatformName = ''
- self.Guid = ''
- self.Version = ''
- self.DscSpecification = ''
- self.OutputDirectory = ''
- self.FlashDefinition = ''
- self.BuildNumber = ''
-
- self.SkuIds = {}
- self.Modules = []
- self.LibraryInstances = []
- self.LibraryClasses = {}
- self.Libraries = {}
- self.Pcds = {}
- self.BuildOptions = {}
+## @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 +from CommonDataClass.DataClass import * +import Common.EdkLogger as EdkLogger +import Common.GlobalData as GlobalData +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']) + +class BuildData(object): + # 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, + } + + def UpdatePcdTypeDict(self): + if GlobalData.gCommandLineDefines.get(TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX,"FALSE").upper() == "TRUE": + self._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_EX, + MODEL_PCD_DYNAMIC_DEFAULT : TAB_PCDS_DYNAMIC_EX, + MODEL_PCD_DYNAMIC_HII : TAB_PCDS_DYNAMIC_EX_HII, + MODEL_PCD_DYNAMIC_VPD : TAB_PCDS_DYNAMIC_EX_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, + } + + ## 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) + +## 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(BuildData): + 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 = {} + +## 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(BuildData): + def __init__(self): + self.MetaFile = '' + self.PackageName = '' + self.Guid = '' + self.Version = '' + + self.Protocols = {} + self.Ppis = {} + self.Guids = {} + self.Includes = [] + self.LibraryClasses = {} + self.Pcds = {} + +## 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 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(BuildData): + def __init__(self): + self.MetaFile = '' + self.PlatformName = '' + self.Guid = '' + self.Version = '' + self.DscSpecification = '' + self.OutputDirectory = '' + self.FlashDefinition = '' + self.BuildNumber = '' + + self.SkuIds = {} + self.Modules = [] + self.LibraryInstances = [] + self.LibraryClasses = {} + self.Libraries = {} + self.Pcds = {} + self.BuildOptions = {} diff --git a/BaseTools/Source/Python/Workspace/DecBuildData.py b/BaseTools/Source/Python/Workspace/DecBuildData.py index eeb7c490ac..9289e969fb 100644 --- a/BaseTools/Source/Python/Workspace/DecBuildData.py +++ b/BaseTools/Source/Python/Workspace/DecBuildData.py @@ -1,461 +1,461 @@ -## @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 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()
- self.UpdatePcdTypeDict()
-
- ## 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
+## @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 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() + self.UpdatePcdTypeDict() + + ## 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/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py index 5df184f9c8..c42db4bb9a 100644 --- a/BaseTools/Source/Python/Workspace/DscBuildData.py +++ b/BaseTools/Source/Python/Workspace/DscBuildData.py @@ -1,3672 +1,3672 @@ -## @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,gDefaultTargetTxtFile
-from Common.ToolDefClassObject import ToolDefDict,gDefaultToolsDefFile
-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
-import json
-import shutil
-
-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'
-StructuredPcdsDataName = 'StructuredPcdsData.json'
-
-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 = 'CFLAGS += -Wno-pointer-to-int-cast -Wno-unused-variable '
-PcdMakefileEnd = r'''
-!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common
-!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app
-'''
-
-AppTarget = '''
-all: $(APPFILE)
-$(APPLICATION): $(OBJECTS)
-$(APPFILE): $(APPLICATION)
-%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(r'^[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 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)
- self.UpdatePcdTypeDict()
- @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_AUTHENTICATED_VARIABLE_STORE:
- if TAB_DSC_DEFINES_VPD_AUTHENTICATED_VARIABLE_STORE not in gCommandLineDefines:
- gCommandLineDefines[TAB_DSC_DEFINES_VPD_AUTHENTICATED_VARIABLE_STORE] = Record[2].strip()
-
- 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 == TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX:
- if TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX not in gCommandLineDefines:
- gCommandLineDefines[TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX] = Record[2].strip()
- 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]
- GlobalData.gPlatformFinalPcds[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])
- flexisbale_size_statement_cache = set()
- 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:
- fieldinfo = tuple(FieldList[FieldName])
- if fieldinfo in flexisbale_size_statement_cache:
- continue
- flexisbale_size_statement_cache.add(fieldinfo)
- 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 GetStructurePcdSet (self, OutputValueFile):
- if not os.path.isfile(OutputValueFile):
- EdkLogger.error("GetStructurePcdSet", FILE_NOT_FOUND, "Output.txt doesn't exist", ExtraData=OutputValueFile)
- return []
- File = open (OutputValueFile, 'r')
- FileBuffer = File.readlines()
- File.close()
-
- #start update structure pcd final value
- 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
-
- def GetBuildOptionsValueList(self):
- 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)
- return CC_FLAGS
-
-
- def GenerateByteArrayValue (self, StructuredPcds):
- #
- # Generate/Compile/Run C application to determine if there are any flexible array members
- #
- if not StructuredPcds:
- return
-
- StructuredPcdsData = {}
- StoredStructuredPcdObjectPaths = {}
- SkipPcdValueInit = False
-
- CC_FLAGS = self.GetBuildOptionsValueList()
-
- for PcdName in StructuredPcds:
- Pcd = StructuredPcds[PcdName]
- TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName
- TokenCName = Pcd.TokenCName
-
- # Create a key using TokenSpaceGuidCName and TokenCName
- StructuredPcdsData[f"{TokenSpaceGuidCName}_{TokenCName}"] = {
- "DefaultValueFromDec": Pcd.DefaultValueFromDec,
- "DefaultValues": Pcd.DefaultValues,
- "PcdFieldValueFromComm": Pcd.PcdFieldValueFromComm,
- "PcdFieldValueFromFdf": Pcd.PcdFieldValueFromFdf,
- "DefaultFromDSC": Pcd.DefaultFromDSC,
- "PcdFiledValueFromDscComponent": Pcd.PcdFiledValueFromDscComponent
- }
-
- # Store the CC Flags
- StructuredPcdsData["CC_FLAGS"] = CC_FLAGS
- #
- # If the output path doesn't exists then create it
- #
- if not os.path.exists(self.OutputPath):
- os.makedirs(self.OutputPath)
-
- StructuredPcdsDataPath = os.path.join(self.OutputPath, self._Arch, StructuredPcdsDataName)
- PcdRecordOutputValueFile = os.path.join(self.OutputPath, self._Arch, 'Output.txt')
-
- if not os.path.exists(os.path.dirname(StructuredPcdsDataPath)):
- os.makedirs(os.path.dirname(StructuredPcdsDataPath))
- #
- # Check if the StructuredPcdsData.json exists or not
- # if exits then it might be a incremental build then check if the StructuredPcdsData has been changed or not.
- # if changed then proceed further, if not changed then return the stored data from earlier build
- #
- if os.path.isfile(StructuredPcdsDataPath):
- with open(StructuredPcdsDataPath, 'r') as file:
- StoredStructuredPcdsData = json.load(file)
- # OBJECTS will have the modified time, which needs to be checked later
- StoredStructuredPcdObjectPaths = StoredStructuredPcdsData.pop("OBJECTS", {})
-
- if StructuredPcdsData == StoredStructuredPcdsData:
- SkipPcdValueInit = True
- for filename, file_mtime in StoredStructuredPcdObjectPaths.items():
- f_mtime = os.path.getmtime(filename)
- #
- # check if the include_file are modified or not,
- # if modified then generate the PcdValueInit
- #
- if f_mtime != file_mtime:
- SkipPcdValueInit = False
- break
-
- if SkipPcdValueInit:
- return self.GetStructurePcdSet(PcdRecordOutputValueFile)
-
- 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'
-
- 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'
-
- MakeApp += CC_FLAGS
-
- if sys.platform == "win32":
- MakeApp = MakeApp + PcdMakefileEnd
- MakeApp = MakeApp + AppTarget % ("""\tcopy $(APPLICATION) $(APPFILE) /y """)
- else:
- MakeApp = MakeApp + AppTarget % ("""\tcp -p $(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)
- StructuredPcdsData["OBJECTS"] = {}
- for include_file in IncFileList:
- StructuredPcdsData["OBJECTS"][include_file] = os.path.getmtime(include_file)
- 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 -p -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%s\n' % (Command, StdOut, StdErr))
-
- #
- # In 1st build create the StructuredPcdsData.json
- # update the record as PCD Input has been changed if its incremental build
- #
- with open(StructuredPcdsDataPath, 'w') as file:
- json.dump(StructuredPcdsData, file, indent=2)
-
- # Copy update output file for each Arch
- shutil.copyfile(OutputValueFile, PcdRecordOutputValueFile)
-
- #start update structure pcd final value
- return self.GetStructurePcdSet(OutputValueFile)
-
- @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, gDefaultTargetTxtFile))
- if os.path.isfile(BuildConfigurationFile) == True:
- ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
- if ToolDefinitionFile == '':
- ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', gDefaultToolsDefFile))
- 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
+## @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,gDefaultTargetTxtFile +from Common.ToolDefClassObject import ToolDefDict,gDefaultToolsDefFile +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 +import json +import shutil + +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' +StructuredPcdsDataName = 'StructuredPcdsData.json' + +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 = 'CFLAGS += -Wno-pointer-to-int-cast -Wno-unused-variable ' +PcdMakefileEnd = r''' +!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common +!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app +''' + +AppTarget = ''' +all: $(APPFILE) +$(APPLICATION): $(OBJECTS) +$(APPFILE): $(APPLICATION) +%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(r'^[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 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) + self.UpdatePcdTypeDict() + @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_AUTHENTICATED_VARIABLE_STORE: + if TAB_DSC_DEFINES_VPD_AUTHENTICATED_VARIABLE_STORE not in gCommandLineDefines: + gCommandLineDefines[TAB_DSC_DEFINES_VPD_AUTHENTICATED_VARIABLE_STORE] = Record[2].strip() + + 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 == TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX: + if TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX not in gCommandLineDefines: + gCommandLineDefines[TAB_DSC_DEFINES_PCD_DYNAMIC_AS_DYNAMICEX] = Record[2].strip() + 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] + GlobalData.gPlatformFinalPcds[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]) + flexisbale_size_statement_cache = set() + 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: + fieldinfo = tuple(FieldList[FieldName]) + if fieldinfo in flexisbale_size_statement_cache: + continue + flexisbale_size_statement_cache.add(fieldinfo) + 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 GetStructurePcdSet (self, OutputValueFile): + if not os.path.isfile(OutputValueFile): + EdkLogger.error("GetStructurePcdSet", FILE_NOT_FOUND, "Output.txt doesn't exist", ExtraData=OutputValueFile) + return [] + File = open (OutputValueFile, 'r') + FileBuffer = File.readlines() + File.close() + + #start update structure pcd final value + 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 + + def GetBuildOptionsValueList(self): + 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) + return CC_FLAGS + + + def GenerateByteArrayValue (self, StructuredPcds): + # + # Generate/Compile/Run C application to determine if there are any flexible array members + # + if not StructuredPcds: + return + + StructuredPcdsData = {} + StoredStructuredPcdObjectPaths = {} + SkipPcdValueInit = False + + CC_FLAGS = self.GetBuildOptionsValueList() + + for PcdName in StructuredPcds: + Pcd = StructuredPcds[PcdName] + TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName + TokenCName = Pcd.TokenCName + + # Create a key using TokenSpaceGuidCName and TokenCName + StructuredPcdsData[f"{TokenSpaceGuidCName}_{TokenCName}"] = { + "DefaultValueFromDec": Pcd.DefaultValueFromDec, + "DefaultValues": Pcd.DefaultValues, + "PcdFieldValueFromComm": Pcd.PcdFieldValueFromComm, + "PcdFieldValueFromFdf": Pcd.PcdFieldValueFromFdf, + "DefaultFromDSC": Pcd.DefaultFromDSC, + "PcdFiledValueFromDscComponent": Pcd.PcdFiledValueFromDscComponent + } + + # Store the CC Flags + StructuredPcdsData["CC_FLAGS"] = CC_FLAGS + # + # If the output path doesn't exists then create it + # + if not os.path.exists(self.OutputPath): + os.makedirs(self.OutputPath) + + StructuredPcdsDataPath = os.path.join(self.OutputPath, self._Arch, StructuredPcdsDataName) + PcdRecordOutputValueFile = os.path.join(self.OutputPath, self._Arch, 'Output.txt') + + if not os.path.exists(os.path.dirname(StructuredPcdsDataPath)): + os.makedirs(os.path.dirname(StructuredPcdsDataPath)) + # + # Check if the StructuredPcdsData.json exists or not + # if exits then it might be a incremental build then check if the StructuredPcdsData has been changed or not. + # if changed then proceed further, if not changed then return the stored data from earlier build + # + if os.path.isfile(StructuredPcdsDataPath): + with open(StructuredPcdsDataPath, 'r') as file: + StoredStructuredPcdsData = json.load(file) + # OBJECTS will have the modified time, which needs to be checked later + StoredStructuredPcdObjectPaths = StoredStructuredPcdsData.pop("OBJECTS", {}) + + if StructuredPcdsData == StoredStructuredPcdsData: + SkipPcdValueInit = True + for filename, file_mtime in StoredStructuredPcdObjectPaths.items(): + f_mtime = os.path.getmtime(filename) + # + # check if the include_file are modified or not, + # if modified then generate the PcdValueInit + # + if f_mtime != file_mtime: + SkipPcdValueInit = False + break + + if SkipPcdValueInit: + return self.GetStructurePcdSet(PcdRecordOutputValueFile) + + 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' + + 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' + + MakeApp += CC_FLAGS + + if sys.platform == "win32": + MakeApp = MakeApp + PcdMakefileEnd + MakeApp = MakeApp + AppTarget % ("""\tcopy $(APPLICATION) $(APPFILE) /y """) + else: + MakeApp = MakeApp + AppTarget % ("""\tcp -p $(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) + StructuredPcdsData["OBJECTS"] = {} + for include_file in IncFileList: + StructuredPcdsData["OBJECTS"][include_file] = os.path.getmtime(include_file) + 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 -p -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%s\n' % (Command, StdOut, StdErr)) + + # + # In 1st build create the StructuredPcdsData.json + # update the record as PCD Input has been changed if its incremental build + # + with open(StructuredPcdsDataPath, 'w') as file: + json.dump(StructuredPcdsData, file, indent=2) + + # Copy update output file for each Arch + shutil.copyfile(OutputValueFile, PcdRecordOutputValueFile) + + #start update structure pcd final value + return self.GetStructurePcdSet(OutputValueFile) + + @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, gDefaultTargetTxtFile)) + if os.path.isfile(BuildConfigurationFile) == True: + ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF] + if ToolDefinitionFile == '': + ToolDefinitionFile = os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', gDefaultToolsDefFile)) + 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/BaseTools/Source/Python/Workspace/InfBuildData.py b/BaseTools/Source/Python/Workspace/InfBuildData.py index e4ff1c6686..ce6d3fa744 100644 --- a/BaseTools/Source/Python/Workspace/InfBuildData.py +++ b/BaseTools/Source/Python/Workspace/InfBuildData.py @@ -1,1100 +1,1100 @@ -## @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
-from Common.Expression import ValueExpressionEx, PcdPattern
-
-## 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 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.UpdatePcdTypeDict()
- 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]
- # OptionsList := [TagName, ToolCode, FeatureFlag]
- OptionsList = ['', '', '']
- TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
- for Index in range(len(TokenList)):
- OptionsList[Index] = TokenList[Index]
- if OptionsList[2]:
- FeaturePcdExpression = self.CheckFeatureFlagPcd(OptionsList[2])
- if not FeaturePcdExpression:
- continue
- File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
- '', False, self._Arch, ToolChainFamily, '', OptionsList[0], OptionsList[1])
- # 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 CheckFeatureFlagPcd(self,Instance):
- Pcds = GlobalData.gPlatformFinalPcds.copy()
- if PcdPattern.search(Instance):
- PcdTuple = tuple(Instance.split('.')[::-1])
- if PcdTuple in self.Pcds:
- if not (self.Pcds[PcdTuple].Type == 'FeatureFlag' or self.Pcds[PcdTuple].Type == 'FixedAtBuild'):
- EdkLogger.error('build', FORMAT_INVALID,
- "\nFeatureFlagPcd must be defined in a [PcdsFeatureFlag] or [PcdsFixedAtBuild] section of Dsc or Dec file",
- File=str(self), ExtraData=Instance)
- if not Instance in Pcds:
- Pcds[Instance] = self.Pcds[PcdTuple].DefaultValue
- else: #if PcdTuple not in self.Pcds:
- EdkLogger.error('build', FORMAT_INVALID,
- "\nFeatureFlagPcd must be defined in [FeaturePcd] or [FixedPcd] of Inf file",
- File=str(self), ExtraData=Instance)
- if Instance in Pcds:
- if Pcds[Instance] == '0':
- return False
- elif Pcds[Instance] == '1':
- return True
- try:
- Value = ValueExpression(Instance, Pcds)()
- if Value == True:
- return True
- return False
- except:
- EdkLogger.warn('build', FORMAT_INVALID,"The FeatureFlagExpression cannot be evaluated", File=str(self), ExtraData=Instance)
- return False
- else:
- for Name, Guid in self.Pcds:
- if self.Pcds[(Name, Guid)].Type == 'FeatureFlag' or self.Pcds[(Name, Guid)].Type == 'FixedAtBuild':
- PcdFullName = '%s.%s' % (Guid, Name);
- if not PcdFullName in Pcds:
- Pcds[PcdFullName] = self.Pcds[(Name, Guid)].DefaultValue
- try:
- Value = ValueExpression(Instance, Pcds)()
- if Value == True:
- return True
- return False
- except:
- EdkLogger.warn('build', FORMAT_INVALID, "The FeatureFlagExpression cannot be evaluated", File=str(self), ExtraData=Instance)
- return False
-def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
- for Key in CopyFromDict:
- CopyToDict[Key].extend(CopyFromDict[Key])
+## @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 +from Common.Expression import ValueExpressionEx, PcdPattern + +## 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 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.UpdatePcdTypeDict() + 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] + # OptionsList := [TagName, ToolCode, FeatureFlag] + OptionsList = ['', '', ''] + TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT) + for Index in range(len(TokenList)): + OptionsList[Index] = TokenList[Index] + if OptionsList[2]: + FeaturePcdExpression = self.CheckFeatureFlagPcd(OptionsList[2]) + if not FeaturePcdExpression: + continue + File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '', + '', False, self._Arch, ToolChainFamily, '', OptionsList[0], OptionsList[1]) + # 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 CheckFeatureFlagPcd(self,Instance): + Pcds = GlobalData.gPlatformFinalPcds.copy() + if PcdPattern.search(Instance): + PcdTuple = tuple(Instance.split('.')[::-1]) + if PcdTuple in self.Pcds: + if not (self.Pcds[PcdTuple].Type == 'FeatureFlag' or self.Pcds[PcdTuple].Type == 'FixedAtBuild'): + EdkLogger.error('build', FORMAT_INVALID, + "\nFeatureFlagPcd must be defined in a [PcdsFeatureFlag] or [PcdsFixedAtBuild] section of Dsc or Dec file", + File=str(self), ExtraData=Instance) + if not Instance in Pcds: + Pcds[Instance] = self.Pcds[PcdTuple].DefaultValue + else: #if PcdTuple not in self.Pcds: + EdkLogger.error('build', FORMAT_INVALID, + "\nFeatureFlagPcd must be defined in [FeaturePcd] or [FixedPcd] of Inf file", + File=str(self), ExtraData=Instance) + if Instance in Pcds: + if Pcds[Instance] == '0': + return False + elif Pcds[Instance] == '1': + return True + try: + Value = ValueExpression(Instance, Pcds)() + if Value == True: + return True + return False + except: + EdkLogger.warn('build', FORMAT_INVALID,"The FeatureFlagExpression cannot be evaluated", File=str(self), ExtraData=Instance) + return False + else: + for Name, Guid in self.Pcds: + if self.Pcds[(Name, Guid)].Type == 'FeatureFlag' or self.Pcds[(Name, Guid)].Type == 'FixedAtBuild': + PcdFullName = '%s.%s' % (Guid, Name); + if not PcdFullName in Pcds: + Pcds[PcdFullName] = self.Pcds[(Name, Guid)].DefaultValue + try: + Value = ValueExpression(Instance, Pcds)() + if Value == True: + return True + return False + except: + EdkLogger.warn('build', FORMAT_INVALID, "The FeatureFlagExpression cannot be evaluated", File=str(self), ExtraData=Instance) + return False +def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict): + for Key in CopyFromDict: + CopyToDict[Key].extend(CopyFromDict[Key]) diff --git a/BaseTools/Source/Python/Workspace/MetaDataTable.py b/BaseTools/Source/Python/Workspace/MetaDataTable.py index a20bd14784..22f8c7fe22 100644 --- a/BaseTools/Source/Python/Workspace/MetaDataTable.py +++ b/BaseTools/Source/Python/Workspace/MetaDataTable.py @@ -1,306 +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
-
+## @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/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py b/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py index 3737ae3511..333d56f3d7 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py +++ b/BaseTools/Source/Python/Workspace/MetaFileCommentParser.py @@ -1,45 +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)
- )
+## @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/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py index 73a1654edb..5da5749bce 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileParser.py +++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py @@ -1,2197 +1,2197 @@ -## @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)
- # Let TokenList[2] be TagName|ToolCode|FeatureFlag
- if len(TokenList) > 3:
- for extraToken in range(3, len(TokenList)):
- TokenList[2] = TokenList[2] + '|' + TokenList[extraToken]
- 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(r',[\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
-
+## @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) + # Let TokenList[2] be TagName|ToolCode|FeatureFlag + if len(TokenList) > 3: + for extraToken in range(3, len(TokenList)): + TokenList[2] = TokenList[2] + '|' + TokenList[extraToken] + 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(r',[\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/BaseTools/Source/Python/Workspace/MetaFileTable.py b/BaseTools/Source/Python/Workspace/MetaFileTable.py index bebf9062e8..7635d89332 100644 --- a/BaseTools/Source/Python/Workspace/MetaFileTable.py +++ b/BaseTools/Source/Python/Workspace/MetaFileTable.py @@ -1,430 +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
-
+## @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/BaseTools/Source/Python/Workspace/WorkspaceCommon.py b/BaseTools/Source/Python/Workspace/WorkspaceCommon.py index 6ad7a3b940..e6fc44fc35 100644 --- a/BaseTools/Source/Python/Workspace/WorkspaceCommon.py +++ b/BaseTools/Source/Python/Workspace/WorkspaceCommon.py @@ -1,260 +1,260 @@ -## @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 LibraryClass[4:].isdigit() 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") and LibraryClass[4:].isdigit():
- 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.startswith("NULL") and LibraryClassName[4:].isdigit() and bool(M.LibraryClass):
- continue
- 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") and LibraryClassName[4:].isdigit():
- 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 library instance [%s] which is consumed by module [%s]" \
- % (str(M), 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
+## @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 LibraryClass[4:].isdigit() 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") and LibraryClass[4:].isdigit(): + 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.startswith("NULL") and LibraryClassName[4:].isdigit() and bool(M.LibraryClass): + continue + 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") and LibraryClassName[4:].isdigit(): + 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 library instance [%s] which is consumed by module [%s]" \ + % (str(M), 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/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py index d955c78b25..0764e27243 100644 --- a/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py +++ b/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py @@ -1,204 +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
-
+## @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/BaseTools/Source/Python/Workspace/__init__.py b/BaseTools/Source/Python/Workspace/__init__.py index 85ae9937c4..4183055e28 100644 --- a/BaseTools/Source/Python/Workspace/__init__.py +++ b/BaseTools/Source/Python/Workspace/__init__.py @@ -1,9 +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
-#
+## @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 +# |
