BaseTools: Support Structure PCD value assignment in DEC/DSC

https://bugzilla.tianocore.org/show_bug.cgi?id=542
This is pure BaseTools enhancement to support PCD with one structure.
User can specify PCD value based on its structure field.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
This commit is contained in:
Liming Gao
2017-11-24 14:30:11 +08:00
parent 309e37a229
commit ae7b6df816
15 changed files with 3796 additions and 2975 deletions

View File

@@ -16,6 +16,7 @@ import Common.LongFilePathOs as os
from Common.Misc import sdict
from Common.Misc import RealPath2
from Common.BuildToolError import *
import collections
## PcdClassObject
#
@@ -106,6 +107,63 @@ class PcdClassObject(object):
def __hash__(self):
return hash((self.TokenCName, self.TokenSpaceGuidCName))
class StructurePcd(PcdClassObject):
def __init__(self, StructuredPcdIncludeFile="", Packages=None, Name=None, Guid=None, Type=None, DatumType=None, Value=None, Token=None, MaxDatumSize=None, SkuInfoList={}, IsOverrided=False, GuidValue=None, validateranges=[], validlists=[], expressions=[]):
super(StructurePcd, self).__init__(Name, Guid, Type, DatumType, Value, Token, MaxDatumSize, SkuInfoList, IsOverrided, GuidValue, validateranges, validlists, expressions)
self.StructuredPcdIncludeFile = StructuredPcdIncludeFile
self.PackageDecs = Packages
self.DefaultStoreName = ['STANDARD']
self.DefaultValues = collections.OrderedDict({})
self.PcdMode = None
self.SkuOverrideValues = collections.OrderedDict({})
self.FlexibleFieldName = None
def __repr__(self):
return self.TypeName
def AddDefaultValue (self, FieldName, Value, FileName="", LineNo=0):
self.DefaultValues[FieldName] = [Value.strip(), FileName, LineNo]
return self.DefaultValues[FieldName]
def AddOverrideValue (self, FieldName, Value, SkuName, FileName="", LineNo=0):
if SkuName not in self.SkuOverrideValues:
self.SkuOverrideValues[SkuName] = collections.OrderedDict({})
self.SkuOverrideValues[SkuName][FieldName] = [Value.strip(), FileName, LineNo]
return self.SkuOverrideValues[SkuName][FieldName]
def SetPcdMode (self, PcdMode):
self.PcdMode = PcdMode
def SetFlexibleFieldName (self, FlexibleFieldName):
self.FlexibleFieldName = FlexibleFieldName
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
if type(PcdObject) is 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.DefaultFromDSC=None
self.OverrideValues = PcdObject.SkuOverrideValues if PcdObject.SkuOverrideValues else self.SkuOverrideValues
self.FlexibleFieldName = PcdObject.FlexibleFieldName if PcdObject.FlexibleFieldName else self.FlexibleFieldName
## LibraryClassObject
#
# This Class defines LibraryClassObject used in BuildDatabase

View File

@@ -0,0 +1,462 @@
## @file
# This file is used to create a database used by build tool
#
# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
from Common.String import *
from Common.DataType import *
from Common.Misc import *
from types import *
from Workspace.BuildClassObject import PackageBuildClassObject, StructurePcd, PcdClassObject
## Platform build information from DEC file
#
# This class is used to retrieve information stored in database and convert them
# into PackageBuildClassObject form for easier use for AutoGen.
#
class DecBuildData(PackageBuildClassObject):
# dict used to convert PCD type in database to string used by build tool
_PCD_TYPE_STRING_ = {
MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
MODEL_PCD_DYNAMIC : "Dynamic",
MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
MODEL_PCD_DYNAMIC_HII : "DynamicHii",
MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
MODEL_PCD_DYNAMIC_EX : "DynamicEx",
MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
}
# 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='COMMON', Target=None, Toolchain=None):
self.MetaFile = File
self._PackageDir = File.Dir
self._RawData = RawData
self._Bdb = BuildDataBase
self._Arch = Arch
self._Target = Target
self._Toolchain = Toolchain
self._Clear()
## XXX[key] = value
def __setitem__(self, key, value):
self.__dict__[self._PROPERTY_[key]] = value
## value = XXX[key]
def __getitem__(self, key):
return self.__dict__[self._PROPERTY_[key]]
## "in" test support
def __contains__(self, key):
return key in self._PROPERTY_
## Set all internal used members of DecBuildData to None
def _Clear(self):
self._Header = None
self._PackageName = None
self._Guid = None
self._Version = None
self._PkgUniFile = None
self._Protocols = None
self._Ppis = None
self._Guids = None
self._Includes = None
self._LibraryClasses = None
self._Pcds = None
self.__Macros = None
self._PrivateProtocols = None
self._PrivatePpis = None
self._PrivateGuids = None
self._PrivateIncludes = None
## Get current effective macros
def _GetMacros(self):
if self.__Macros == None:
self.__Macros = {}
self.__Macros.update(GlobalData.gGlobalDefines)
return self.__Macros
## Get architecture
def _GetArch(self):
return self._Arch
## Set architecture
#
# Changing the default ARCH to another may affect all other information
# because all information in a platform may be ARCH-related. That's
# why we need to clear all internal used members, in order to cause all
# information to be re-retrieved.
#
# @param Value The value of ARCH
#
def _SetArch(self, Value):
if self._Arch == Value:
return
self._Arch = Value
self._Clear()
## Retrieve all information in [Defines] section
#
# (Retriving 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
def _GetPackageName(self):
if self._PackageName == None:
if self._Header == None:
self._GetHeaderInfo()
if self._PackageName == None:
EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
return self._PackageName
## Retrieve file guid
def _GetFileGuid(self):
if self._Guid == None:
if self._Header == None:
self._GetHeaderInfo()
if self._Guid == None:
EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
return self._Guid
## Retrieve package version
def _GetVersion(self):
if self._Version == None:
if self._Header == None:
self._GetHeaderInfo()
if self._Version == None:
self._Version = ''
return self._Version
## Retrieve protocol definitions (name/value pairs)
def _GetProtocol(self):
if self._Protocols == None:
#
# tdict is a special kind of dict, used for selecting correct
# protocol defition 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 sdict to keep the order
self._Protocols = sdict()
self._PrivateProtocols = sdict()
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)
def _GetPpi(self):
if self._Ppis == None:
#
# tdict is a special kind of dict, used for selecting correct
# PPI defition 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 sdict to keep the order
self._Ppis = sdict()
self._PrivatePpis = sdict()
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)
def _GetGuid(self):
if self._Guids == None:
#
# tdict is a special kind of dict, used for selecting correct
# GUID defition 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 sdict to keep the order
self._Guids = sdict()
self._PrivateGuids = sdict()
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
def _GetInclude(self):
if self._Includes == None:
self._Includes = []
self._PrivateIncludes = []
PublicInclues = []
RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
Macros = self._Macros
Macros["EDK_SOURCE"] = GlobalData.gEcpSource
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)
return self._Includes
## Retrieve library class declarations (not used in build at present)
def _GetLibraryClass(self):
if self._LibraryClasses == 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 = sdict()
for LibraryClass in LibraryClassSet:
self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
return self._LibraryClasses
## Retrieve PCD declarations
def _GetPcds(self):
if self._Pcds == None:
self._Pcds = sdict()
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 ProcessStructurePcd(self, StructurePcdRawDataSet):
s_pcd_set = dict()
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 "<HeaderFiles>" in item.TokenCName:
struct_pcd.StructuredPcdIncludeFile = 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(".")
else:
struct_pcd.AddDefaultValue(item.TokenCName, item.DefaultValue,self.MetaFile.File,LineNo)
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 = sdict()
#
# tdict is a special kind of dict, used for selecting correct
# PCD declaration for given ARCH
#
PcdDict = tdict(True, 3)
# for summarizing PCD
PcdSet = set()
# 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)
PcdSet.add((PcdCName, TokenSpaceGuid))
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 == 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)
)
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
return Pcds
_Macros = property(_GetMacros)
Arch = property(_GetArch, _SetArch)
PackageName = property(_GetPackageName)
Guid = property(_GetFileGuid)
Version = property(_GetVersion)
Protocols = property(_GetProtocol)
Ppis = property(_GetPpi)
Guids = property(_GetGuid)
Includes = property(_GetInclude)
LibraryClasses = property(_GetLibraryClass)
Pcds = property(_GetPcds)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@ import Common.LongFilePathOs as os
import re
import time
import copy
import md5
import Common.EdkLogger as EdkLogger
import Common.GlobalData as GlobalData
@@ -1116,6 +1117,11 @@ class DscParser(MetaFileParser):
def _PcdParser(self):
TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
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]
if len(TokenList) == 2:
self._ValueList[2] = TokenList[1]
if self._ValueList[0] == '' or self._ValueList[1] == '':
@@ -1134,7 +1140,7 @@ class DscParser(MetaFileParser):
# Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
ValueList = GetSplitValueList(self._ValueList[2])
if len(ValueList) > 1 and ValueList[1] != TAB_VOID \
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)
@@ -1560,7 +1566,7 @@ class DscParser(MetaFileParser):
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:
if PcdValue and "." not in self._ValueList[0]:
try:
ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
except WrnExpression, Value:
@@ -1574,7 +1580,10 @@ class DscParser(MetaFileParser):
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
self._ValueList[2] = '|'.join(ValList)
try:
self._ValueList[2] = '|'.join(ValList)
except Exception:
print ValList
def __ProcessComponent(self):
self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
@@ -1655,6 +1664,10 @@ class DecParser(MetaFileParser):
self._AllPCDs = [] # Only for check duplicate PCD
self._AllPcdDict = {}
self._CurrentStructurePcdName = ""
self._include_flag = False
self._package_flag = False
## Parser starter
def Start(self):
Content = ''
@@ -1847,105 +1860,143 @@ class DecParser(MetaFileParser):
#
@ParseMacro
def _PcdParser(self):
TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
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)
if self._CurrentStructurePcdName:
self._ValueList[0] = self._CurrentStructurePcdName
if "|" not in self._CurrentLine:
if "<HeaderFiles>" == self._CurrentLine:
self._include_flag = True
self._ValueList = None
return
if "<Packages>" == self._CurrentLine:
self._package_flag = True
self._ValueList = None
return
if self._include_flag:
self._ValueList[1] = "<HeaderFiles>_" + md5.new(self._CurrentLine).hexdigest()
self._ValueList[2] = self._CurrentLine
self._include_flag = False
if self._package_flag and "}" != self._CurrentLine:
self._ValueList[1] = "<Packages>_" + md5.new(self._CurrentLine).hexdigest()
self._ValueList[2] = self._CurrentLine
if self._CurrentLine == "}":
self._package_flag = False
self._ValueList = None
return
else:
PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)
PcdNames = PcdTockens[0].split(TAB_SPLIT)
if len(PcdNames) == 2:
self._CurrentStructurePcdName = ""
else:
self._ValueList[1] = PcdNames[2]
self._ValueList[2] = PcdTockens[1]
if not self._CurrentStructurePcdName:
TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
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])
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])
# 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)
# 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:
ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
except WrnExpression, Value:
ValueList[0] = Value.result
PcdValue = ValueList[0]
if PcdValue:
try:
ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
except WrnExpression, Value:
ValueList[0] = Value.result
if ValueList[0] == 'True':
ValueList[0] = '1'
if ValueList[0] == 'False':
ValueList[0] = '0'
if ValueList[0] == 'True':
ValueList[0] = '1'
if ValueList[0] == 'False':
ValueList[0] = '0'
# 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)
# 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 ValueList[0] in ['True', 'true', 'TRUE']:
ValueList[0] = '1'
elif ValueList[0] in ['False', 'false', 'FALSE']:
ValueList[0] = '0'
if Cause == "StructurePcd":
self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])
self._ValueList[0] = self._CurrentStructurePcdName
self._ValueList[1] = ValueList[1].strip()
# 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]
if ValueList[0] in ['True', 'true', 'TRUE']:
ValueList[0] = '1'
elif ValueList[0] in ['False', 'false', 'FALSE']:
ValueList[0] = '0'
self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
# 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,

View File

@@ -15,6 +15,7 @@ from Common.Misc import sdict
from Common.DataType import SUP_MODULE_USER_DEFINED
from BuildClassObject import LibraryClassObject
import Common.GlobalData as GlobalData
from Workspace.BuildClassObject import StructurePcd
## Get all packages from platform for specified arch, target and toolchain
#

File diff suppressed because it is too large Load Diff