mirror of https://github.com/acidanthera/audk.git
BaseTools/Build: Add SDL support
1.BaseTool add ATTRIBUTE (+/-RT, RO) support in PCD declaration in DSC file 2.BaseTool collect valid PCD value in DEC file and generate data base for runtime sanity check 3.BaseTool support SetPcd error. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: "Bob Feng" <bob.c.feng@intel.com> Reviewed-by: "Chen, Hesheng" <hesheng.chen@intel.com> Reviewed-by: "Liu, Yingke D" <yingke.d.liu@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17158 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
b7668ccee9
commit
82a6a9605c
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# Generate AutoGen.h, AutoGen.c and *.depex files
|
||||
#
|
||||
# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -1813,6 +1813,9 @@ class PlatformAutoGen(AutoGen):
|
|||
if not IsValid:
|
||||
EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
|
||||
ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName))
|
||||
ToPcd.validateranges = FromPcd.validateranges
|
||||
ToPcd.validlists = FromPcd.validlists
|
||||
ToPcd.expressions = FromPcd.expressions
|
||||
|
||||
if ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:
|
||||
EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# Routines for generating AutoGen.h and AutoGen.c
|
||||
#
|
||||
# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -786,6 +786,7 @@ def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd):
|
|||
DatumSizeLib = gDatumSizeStringDatabaseLib[Pcd.DatumType]
|
||||
GetModeName = '_PCD_GET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName
|
||||
SetModeName = '_PCD_SET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_' + Pcd.TokenCName
|
||||
SetModeStatusName = '_PCD_SET_MODE_' + gDatumSizeStringDatabaseH[Pcd.DatumType] + '_S_' + Pcd.TokenCName
|
||||
|
||||
PcdExCNameList = []
|
||||
if Pcd.Type in gDynamicExPcd:
|
||||
|
@ -805,21 +806,27 @@ def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd):
|
|||
AutoGenH.Append('// #define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
if Pcd.DatumType == 'VOID*':
|
||||
AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%sS(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('// #define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('// #define %s(Value) LibPcdSetEx%sS(&%s, %s, (Value))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('#define %s %s\n' % (PcdTokenName, PcdExTokenName))
|
||||
AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
if Pcd.DatumType == 'VOID*':
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%sS(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSetEx%sS(&%s, %s, (Value))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
elif Pcd.Type in gDynamicPcd:
|
||||
AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName))
|
||||
if Pcd.DatumType == 'VOID*':
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%sS(%s, (SizeOfBuffer), (Buffer))\n' % (SetModeStatusName, DatumSizeLib, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSet%sS(%s, (Value))\n' % (SetModeStatusName, DatumSizeLib, PcdTokenName))
|
||||
else:
|
||||
PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[Pcd.Type] + '_' + Pcd.TokenCName
|
||||
Const = 'const'
|
||||
|
@ -963,8 +970,10 @@ def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd):
|
|||
if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
|
||||
if Pcd.DatumType == 'VOID*':
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPatchPcdSetPtr(_gPcd_BinaryPatch_%s, (UINTN)_PCD_PATCHABLE_%s_SIZE, (SizeOfBuffer), (Buffer))\n' % (SetModeName, Pcd.TokenCName, Pcd.TokenCName))
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPatchPcdSetPtrS(_gPcd_BinaryPatch_%s, (UINTN)_PCD_PATCHABLE_%s_SIZE, (SizeOfBuffer), (Buffer))\n' % (SetModeStatusName, Pcd.TokenCName, Pcd.TokenCName))
|
||||
else:
|
||||
AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName))
|
||||
AutoGenH.Append('#define %s(Value) ((%s = (Value)), RETURN_SUCCESS) \n' % (SetModeStatusName, PcdVariableName))
|
||||
else:
|
||||
AutoGenH.Append('//#define %s ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD\n' % SetModeName)
|
||||
|
||||
|
@ -1018,6 +1027,7 @@ def CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd):
|
|||
DatumSizeLib= gDatumSizeStringDatabaseLib[DatumType]
|
||||
GetModeName = '_PCD_GET_MODE_' + DatumSize + '_' + TokenCName
|
||||
SetModeName = '_PCD_SET_MODE_' + DatumSize + '_' + TokenCName
|
||||
SetModeStatusName = '_PCD_SET_MODE_' + DatumSize + '_S_' + TokenCName
|
||||
|
||||
Type = ''
|
||||
Array = ''
|
||||
|
@ -1046,28 +1056,35 @@ def CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd):
|
|||
AutoGenH.Append('// #define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
if Pcd.DatumType == 'VOID*':
|
||||
AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('// #define %s(SizeOfBuffer, Buffer) LibPcdSetEx%sS(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('// #define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('// #define %s(Value) LibPcdSetEx%sS(&%s, %s, (Value))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('#define %s %s\n' % (PcdTokenName, PcdExTokenName))
|
||||
AutoGenH.Append('#define %s LibPcdGetEx%s(&%s, %s)\n' % (GetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
if Pcd.DatumType == 'VOID*':
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%s(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSetEx%sS(&%s, %s, (SizeOfBuffer), (Buffer))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSetEx%s(&%s, %s, (Value))\n' % (SetModeName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSetEx%sS(&%s, %s, (Value))\n' % (SetModeStatusName, DatumSizeLib, Pcd.TokenSpaceGuidCName, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('#define _PCD_TOKEN_%s %dU\n' % (TokenCName, TokenNumber))
|
||||
if PcdItemType in gDynamicPcd:
|
||||
AutoGenH.Append('#define %s LibPcdGet%s(%s)\n' % (GetModeName, DatumSizeLib, PcdTokenName))
|
||||
if DatumType == 'VOID*':
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%s(%s, (SizeOfBuffer), (Buffer))\n' %(SetModeName, DatumSizeLib, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(SizeOfBuffer, Buffer) LibPcdSet%sS(%s, (SizeOfBuffer), (Buffer))\n' % (SetModeStatusName, DatumSizeLib, PcdTokenName))
|
||||
else:
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSet%s(%s, (Value))\n' % (SetModeName, DatumSizeLib, PcdTokenName))
|
||||
AutoGenH.Append('#define %s(Value) LibPcdSet%sS(%s, (Value))\n' % (SetModeStatusName, DatumSizeLib, PcdTokenName))
|
||||
if PcdItemType == TAB_PCDS_PATCHABLE_IN_MODULE:
|
||||
PcdVariableName = '_gPcd_' + gItemTypeStringDatabase[TAB_PCDS_PATCHABLE_IN_MODULE] + '_' + TokenCName
|
||||
AutoGenH.Append('extern volatile %s _gPcd_BinaryPatch_%s%s;\n' %(DatumType, TokenCName, Array) )
|
||||
AutoGenH.Append('#define %s %s_gPcd_BinaryPatch_%s\n' %(GetModeName, Type, TokenCName))
|
||||
AutoGenH.Append('#define %s(Value) (%s = (Value))\n' % (SetModeName, PcdVariableName))
|
||||
AutoGenH.Append('#define %s(Value) ((%s = (Value)), RETURN_SUCCESS)\n' % (SetModeStatusName, PcdVariableName))
|
||||
if PcdItemType == TAB_PCDS_FIXED_AT_BUILD or PcdItemType == TAB_PCDS_FEATURE_FLAG:
|
||||
key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# Routines for generating Pcd Database
|
||||
#
|
||||
# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -14,8 +14,12 @@ from StringIO import StringIO
|
|||
from Common.Misc import *
|
||||
from Common.String import StringToArray
|
||||
from struct import pack
|
||||
from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER
|
||||
from ValidCheckingInfoObject import VAR_CHECK_PCD_VARIABLE_TAB
|
||||
from ValidCheckingInfoObject import VAR_VALID_OBJECT_FACTORY
|
||||
from Common.VariableAttributes import VariableAttributes
|
||||
|
||||
DATABASE_VERSION = 4
|
||||
DATABASE_VERSION = 5
|
||||
|
||||
gPcdDatabaseAutoGenC = TemplateString("""
|
||||
//
|
||||
|
@ -444,7 +448,7 @@ class DbVariableTableItemList (DbComItemList):
|
|||
RawDataList = []
|
||||
DbComItemList.__init__(self, ItemSize, DataList, RawDataList)
|
||||
def PackData(self):
|
||||
PackStr = "=LLHH"
|
||||
PackStr = "=LLHHLHH"
|
||||
Buffer = ''
|
||||
for DataList in self.RawDataList:
|
||||
for Data in DataList:
|
||||
|
@ -452,7 +456,10 @@ class DbVariableTableItemList (DbComItemList):
|
|||
GetIntegerValue(Data[0]),
|
||||
GetIntegerValue(Data[1]),
|
||||
GetIntegerValue(Data[2]),
|
||||
GetIntegerValue(Data[3]))
|
||||
GetIntegerValue(Data[3]),
|
||||
GetIntegerValue(Data[4]),
|
||||
GetIntegerValue(Data[5]),
|
||||
GetIntegerValue(0))
|
||||
return Buffer
|
||||
|
||||
class DbStringHeadTableItemList(DbItemList):
|
||||
|
@ -712,7 +719,7 @@ def BuildExDataBase(Dict):
|
|||
# DbItemList to DbStringHeadTableItemList
|
||||
DbStringHeadValue = DbStringHeadTableItemList(4, RawDataList = StringHeadValue)
|
||||
VariableTable = Dict['VARIABLE_DB_VALUE']
|
||||
DbVariableTable = DbVariableTableItemList(12, RawDataList = VariableTable)
|
||||
DbVariableTable = DbVariableTableItemList(20, RawDataList = VariableTable)
|
||||
NumberOfSkuEnabledPcd = GetIntegerValue(Dict['SKU_HEAD_SIZE'])
|
||||
Dict['SKUHEAD_TABLE_VALUE'] = [(0,0) for i in xrange(NumberOfSkuEnabledPcd)]
|
||||
SkuTable = Dict['SKUHEAD_TABLE_VALUE'] # Generated later
|
||||
|
@ -852,7 +859,7 @@ def BuildExDataBase(Dict):
|
|||
for VariableEntries in VariableTable:
|
||||
skuindex = 0
|
||||
for VariableEntryPerSku in VariableEntries:
|
||||
(VariableHeadGuidIndex, VariableHeadStringIndex, SKUVariableOffset, VariableOffset, VariableRefTable) = VariableEntryPerSku[:]
|
||||
(VariableHeadGuidIndex, VariableHeadStringIndex, SKUVariableOffset, VariableOffset, VariableRefTable, VariableAttribute) = VariableEntryPerSku[:]
|
||||
DbIndex = 0
|
||||
DbOffset = FixedHeaderLen
|
||||
for DbIndex in xrange(len(DbTotal)):
|
||||
|
@ -867,8 +874,8 @@ def BuildExDataBase(Dict):
|
|||
skuindex += 1
|
||||
if DbIndex >= InitTableNum:
|
||||
assert(False)
|
||||
|
||||
VariableEntryPerSku[:] = (VariableHeadStringIndex, DbOffset, VariableHeadGuidIndex, SKUVariableOffset)
|
||||
VarAttr, VarProp = VariableAttributes.GetVarAttributes(VariableAttribute)
|
||||
VariableEntryPerSku[:] = (VariableHeadStringIndex, DbOffset, VariableHeadGuidIndex, SKUVariableOffset, VarAttr, VarProp)
|
||||
|
||||
# calculate various table offset now
|
||||
DbTotalLength = FixedHeaderLen
|
||||
|
@ -1113,6 +1120,7 @@ def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
|
|||
NumberOfSizeItems = 0
|
||||
NumberOfSkuEnabledPcd = 0
|
||||
GuidList = []
|
||||
VarCheckTab = VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER()
|
||||
i = 0
|
||||
ReorderedDynPcdList = GetOrderedDynamicPcdList(Platform.DynamicPcdList, Platform.PcdTokenNumber)
|
||||
for Pcd in ReorderedDynPcdList:
|
||||
|
@ -1182,6 +1190,29 @@ def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
|
|||
SkuIdIndex += 1
|
||||
|
||||
if len(Sku.VariableName) > 0:
|
||||
VariableGuidStructure = Sku.VariableGuidValue
|
||||
VariableGuid = GuidStructureStringToGuidValueName(VariableGuidStructure)
|
||||
if Platform.Platform.VarCheckFlag:
|
||||
var_check_obj = VAR_CHECK_PCD_VARIABLE_TAB(VariableGuidStructure, StringToArray(Sku.VariableName))
|
||||
try:
|
||||
var_check_obj.push_back(VAR_VALID_OBJECT_FACTORY.Get_valid_object(Pcd, Sku.VariableOffset))
|
||||
VarAttr, _ = VariableAttributes.GetVarAttributes(Sku.VariableAttribute)
|
||||
var_check_obj.SetAttributes(VarAttr)
|
||||
var_check_obj.UpdateSize()
|
||||
VarCheckTab.push_back(var_check_obj)
|
||||
except Exception:
|
||||
ValidInfo = ''
|
||||
if Pcd.validateranges:
|
||||
ValidInfo = Pcd.validateranges[0]
|
||||
if Pcd.validlists:
|
||||
ValidInfo = Pcd.validlists[0]
|
||||
if ValidInfo:
|
||||
EdkLogger.error("build", PCD_VALIDATION_INFO_ERROR,
|
||||
"The PCD '%s.%s' Validation information defined in DEC file has incorrect format." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName),
|
||||
ExtraData = "[%s]" % str(ValidInfo))
|
||||
else:
|
||||
EdkLogger.error("build", PCD_VALIDATION_INFO_ERROR,
|
||||
"The PCD '%s.%s' Validation information defined in DEC file has incorrect format." % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
|
||||
Pcd.TokenTypeList += ['PCD_TYPE_HII']
|
||||
Pcd.InitString = 'INIT'
|
||||
# Store all variable names of one HII PCD under different SKU to stringTable
|
||||
|
@ -1215,8 +1246,6 @@ def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
|
|||
|
||||
VariableHeadStringIndex = VariableHeadList[SkuIdIndex - 2]
|
||||
# store VariableGuid to GuidTable and get the VariableHeadGuidIndex
|
||||
VariableGuidStructure = Sku.VariableGuidValue
|
||||
VariableGuid = GuidStructureStringToGuidValueName(VariableGuidStructure)
|
||||
|
||||
if VariableGuid not in GuidList:
|
||||
GuidList += [VariableGuid]
|
||||
|
@ -1268,7 +1297,7 @@ def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
|
|||
# the Pcd default value was filled before
|
||||
VariableOffset = len(Dict['VARDEF_DB_VALUE_' + Pcd.DatumType]) - 1
|
||||
VariableRefTable = Dict['VARDEF_DB_VALUE_' + Pcd.DatumType]
|
||||
VariableDbValueList.append([VariableHeadGuidIndex, VariableHeadStringIndex, Sku.VariableOffset, VariableOffset, VariableRefTable])
|
||||
VariableDbValueList.append([VariableHeadGuidIndex, VariableHeadStringIndex, Sku.VariableOffset, VariableOffset, VariableRefTable, Sku.VariableAttribute])
|
||||
|
||||
elif Sku.VpdOffset != '':
|
||||
Pcd.TokenTypeList += ['PCD_TYPE_VPD']
|
||||
|
@ -1600,6 +1629,9 @@ def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
|
|||
|
||||
AutoGenC.Append(gPcdDatabaseAutoGenC.Replace(Dict))
|
||||
|
||||
if Platform.Platform.VarCheckFlag:
|
||||
dest = os.path.join(Platform.BuildDir, 'FV')
|
||||
VarCheckTab.dump(dest, Phase)
|
||||
Buffer = BuildExDataBase(Dict)
|
||||
return AutoGenH, AutoGenC, Buffer
|
||||
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
# Copyright (c) 2015, Intel Corporation. All rights reserved.<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.
|
||||
|
||||
#
|
||||
# This file is used to collect the Variable checking information
|
||||
#
|
||||
|
||||
# #
|
||||
# Import Modules
|
||||
#
|
||||
import os
|
||||
from Common.RangeExpression import RangeExpression
|
||||
from Common.Misc import *
|
||||
from StringIO import StringIO
|
||||
from struct import pack
|
||||
|
||||
class VAR_CHECK_PCD_VARIABLE_TAB_CONTAINER(object):
|
||||
def __init__(self):
|
||||
self.var_check_info = []
|
||||
|
||||
def push_back(self, var_check_tab):
|
||||
for tab in self.var_check_info:
|
||||
if tab.equal(var_check_tab):
|
||||
tab.merge(var_check_tab)
|
||||
break
|
||||
else:
|
||||
self.var_check_info.append(var_check_tab)
|
||||
|
||||
def dump(self, dest, Phase):
|
||||
|
||||
FormatMap = {}
|
||||
FormatMap[1] = "=B"
|
||||
FormatMap[2] = "=H"
|
||||
FormatMap[4] = "=L"
|
||||
FormatMap[8] = "=Q"
|
||||
|
||||
if not os.path.isabs(dest):
|
||||
return
|
||||
if not os.path.exists(dest):
|
||||
os.mkdir(dest)
|
||||
BinFileName = "PcdVarCheck.bin"
|
||||
BinFilePath = os.path.join(dest, BinFileName)
|
||||
Buffer = ''
|
||||
index = 0
|
||||
for var_check_tab in self.var_check_info:
|
||||
index += 1
|
||||
realLength = 0
|
||||
realLength += 32
|
||||
Name = var_check_tab.Name[1:-1]
|
||||
NameChars = Name.split(",")
|
||||
realLength += len(NameChars)
|
||||
if (index < len(self.var_check_info) and realLength % 4) or (index == len(self.var_check_info) and len(var_check_tab.validtab) > 0 and realLength % 4):
|
||||
realLength += (4 - (realLength % 4))
|
||||
itemIndex = 0
|
||||
for item in var_check_tab.validtab:
|
||||
itemIndex += 1
|
||||
realLength += 5
|
||||
for v_data in item.data:
|
||||
if type(v_data) == type(1):
|
||||
realLength += item.StorageWidth
|
||||
else:
|
||||
realLength += item.StorageWidth
|
||||
realLength += item.StorageWidth
|
||||
if (index == len(self.var_check_info)) :
|
||||
if (itemIndex < len(var_check_tab.validtab)) and realLength % 4:
|
||||
realLength += (4 - (realLength % 4))
|
||||
else:
|
||||
if realLength % 4:
|
||||
realLength += (4 - (realLength % 4))
|
||||
var_check_tab.Length = realLength
|
||||
realLength = 0
|
||||
index = 0
|
||||
for var_check_tab in self.var_check_info:
|
||||
index += 1
|
||||
|
||||
b = pack("=H", var_check_tab.Revision)
|
||||
Buffer += b
|
||||
realLength += 2
|
||||
|
||||
b = pack("=H", var_check_tab.HeaderLength)
|
||||
Buffer += b
|
||||
realLength += 2
|
||||
|
||||
b = pack("=L", var_check_tab.Length)
|
||||
Buffer += b
|
||||
realLength += 4
|
||||
|
||||
b = pack("=B", var_check_tab.Type)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
|
||||
for i in range(0, 3):
|
||||
b = pack("=B", var_check_tab.Reserved)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
|
||||
b = pack("=L", var_check_tab.Attributes)
|
||||
Buffer += b
|
||||
realLength += 4
|
||||
|
||||
Guid = var_check_tab.Guid
|
||||
b = pack('=LHHBBBBBBBB',
|
||||
Guid[0],
|
||||
Guid[1],
|
||||
Guid[2],
|
||||
Guid[3],
|
||||
Guid[4],
|
||||
Guid[5],
|
||||
Guid[6],
|
||||
Guid[7],
|
||||
Guid[8],
|
||||
Guid[9],
|
||||
Guid[10],
|
||||
)
|
||||
Buffer += b
|
||||
realLength += 16
|
||||
|
||||
Name = var_check_tab.Name[1:-1]
|
||||
NameChars = Name.split(",")
|
||||
for NameChar in NameChars:
|
||||
NameCharNum = int(NameChar, 16)
|
||||
b = pack("=B", NameCharNum)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
|
||||
if (index < len(self.var_check_info) and realLength % 4) or (index == len(self.var_check_info) and len(var_check_tab.validtab) > 0 and realLength % 4):
|
||||
for i in range(4 - (realLength % 4)):
|
||||
b = pack("=B", var_check_tab.pad)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
itemIndex = 0
|
||||
for item in var_check_tab.validtab:
|
||||
itemIndex += 1
|
||||
|
||||
b = pack("=B", item.Type)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
|
||||
b = pack("=B", item.Length)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
|
||||
b = pack("=H", int(item.VarOffset, 16))
|
||||
Buffer += b
|
||||
realLength += 2
|
||||
|
||||
b = pack("=B", item.StorageWidth)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
|
||||
for v_data in item.data:
|
||||
if type(v_data) == type(1):
|
||||
b = pack(FormatMap[item.StorageWidth], v_data)
|
||||
Buffer += b
|
||||
realLength += item.StorageWidth
|
||||
else:
|
||||
b = pack(FormatMap[item.StorageWidth], v_data[0])
|
||||
Buffer += b
|
||||
realLength += item.StorageWidth
|
||||
b = pack(FormatMap[item.StorageWidth], v_data[1])
|
||||
Buffer += b
|
||||
realLength += item.StorageWidth
|
||||
|
||||
if (index == len(self.var_check_info)) :
|
||||
if (itemIndex < len(var_check_tab.validtab)) and realLength % 4:
|
||||
for i in range(4 - (realLength % 4)):
|
||||
b = pack("=B", var_check_tab.pad)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
else:
|
||||
if realLength % 4:
|
||||
for i in range(4 - (realLength % 4)):
|
||||
b = pack("=B", var_check_tab.pad)
|
||||
Buffer += b
|
||||
realLength += 1
|
||||
|
||||
DbFile = StringIO()
|
||||
if Phase == 'DXE' and os.path.exists(BinFilePath):
|
||||
BinFile = open(BinFilePath, "rb")
|
||||
BinBuffer = BinFile.read()
|
||||
BinFile.close()
|
||||
BinBufferSize = len(BinBuffer)
|
||||
if (BinBufferSize % 4):
|
||||
for i in range(4 - (BinBufferSize % 4)):
|
||||
b = pack("=B", VAR_CHECK_PCD_VARIABLE_TAB.pad)
|
||||
BinBuffer += b
|
||||
Buffer = BinBuffer + Buffer
|
||||
DbFile.write(Buffer)
|
||||
SaveFileOnChange(BinFilePath, DbFile.getvalue(), True)
|
||||
|
||||
|
||||
class VAR_CHECK_PCD_VARIABLE_TAB(object):
|
||||
pad = 0xDA
|
||||
def __init__(self, TokenSpaceGuid, PcdCName):
|
||||
self.Revision = 0x0001
|
||||
self.HeaderLength = 0
|
||||
self.Length = 0 # Length include this header
|
||||
self.Type = 0
|
||||
self.Reserved = 0
|
||||
self.Attributes = 0x00000000
|
||||
self.Guid = eval("[" + TokenSpaceGuid.replace("{", "").replace("}", "") + "]")
|
||||
self.Name = PcdCName
|
||||
self.validtab = []
|
||||
|
||||
def UpdateSize(self):
|
||||
self.HeaderLength = 32 + len(self.Name.split(","))
|
||||
self.Length = 32 + len(self.Name.split(",")) + self.GetValidTabLen()
|
||||
|
||||
def GetValidTabLen(self):
|
||||
validtablen = 0
|
||||
for item in self.validtab:
|
||||
validtablen += item.Length
|
||||
return validtablen
|
||||
|
||||
def SetAttributes(self, attributes):
|
||||
self.Attributes = attributes
|
||||
|
||||
def push_back(self, valid_obj):
|
||||
if valid_obj is not None:
|
||||
self.validtab.append(valid_obj)
|
||||
|
||||
def equal(self, varchecktab):
|
||||
if self.Guid == varchecktab.Guid and self.Name == varchecktab.Name:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def merge(self, varchecktab):
|
||||
for validobj in varchecktab.validtab:
|
||||
if validobj in self.validtab:
|
||||
continue
|
||||
self.validtab.append(validobj)
|
||||
self.UpdateSize()
|
||||
|
||||
|
||||
class VAR_CHECK_PCD_VALID_OBJ(object):
|
||||
def __init__(self, VarOffset, data, PcdDataType):
|
||||
self.Type = 1
|
||||
self.Length = 0 # Length include this header
|
||||
self.VarOffset = VarOffset
|
||||
self.StorageWidth = 0
|
||||
self.PcdDataType = PcdDataType.strip()
|
||||
self.rawdata = data
|
||||
self.data = set()
|
||||
self.ValidData = True
|
||||
self.updateStorageWidth()
|
||||
def updateStorageWidth(self):
|
||||
if self.PcdDataType == "UINT8" or self.PcdDataType == "BOOLEAN":
|
||||
self.StorageWidth = 1
|
||||
elif self.PcdDataType == "UINT16":
|
||||
self.StorageWidth = 2
|
||||
elif self.PcdDataType == "UINT32":
|
||||
self.StorageWidth = 4
|
||||
elif self.PcdDataType == "UINT64":
|
||||
self.StorageWidth = 8
|
||||
else:
|
||||
self.StorageWidth = 0
|
||||
self.ValidData = False
|
||||
|
||||
def __eq__(self, validObj):
|
||||
if self.VarOffset == validObj.VarOffset:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
class VAR_CHECK_PCD_VALID_LIST(VAR_CHECK_PCD_VALID_OBJ):
|
||||
def __init__(self, VarOffset, validlist, PcdDataType):
|
||||
super(VAR_CHECK_PCD_VALID_LIST, self).__init__(VarOffset, validlist, PcdDataType)
|
||||
self.Type = 1
|
||||
self.update_data()
|
||||
self.update_size()
|
||||
def update_data(self):
|
||||
valid_num_list = []
|
||||
data_list = []
|
||||
for item in self.rawdata:
|
||||
valid_num_list.extend(item.split(','))
|
||||
|
||||
for valid_num in valid_num_list:
|
||||
valid_num = valid_num.strip()
|
||||
|
||||
if valid_num.startswith('0x') or valid_num.startswith('0X'):
|
||||
data_list.append(int(valid_num, 16))
|
||||
else:
|
||||
data_list.append(int(valid_num))
|
||||
|
||||
|
||||
self.data = set(data_list)
|
||||
|
||||
def update_size(self):
|
||||
self.Length = 5 + len(self.data) * self.StorageWidth
|
||||
|
||||
|
||||
class VAR_CHECK_PCD_VALID_RANGE(VAR_CHECK_PCD_VALID_OBJ):
|
||||
def __init__(self, VarOffset, validrange, PcdDataType):
|
||||
super(VAR_CHECK_PCD_VALID_RANGE, self).__init__(VarOffset, validrange, PcdDataType)
|
||||
self.Type = 2
|
||||
self.update_data()
|
||||
self.update_size()
|
||||
def update_data(self):
|
||||
RangeExpr = ""
|
||||
data_list = []
|
||||
i = 0
|
||||
for item in self.rawdata:
|
||||
if i == 0:
|
||||
RangeExpr = "( " + item + " )"
|
||||
else:
|
||||
RangeExpr = RangeExpr + "OR ( " + item + " )"
|
||||
range_result = RangeExpression(RangeExpr, self.PcdDataType)(True)
|
||||
for rangelist in range_result:
|
||||
for obj in rangelist.pop():
|
||||
data_list.append((obj.start, obj.end))
|
||||
self.data = set(data_list)
|
||||
|
||||
def update_size(self):
|
||||
self.Length = 5 + len(self.data) * 2 * self.StorageWidth
|
||||
|
||||
|
||||
class VAR_VALID_OBJECT_FACTORY(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
@staticmethod
|
||||
def Get_valid_object(PcdClass, VarOffset):
|
||||
if PcdClass.validateranges:
|
||||
return VAR_CHECK_PCD_VALID_RANGE(VarOffset, PcdClass.validateranges, PcdClass.DatumType)
|
||||
if PcdClass.validlists:
|
||||
return VAR_CHECK_PCD_VALID_LIST(VarOffset, PcdClass.validlists, PcdClass.DatumType)
|
||||
else:
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
class TestObj(object):
|
||||
def __init__(self, number1):
|
||||
self.number_1 = number1
|
||||
def __eq__(self, testobj):
|
||||
if self.number_1 == testobj.number_1:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
test1 = TestObj(1)
|
||||
test2 = TestObj(2)
|
||||
|
||||
testarr = [test1, test2]
|
||||
print TestObj(2) in testarr
|
||||
print TestObj(2) == test2
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# Standardized Error Hanlding infrastructures.
|
||||
#
|
||||
# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -81,6 +81,9 @@ EOT_ERROR = 0xF005
|
|||
DDC_ERROR = 0xF009
|
||||
WARNING_AS_ERROR = 0xF006
|
||||
MIGRATION_ERROR = 0xF010
|
||||
PCD_VALIDATION_INFO_ERROR = 0xF011
|
||||
PCD_VARIABLE_ATTRIBUTES_ERROR = 0xF012
|
||||
PCD_VARIABLE_ATTRIBUTES_CONFLICT_ERROR = 0xF013
|
||||
ABORT_ERROR = 0xFFFE
|
||||
UNKNOWN_ERROR = 0xFFFF
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# This file is used to define common static strings used by INF/DEC/DSC files
|
||||
#
|
||||
# Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
|
@ -398,6 +398,7 @@ TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES = 'SUPPORTED_ARCHITECTURES'
|
|||
TAB_DSC_DEFINES_BUILD_TARGETS = 'BUILD_TARGETS'
|
||||
TAB_DSC_DEFINES_SKUID_IDENTIFIER = 'SKUID_IDENTIFIER'
|
||||
TAB_DSC_DEFINES_PCD_INFO_GENERATION = 'PCD_INFO_GENERATION'
|
||||
TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION = 'PCD_VAR_CHECK_GENERATION'
|
||||
TAB_DSC_DEFINES_FLASH_DEFINITION = 'FLASH_DEFINITION'
|
||||
TAB_DSC_DEFINES_BUILD_NUMBER = 'BUILD_NUMBER'
|
||||
TAB_DSC_DEFINES_MAKEFILE_NAME = 'MAKEFILE_NAME'
|
||||
|
|
|
@ -1508,15 +1508,17 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
|
|||
return [VpdOffset, Size, Value], IsValid, 2
|
||||
elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):
|
||||
HiiString = FieldList[0]
|
||||
Guid = Offset = Value = ''
|
||||
Guid = Offset = Value = Attribute = ''
|
||||
if len(FieldList) > 1:
|
||||
Guid = FieldList[1]
|
||||
if len(FieldList) > 2:
|
||||
Offset = FieldList[2]
|
||||
if len(FieldList) > 3:
|
||||
Value = FieldList[3]
|
||||
IsValid = (3 <= len(FieldList) <= 4)
|
||||
return [HiiString, Guid, Offset, Value], IsValid, 3
|
||||
if len(FieldList) > 4:
|
||||
Attribute = FieldList[4]
|
||||
IsValid = (3 <= len(FieldList) <= 5)
|
||||
return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3
|
||||
return [], False, 0
|
||||
|
||||
## AnalyzePcdData
|
||||
|
|
|
@ -0,0 +1,737 @@
|
|||
# # @file
|
||||
# This file is used to parse and evaluate range expression in Pcd declaration.
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. All rights reserved.<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.
|
||||
|
||||
# # Import Modules
|
||||
#
|
||||
from Common.GlobalData import *
|
||||
from CommonDataClass.Exceptions import BadExpression
|
||||
from CommonDataClass.Exceptions import WrnExpression
|
||||
import uuid
|
||||
|
||||
ERR_STRING_EXPR = 'This operator cannot be used in string expression: [%s].'
|
||||
ERR_SNYTAX = 'Syntax error, the rest of expression cannot be evaluated: [%s].'
|
||||
ERR_MATCH = 'No matching right parenthesis.'
|
||||
ERR_STRING_TOKEN = 'Bad string token: [%s].'
|
||||
ERR_MACRO_TOKEN = 'Bad macro token: [%s].'
|
||||
ERR_EMPTY_TOKEN = 'Empty token is not allowed.'
|
||||
ERR_PCD_RESOLVE = 'PCD token cannot be resolved: [%s].'
|
||||
ERR_VALID_TOKEN = 'No more valid token found from rest of string: [%s].'
|
||||
ERR_EXPR_TYPE = 'Different types found in expression.'
|
||||
ERR_OPERATOR_UNSUPPORT = 'Unsupported operator: [%s]'
|
||||
ERR_REL_NOT_IN = 'Expect "IN" after "not" operator.'
|
||||
WRN_BOOL_EXPR = 'Operand of boolean type cannot be used in arithmetic expression.'
|
||||
WRN_EQCMP_STR_OTHERS = '== Comparison between Operand of string type and Boolean/Number Type always return False.'
|
||||
WRN_NECMP_STR_OTHERS = '!= Comparison between Operand of string type and Boolean/Number Type always return True.'
|
||||
ERR_RELCMP_STR_OTHERS = 'Operator taking Operand of string type and Boolean/Number Type is not allowed: [%s].'
|
||||
ERR_STRING_CMP = 'Unicode string and general string cannot be compared: [%s %s %s]'
|
||||
ERR_ARRAY_TOKEN = 'Bad C array or C format GUID token: [%s].'
|
||||
ERR_ARRAY_ELE = 'This must be HEX value for NList or Array: [%s].'
|
||||
ERR_EMPTY_EXPR = 'Empty expression is not allowed.'
|
||||
ERR_IN_OPERAND = 'Macro after IN operator can only be: $(FAMILY), $(ARCH), $(TOOL_CHAIN_TAG) and $(TARGET).'
|
||||
|
||||
def MaxOfType(DataType):
|
||||
if DataType == 'UINT8':
|
||||
return int('0xFF', 16)
|
||||
if DataType == 'UINT16':
|
||||
return int('0xFFFF', 16)
|
||||
if DataType == 'UINT32':
|
||||
return int('0xFFFFFFFF', 16)
|
||||
if DataType == 'UINT64':
|
||||
return int('0xFFFFFFFFFFFFFFFF', 16)
|
||||
|
||||
class RangeObject(object):
|
||||
def __init__(self, start, end, empty = False):
|
||||
|
||||
if int(start) < int(end):
|
||||
self.start = int(start)
|
||||
self.end = int(end)
|
||||
else:
|
||||
self.start = int(end)
|
||||
self.end = int(start)
|
||||
self.empty = empty
|
||||
|
||||
class RangeContainer(object):
|
||||
def __init__(self):
|
||||
self.rangelist = []
|
||||
|
||||
def push(self, RangeObject):
|
||||
self.rangelist.append(RangeObject)
|
||||
self.rangelist = sorted(self.rangelist, key = lambda rangeobj : rangeobj.start)
|
||||
self.merge()
|
||||
|
||||
def pop(self):
|
||||
for item in self.rangelist:
|
||||
yield item
|
||||
|
||||
def __clean__(self):
|
||||
newrangelist = []
|
||||
for rangeobj in self.rangelist:
|
||||
if rangeobj.empty == True:
|
||||
continue
|
||||
else:
|
||||
newrangelist.append(rangeobj)
|
||||
self.rangelist = newrangelist
|
||||
def merge(self):
|
||||
self.__clean__()
|
||||
for i in range(0, len(self.rangelist) - 1):
|
||||
if self.rangelist[i + 1].start > self.rangelist[i].end:
|
||||
continue
|
||||
else:
|
||||
self.rangelist[i + 1].start = self.rangelist[i].start
|
||||
self.rangelist[i + 1].end = self.rangelist[i + 1].end > self.rangelist[i].end and self.rangelist[i + 1].end or self.rangelist[i].end
|
||||
self.rangelist[i].empty = True
|
||||
|
||||
self.__clean__()
|
||||
|
||||
def dump(self):
|
||||
print "----------------------"
|
||||
rangelist = ""
|
||||
for object in self.rangelist:
|
||||
rangelist = rangelist + "[%d , %d]" % (object.start, object.end)
|
||||
print rangelist
|
||||
|
||||
|
||||
class XOROperatorObject(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def Calculate(self, Operand, DataType, SymbolTable):
|
||||
if type(Operand) == type('') and not Operand.isalnum():
|
||||
Expr = "XOR ..."
|
||||
raise BadExpression(ERR_SNYTAX % Expr)
|
||||
rangeId = str(uuid.uuid1())
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(0, int(Operand) - 1))
|
||||
rangeContainer.push(RangeObject(int(Operand) + 1, MaxOfType(DataType)))
|
||||
SymbolTable[rangeId] = rangeContainer
|
||||
return rangeId
|
||||
|
||||
class LEOperatorObject(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def Calculate(self, Operand, DataType, SymbolTable):
|
||||
if type(Operand) == type('') and not Operand.isalnum():
|
||||
Expr = "LE ..."
|
||||
raise BadExpression(ERR_SNYTAX % Expr)
|
||||
rangeId1 = str(uuid.uuid1())
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(0, int(Operand)))
|
||||
SymbolTable[rangeId1] = rangeContainer
|
||||
return rangeId1
|
||||
class LTOperatorObject(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def Calculate(self, Operand, DataType, SymbolTable):
|
||||
if type(Operand) == type('') and not Operand.isalnum():
|
||||
Expr = "LT ..."
|
||||
raise BadExpression(ERR_SNYTAX % Expr)
|
||||
rangeId1 = str(uuid.uuid1())
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(0, int(Operand) - 1))
|
||||
SymbolTable[rangeId1] = rangeContainer
|
||||
return rangeId1
|
||||
|
||||
class GEOperatorObject(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def Calculate(self, Operand, DataType, SymbolTable):
|
||||
if type(Operand) == type('') and not Operand.isalnum():
|
||||
Expr = "GE ..."
|
||||
raise BadExpression(ERR_SNYTAX % Expr)
|
||||
rangeId1 = str(uuid.uuid1())
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(int(Operand), MaxOfType(DataType)))
|
||||
SymbolTable[rangeId1] = rangeContainer
|
||||
return rangeId1
|
||||
|
||||
class GTOperatorObject(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def Calculate(self, Operand, DataType, SymbolTable):
|
||||
if type(Operand) == type('') and not Operand.isalnum():
|
||||
Expr = "GT ..."
|
||||
raise BadExpression(ERR_SNYTAX % Expr)
|
||||
rangeId1 = str(uuid.uuid1())
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(int(Operand) + 1, MaxOfType(DataType)))
|
||||
SymbolTable[rangeId1] = rangeContainer
|
||||
return rangeId1
|
||||
|
||||
class EQOperatorObject(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def Calculate(self, Operand, DataType, SymbolTable):
|
||||
if type(Operand) == type('') and not Operand.isalnum():
|
||||
Expr = "EQ ..."
|
||||
raise BadExpression(ERR_SNYTAX % Expr)
|
||||
rangeId1 = str(uuid.uuid1())
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(int(Operand) , int(Operand)))
|
||||
SymbolTable[rangeId1] = rangeContainer
|
||||
return rangeId1
|
||||
|
||||
def GetOperatorObject(Operator):
|
||||
if Operator == '>':
|
||||
return GTOperatorObject()
|
||||
elif Operator == '>=':
|
||||
return GEOperatorObject()
|
||||
elif Operator == '<':
|
||||
return LTOperatorObject()
|
||||
elif Operator == '<=':
|
||||
return LEOperatorObject()
|
||||
elif Operator == '==':
|
||||
return EQOperatorObject()
|
||||
elif Operator == '^':
|
||||
return XOROperatorObject()
|
||||
else:
|
||||
raise BadExpression("Bad Operator")
|
||||
|
||||
class RangeExpression(object):
|
||||
# Logical operator mapping
|
||||
LogicalOperators = {
|
||||
'&&' : 'and', '||' : 'or',
|
||||
'!' : 'not', 'AND': 'and',
|
||||
'OR' : 'or' , 'NOT': 'not',
|
||||
'XOR': '^' , 'xor': '^',
|
||||
'EQ' : '==' , 'NE' : '!=',
|
||||
'GT' : '>' , 'LT' : '<',
|
||||
'GE' : '>=' , 'LE' : '<=',
|
||||
'IN' : 'in'
|
||||
}
|
||||
|
||||
NonLetterOpLst = ['+', '-', '&', '|', '^', '!', '=', '>', '<']
|
||||
|
||||
PcdPattern = re.compile(r'[_a-zA-Z][0-9A-Za-z_]*\.[_a-zA-Z][0-9A-Za-z_]*$')
|
||||
HexPattern = re.compile(r'0[xX][0-9a-fA-F]+')
|
||||
RegGuidPattern = re.compile(r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}')
|
||||
ExRegGuidPattern = re.compile(r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$')
|
||||
|
||||
SymbolPattern = re.compile("("
|
||||
"\$\([A-Z][A-Z0-9_]*\)|\$\(\w+\.\w+\)|\w+\.\w+|"
|
||||
"&&|\|\||!(?!=)|"
|
||||
"(?<=\W)AND(?=\W)|(?<=\W)OR(?=\W)|(?<=\W)NOT(?=\W)|(?<=\W)XOR(?=\W)|"
|
||||
"(?<=\W)EQ(?=\W)|(?<=\W)NE(?=\W)|(?<=\W)GT(?=\W)|(?<=\W)LT(?=\W)|(?<=\W)GE(?=\W)|(?<=\W)LE(?=\W)"
|
||||
")")
|
||||
|
||||
RangePattern = re.compile(r'[0-9]+ - [0-9]+')
|
||||
|
||||
def preProcessRangeExpr(self, expr):
|
||||
# convert hex to int
|
||||
# convert interval to object index. ex. 1 - 10 to a GUID
|
||||
expr = expr.strip()
|
||||
NumberDict = {}
|
||||
for HexNumber in self.HexPattern.findall(expr):
|
||||
Number = str(int(HexNumber, 16))
|
||||
NumberDict[HexNumber] = Number
|
||||
for HexNum in NumberDict:
|
||||
expr = expr.replace(HexNum, NumberDict[HexNum])
|
||||
|
||||
rangedict = {}
|
||||
for validrange in self.RangePattern.findall(expr):
|
||||
start, end = validrange.split(" - ")
|
||||
start = start.strip()
|
||||
end = end.strip()
|
||||
rangeid = str(uuid.uuid1())
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(start, end))
|
||||
self.operanddict[str(rangeid)] = rangeContainer
|
||||
rangedict[validrange] = str(rangeid)
|
||||
|
||||
for validrange in rangedict:
|
||||
expr = expr.replace(validrange, rangedict[validrange])
|
||||
|
||||
self._Expr = expr
|
||||
return expr
|
||||
|
||||
|
||||
def EvalRange(self, Operator, Oprand):
|
||||
|
||||
operatorobj = GetOperatorObject(Operator)
|
||||
return operatorobj.Calculate(Oprand, self.PcdDataType, self.operanddict)
|
||||
|
||||
def Rangeintersection(self, Oprand1, Oprand2):
|
||||
rangeContainer1 = self.operanddict[Oprand1]
|
||||
rangeContainer2 = self.operanddict[Oprand2]
|
||||
rangeContainer = RangeContainer()
|
||||
for range1 in rangeContainer1.pop():
|
||||
for range2 in rangeContainer2.pop():
|
||||
if range1.start >= range2.start:
|
||||
start = range1.start
|
||||
end = range1.end
|
||||
range1.start = range2.start
|
||||
range1.end = range2.end
|
||||
range2.start = start
|
||||
range2.end = end
|
||||
if range1.empty:
|
||||
rangeid = str(uuid.uuid1())
|
||||
rangeContainer.push(RangeObject(0, 0, True))
|
||||
if range1.end < range2.start:
|
||||
rangeid = str(uuid.uuid1())
|
||||
rangeContainer.push(RangeObject(0, 0, True))
|
||||
elif range1.end == range2.start:
|
||||
rangeid = str(uuid.uuid1())
|
||||
rangeContainer.push(RangeObject(range1.end, range1.end))
|
||||
elif range1.end <= range2.end and range1.end > range2.start:
|
||||
rangeid = str(uuid.uuid1())
|
||||
rangeContainer.push(RangeObject(range2.start, range1.end))
|
||||
elif range1.end >= range2.end:
|
||||
rangeid = str(uuid.uuid1())
|
||||
rangeContainer.push(RangeObject(range2.start, range2.end))
|
||||
|
||||
self.operanddict[rangeid] = rangeContainer
|
||||
# rangeContainer.dump()
|
||||
return rangeid
|
||||
|
||||
def Rangecollections(self, Oprand1, Oprand2):
|
||||
|
||||
rangeContainer1 = self.operanddict[Oprand1]
|
||||
rangeContainer2 = self.operanddict[Oprand2]
|
||||
rangeContainer = RangeContainer()
|
||||
|
||||
for rangeobj in rangeContainer2.pop():
|
||||
rangeContainer.push(rangeobj)
|
||||
for rangeobj in rangeContainer1.pop():
|
||||
rangeContainer.push(rangeobj)
|
||||
|
||||
rangeid = str(uuid.uuid1())
|
||||
self.operanddict[rangeid] = rangeContainer
|
||||
|
||||
# rangeContainer.dump()
|
||||
return rangeid
|
||||
|
||||
|
||||
def NegtiveRange(self, Oprand1):
|
||||
rangeContainer1 = self.operanddict[Oprand1]
|
||||
|
||||
|
||||
rangeids = []
|
||||
|
||||
for rangeobj in rangeContainer1.pop():
|
||||
rangeContainer = RangeContainer()
|
||||
rangeid = str(uuid.uuid1())
|
||||
if rangeobj.empty:
|
||||
rangeContainer.push(RangeObject(0, MaxOfType(self.PcdDataType)))
|
||||
else:
|
||||
if rangeobj.start > 0:
|
||||
rangeContainer.push(RangeObject(0, rangeobj.start - 1))
|
||||
if rangeobj.end < MaxOfType(self.PcdDataType):
|
||||
rangeContainer.push(RangeObject(rangeobj.end + 1, MaxOfType(self.PcdDataType)))
|
||||
self.operanddict[rangeid] = rangeContainer
|
||||
rangeids.append(rangeid)
|
||||
|
||||
if len(rangeids) == 0:
|
||||
rangeContainer = RangeContainer()
|
||||
rangeContainer.push(RangeObject(0, MaxOfType(self.PcdDataType)))
|
||||
rangeid = str(uuid.uuid1())
|
||||
self.operanddict[rangeid] = rangeContainer
|
||||
return rangeid
|
||||
|
||||
if len(rangeids) == 1:
|
||||
return rangeids[0]
|
||||
|
||||
re = self.Rangeintersection(rangeids[0], rangeids[1])
|
||||
for i in range(2, len(rangeids)):
|
||||
re = self.Rangeintersection(re, rangeids[i])
|
||||
|
||||
rangeid2 = str(uuid.uuid1())
|
||||
self.operanddict[rangeid2] = self.operanddict[re]
|
||||
return rangeid2
|
||||
|
||||
def Eval(self, Operator, Oprand1, Oprand2 = None):
|
||||
|
||||
if Operator in ["!", "NOT", "not"]:
|
||||
if not self.RegGuidPattern.match(Oprand1.strip()):
|
||||
raise BadExpression(ERR_STRING_EXPR % Operator)
|
||||
return self.NegtiveRange(Oprand1)
|
||||
else:
|
||||
if Operator in ["==", ">=", "<=", ">", "<", '^']:
|
||||
return self.EvalRange(Operator, Oprand1)
|
||||
elif Operator == 'and' :
|
||||
if not self.ExRegGuidPattern.match(Oprand1.strip()) or not self.ExRegGuidPattern.match(Oprand2.strip()):
|
||||
raise BadExpression(ERR_STRING_EXPR % Operator)
|
||||
return self.Rangeintersection(Oprand1, Oprand2)
|
||||
elif Operator == 'or':
|
||||
if not self.ExRegGuidPattern.match(Oprand1.strip()) or not self.ExRegGuidPattern.match(Oprand2.strip()):
|
||||
raise BadExpression(ERR_STRING_EXPR % Operator)
|
||||
return self.Rangecollections(Oprand1, Oprand2)
|
||||
else:
|
||||
raise BadExpression(ERR_STRING_EXPR % Operator)
|
||||
|
||||
|
||||
def __init__(self, Expression, PcdDataType, SymbolTable = {}):
|
||||
self._NoProcess = False
|
||||
if type(Expression) != type(''):
|
||||
self._Expr = Expression
|
||||
self._NoProcess = True
|
||||
return
|
||||
|
||||
self._Expr = Expression.strip()
|
||||
|
||||
if not self._Expr.strip():
|
||||
raise BadExpression(ERR_EMPTY_EXPR)
|
||||
|
||||
#
|
||||
# The symbol table including PCD and macro mapping
|
||||
#
|
||||
self._Symb = SymbolTable
|
||||
self._Symb.update(self.LogicalOperators)
|
||||
self._Idx = 0
|
||||
self._Len = len(self._Expr)
|
||||
self._Token = ''
|
||||
self._WarnExcept = None
|
||||
|
||||
|
||||
# Literal token without any conversion
|
||||
self._LiteralToken = ''
|
||||
|
||||
# store the operand object
|
||||
self.operanddict = {}
|
||||
# The Pcd max value depends on PcdDataType
|
||||
self.PcdDataType = PcdDataType
|
||||
|
||||
# Public entry for this class
|
||||
# @param RealValue: False: only evaluate if the expression is true or false, used for conditional expression
|
||||
# True : return the evaluated str(value), used for PCD value
|
||||
#
|
||||
# @return: True or False if RealValue is False
|
||||
# Evaluated value of string format if RealValue is True
|
||||
#
|
||||
def __call__(self, RealValue = False, Depth = 0):
|
||||
if self._NoProcess:
|
||||
return self._Expr
|
||||
|
||||
self._Depth = Depth
|
||||
|
||||
self._Expr = self._Expr.strip()
|
||||
|
||||
self.preProcessRangeExpr(self._Expr)
|
||||
|
||||
# check if the expression does not need to evaluate
|
||||
if RealValue and Depth == 0:
|
||||
self._Token = self._Expr
|
||||
if self.ExRegGuidPattern.match(self._Expr):
|
||||
return [self.operanddict[self._Expr] ]
|
||||
|
||||
self._Idx = 0
|
||||
self._Token = ''
|
||||
|
||||
Val = self._OrExpr()
|
||||
RealVal = Val
|
||||
|
||||
RangeIdList = RealVal.split("or")
|
||||
RangeList = []
|
||||
for rangeid in RangeIdList:
|
||||
RangeList.append(self.operanddict[rangeid.strip()])
|
||||
|
||||
return RangeList
|
||||
|
||||
# Template function to parse binary operators which have same precedence
|
||||
# Expr [Operator Expr]*
|
||||
def _ExprFuncTemplate(self, EvalFunc, OpLst):
|
||||
Val = EvalFunc()
|
||||
while self._IsOperator(OpLst):
|
||||
Op = self._Token
|
||||
try:
|
||||
Val = self.Eval(Op, Val, EvalFunc())
|
||||
except WrnExpression, Warn:
|
||||
self._WarnExcept = Warn
|
||||
Val = Warn.result
|
||||
return Val
|
||||
|
||||
# A [|| B]*
|
||||
def _OrExpr(self):
|
||||
return self._ExprFuncTemplate(self._AndExpr, ["OR", "or"])
|
||||
|
||||
# A [&& B]*
|
||||
def _AndExpr(self):
|
||||
return self._ExprFuncTemplate(self._NeExpr, ["AND", "and"])
|
||||
|
||||
def _NeExpr(self):
|
||||
Val = self._RelExpr()
|
||||
while self._IsOperator([ "!=", "NOT", "not"]):
|
||||
Op = self._Token
|
||||
if Op in ["!", "NOT", "not"]:
|
||||
if not self._IsOperator(["IN", "in"]):
|
||||
raise BadExpression(ERR_REL_NOT_IN)
|
||||
Op += ' ' + self._Token
|
||||
try:
|
||||
Val = self.Eval(Op, Val, self._RelExpr())
|
||||
except WrnExpression, Warn:
|
||||
self._WarnExcept = Warn
|
||||
Val = Warn.result
|
||||
return Val
|
||||
|
||||
# [!]*A
|
||||
def _RelExpr(self):
|
||||
if self._IsOperator(["NOT" , "LE", "GE", "LT", "GT", "EQ", "XOR"]):
|
||||
Token = self._Token
|
||||
Val = self._NeExpr()
|
||||
try:
|
||||
return self.Eval(Token, Val)
|
||||
except WrnExpression, Warn:
|
||||
self._WarnExcept = Warn
|
||||
return Warn.result
|
||||
return self._IdenExpr()
|
||||
|
||||
# Parse identifier or encapsulated expression
|
||||
def _IdenExpr(self):
|
||||
Tk = self._GetToken()
|
||||
if Tk == '(':
|
||||
Val = self._OrExpr()
|
||||
try:
|
||||
# _GetToken may also raise BadExpression
|
||||
if self._GetToken() != ')':
|
||||
raise BadExpression(ERR_MATCH)
|
||||
except BadExpression:
|
||||
raise BadExpression(ERR_MATCH)
|
||||
return Val
|
||||
return Tk
|
||||
|
||||
# Skip whitespace or tab
|
||||
def __SkipWS(self):
|
||||
for Char in self._Expr[self._Idx:]:
|
||||
if Char not in ' \t':
|
||||
break
|
||||
self._Idx += 1
|
||||
|
||||
# Try to convert string to number
|
||||
def __IsNumberToken(self):
|
||||
Radix = 10
|
||||
if self._Token.lower()[0:2] == '0x' and len(self._Token) > 2:
|
||||
Radix = 16
|
||||
try:
|
||||
self._Token = int(self._Token, Radix)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
# Parse array: {...}
|
||||
def __GetArray(self):
|
||||
Token = '{'
|
||||
self._Idx += 1
|
||||
self.__GetNList(True)
|
||||
Token += self._LiteralToken
|
||||
if self._Idx >= self._Len or self._Expr[self._Idx] != '}':
|
||||
raise BadExpression(ERR_ARRAY_TOKEN % Token)
|
||||
Token += '}'
|
||||
|
||||
# All whitespace and tabs in array are already stripped.
|
||||
IsArray = IsGuid = False
|
||||
if len(Token.split(',')) == 11 and len(Token.split(',{')) == 2 \
|
||||
and len(Token.split('},')) == 1:
|
||||
HexLen = [11, 6, 6, 5, 4, 4, 4, 4, 4, 4, 6]
|
||||
HexList = Token.split(',')
|
||||
if HexList[3].startswith('{') and \
|
||||
not [Index for Index, Hex in enumerate(HexList) if len(Hex) > HexLen[Index]]:
|
||||
IsGuid = True
|
||||
if Token.lstrip('{').rstrip('}').find('{') == -1:
|
||||
if not [Hex for Hex in Token.lstrip('{').rstrip('}').split(',') if len(Hex) > 4]:
|
||||
IsArray = True
|
||||
if not IsArray and not IsGuid:
|
||||
raise BadExpression(ERR_ARRAY_TOKEN % Token)
|
||||
self._Idx += 1
|
||||
self._Token = self._LiteralToken = Token
|
||||
return self._Token
|
||||
|
||||
# Parse string, the format must be: "..."
|
||||
def __GetString(self):
|
||||
Idx = self._Idx
|
||||
|
||||
# Skip left quote
|
||||
self._Idx += 1
|
||||
|
||||
# Replace escape \\\", \"
|
||||
Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace('\\\"', '\\\'')
|
||||
for Ch in Expr:
|
||||
self._Idx += 1
|
||||
if Ch == '"':
|
||||
break
|
||||
self._Token = self._LiteralToken = self._Expr[Idx:self._Idx]
|
||||
if not self._Token.endswith('"'):
|
||||
raise BadExpression(ERR_STRING_TOKEN % self._Token)
|
||||
self._Token = self._Token[1:-1]
|
||||
return self._Token
|
||||
|
||||
# Get token that is comprised by alphanumeric, underscore or dot(used by PCD)
|
||||
# @param IsAlphaOp: Indicate if parsing general token or script operator(EQ, NE...)
|
||||
def __GetIdToken(self, IsAlphaOp = False):
|
||||
IdToken = ''
|
||||
for Ch in self._Expr[self._Idx:]:
|
||||
if not self.__IsIdChar(Ch):
|
||||
break
|
||||
self._Idx += 1
|
||||
IdToken += Ch
|
||||
|
||||
self._Token = self._LiteralToken = IdToken
|
||||
if not IsAlphaOp:
|
||||
self.__ResolveToken()
|
||||
return self._Token
|
||||
|
||||
# Try to resolve token
|
||||
def __ResolveToken(self):
|
||||
if not self._Token:
|
||||
raise BadExpression(ERR_EMPTY_TOKEN)
|
||||
|
||||
# PCD token
|
||||
if self.PcdPattern.match(self._Token):
|
||||
if self._Token not in self._Symb:
|
||||
Ex = BadExpression(ERR_PCD_RESOLVE % self._Token)
|
||||
Ex.Pcd = self._Token
|
||||
raise Ex
|
||||
self._Token = RangeExpression(self._Symb[self._Token], self._Symb)(True, self._Depth + 1)
|
||||
if type(self._Token) != type(''):
|
||||
self._LiteralToken = hex(self._Token)
|
||||
return
|
||||
|
||||
if self._Token.startswith('"'):
|
||||
self._Token = self._Token[1:-1]
|
||||
elif self._Token in ["FALSE", "false", "False"]:
|
||||
self._Token = False
|
||||
elif self._Token in ["TRUE", "true", "True"]:
|
||||
self._Token = True
|
||||
else:
|
||||
self.__IsNumberToken()
|
||||
|
||||
def __GetNList(self, InArray = False):
|
||||
self._GetSingleToken()
|
||||
if not self.__IsHexLiteral():
|
||||
if InArray:
|
||||
raise BadExpression(ERR_ARRAY_ELE % self._Token)
|
||||
return self._Token
|
||||
|
||||
self.__SkipWS()
|
||||
Expr = self._Expr[self._Idx:]
|
||||
if not Expr.startswith(','):
|
||||
return self._Token
|
||||
|
||||
NList = self._LiteralToken
|
||||
while Expr.startswith(','):
|
||||
NList += ','
|
||||
self._Idx += 1
|
||||
self.__SkipWS()
|
||||
self._GetSingleToken()
|
||||
if not self.__IsHexLiteral():
|
||||
raise BadExpression(ERR_ARRAY_ELE % self._Token)
|
||||
NList += self._LiteralToken
|
||||
self.__SkipWS()
|
||||
Expr = self._Expr[self._Idx:]
|
||||
self._Token = self._LiteralToken = NList
|
||||
return self._Token
|
||||
|
||||
def __IsHexLiteral(self):
|
||||
if self._LiteralToken.startswith('{') and \
|
||||
self._LiteralToken.endswith('}'):
|
||||
return True
|
||||
|
||||
if self.HexPattern.match(self._LiteralToken):
|
||||
Token = self._LiteralToken[2:]
|
||||
Token = Token.lstrip('0')
|
||||
if not Token:
|
||||
self._LiteralToken = '0x0'
|
||||
else:
|
||||
self._LiteralToken = '0x' + Token.lower()
|
||||
return True
|
||||
return False
|
||||
|
||||
def _GetToken(self):
|
||||
return self.__GetNList()
|
||||
|
||||
@staticmethod
|
||||
def __IsIdChar(Ch):
|
||||
return Ch in '._/:' or Ch.isalnum()
|
||||
|
||||
# Parse operand
|
||||
def _GetSingleToken(self):
|
||||
self.__SkipWS()
|
||||
Expr = self._Expr[self._Idx:]
|
||||
if Expr.startswith('L"'):
|
||||
# Skip L
|
||||
self._Idx += 1
|
||||
UStr = self.__GetString()
|
||||
self._Token = 'L"' + UStr + '"'
|
||||
return self._Token
|
||||
|
||||
self._Token = ''
|
||||
if Expr:
|
||||
Ch = Expr[0]
|
||||
Match = self.RegGuidPattern.match(Expr)
|
||||
if Match and not Expr[Match.end():Match.end() + 1].isalnum() \
|
||||
and Expr[Match.end():Match.end() + 1] != '_':
|
||||
self._Idx += Match.end()
|
||||
self._Token = Expr[0:Match.end()]
|
||||
return self._Token
|
||||
elif self.__IsIdChar(Ch):
|
||||
return self.__GetIdToken()
|
||||
elif Ch == '(' or Ch == ')':
|
||||
self._Idx += 1
|
||||
self._Token = Ch
|
||||
return self._Token
|
||||
|
||||
raise BadExpression(ERR_VALID_TOKEN % Expr)
|
||||
|
||||
# Parse operator
|
||||
def _GetOperator(self):
|
||||
self.__SkipWS()
|
||||
LegalOpLst = ['&&', '||', '!=', '==', '>=', '<='] + self.NonLetterOpLst
|
||||
|
||||
self._Token = ''
|
||||
Expr = self._Expr[self._Idx:]
|
||||
|
||||
# Reach end of expression
|
||||
if not Expr:
|
||||
return ''
|
||||
|
||||
# Script operator: LT, GT, LE, GE, EQ, NE, and, or, xor, not
|
||||
if Expr[0].isalpha():
|
||||
return self.__GetIdToken(True)
|
||||
|
||||
# Start to get regular operator: +, -, <, > ...
|
||||
if Expr[0] not in self.NonLetterOpLst:
|
||||
return ''
|
||||
|
||||
OpToken = ''
|
||||
for Ch in Expr:
|
||||
if Ch in self.NonLetterOpLst:
|
||||
if '!' == Ch and OpToken:
|
||||
break
|
||||
self._Idx += 1
|
||||
OpToken += Ch
|
||||
else:
|
||||
break
|
||||
|
||||
if OpToken not in LegalOpLst:
|
||||
raise BadExpression(ERR_OPERATOR_UNSUPPORT % OpToken)
|
||||
self._Token = OpToken
|
||||
return OpToken
|
||||
|
||||
# Check if current token matches the operators given from OpList
|
||||
def _IsOperator(self, OpList):
|
||||
Idx = self._Idx
|
||||
self._GetOperator()
|
||||
if self._Token in OpList:
|
||||
if self._Token in self.LogicalOperators:
|
||||
self._Token = self.LogicalOperators[self._Token]
|
||||
return True
|
||||
self._Idx = Idx
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# UTRangeList()
|
|
@ -0,0 +1,57 @@
|
|||
# # @file
|
||||
#
|
||||
# This file is used to handle the variable attributes and property information
|
||||
#
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. All rights reserved.<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.
|
||||
#
|
||||
|
||||
class VariableAttributes(object):
|
||||
EFI_VARIABLE_NON_VOLATILE = 0x00000001
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS = 0x00000002
|
||||
EFI_VARIABLE_RUNTIME_ACCESS = 0x00000004
|
||||
VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY = 0x00000001
|
||||
VarAttributesMap = {
|
||||
"NV":EFI_VARIABLE_NON_VOLATILE,
|
||||
"BS":EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
"RT":EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
"RO":VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def GetVarAttributes(var_attr_str):
|
||||
VarAttr = 0x00000000
|
||||
VarProp = 0x00000000
|
||||
|
||||
attr_list = var_attr_str.split(",")
|
||||
for attr in attr_list:
|
||||
attr = attr.strip()
|
||||
if attr == 'RO':
|
||||
VarProp = VariableAttributes.VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY
|
||||
else:
|
||||
VarAttr = VarAttr | VariableAttributes.VarAttributesMap.get(attr, 0x00000000)
|
||||
return VarAttr, VarProp
|
||||
@staticmethod
|
||||
def ValidateVarAttributes(var_attr_str):
|
||||
if not var_attr_str:
|
||||
return True, ""
|
||||
attr_list = var_attr_str.split(",")
|
||||
attr_temp = []
|
||||
for attr in attr_list:
|
||||
attr = attr.strip()
|
||||
attr_temp.append(attr)
|
||||
if attr not in VariableAttributes.VarAttributesMap:
|
||||
return False, "The variable attribute %s is not support to be specified in dsc file. Supported variable attribute are ['BS','NV','RT','RO'] "
|
||||
if 'RT' in attr_temp and 'BS' not in attr_temp:
|
||||
return False, "the RT attribute need the BS attribute to be present"
|
||||
return True, ""
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# This file is used to define common items of class object
|
||||
#
|
||||
# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -270,7 +270,7 @@ class PpiClass(GuidProtocolPpiCommonClass):
|
|||
#
|
||||
class SkuInfoClass(object):
|
||||
def __init__(self, SkuIdName = '', SkuId = '', VariableName = '', VariableGuid = '', VariableOffset = '',
|
||||
HiiDefaultValue = '', VpdOffset = '', DefaultValue = '', VariableGuidValue = ''):
|
||||
HiiDefaultValue = '', VpdOffset = '', DefaultValue = '', VariableGuidValue = '', VariableAttribute = ''):
|
||||
self.SkuIdName = SkuIdName
|
||||
self.SkuId = SkuId
|
||||
|
||||
|
@ -282,6 +282,7 @@ class SkuInfoClass(object):
|
|||
self.VariableGuidValue = VariableGuidValue
|
||||
self.VariableOffset = VariableOffset
|
||||
self.HiiDefaultValue = HiiDefaultValue
|
||||
self.VariableAttribute = VariableAttribute
|
||||
|
||||
#
|
||||
# Used by Vpd
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# This file is used to define each component of the build database
|
||||
#
|
||||
# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -44,7 +44,7 @@ from Common.BuildToolError import *
|
|||
# @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 = {}, IsOverrided = False, GuidValue = None):
|
||||
def __init__(self, Name = None, Guid = None, Type = None, DatumType = None, Value = None, Token = None, MaxDatumSize = None, SkuInfoList = {}, IsOverrided = False, GuidValue = None, validateranges = [], validlists = [], expressions = []):
|
||||
self.TokenCName = Name
|
||||
self.TokenSpaceGuidCName = Guid
|
||||
self.TokenSpaceGuidValue = GuidValue
|
||||
|
@ -59,6 +59,9 @@ class PcdClassObject(object):
|
|||
self.IsOverrided = IsOverrided
|
||||
self.IsFromBinaryInf = False
|
||||
self.IsFromDsc = False
|
||||
self.validateranges = validateranges
|
||||
self.validlists = validlists
|
||||
self.expressions = expressions
|
||||
|
||||
## Convert the class to a string
|
||||
#
|
||||
|
|
|
@ -376,7 +376,8 @@ class MetaFileParser(object):
|
|||
File=self.MetaFile,
|
||||
Line=self._LineIndex + 1
|
||||
)
|
||||
|
||||
def GetValidExpression(self, TokenSpaceGuid, PcdCName):
|
||||
return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)
|
||||
def _GetMacros(self):
|
||||
Macros = {}
|
||||
Macros.update(self._FileLocalMacros)
|
||||
|
@ -814,6 +815,7 @@ class DscParser(MetaFileParser):
|
|||
"PLATFORM_VERSION",
|
||||
"SKUID_IDENTIFIER",
|
||||
"PCD_INFO_GENERATION",
|
||||
"PCD_VAR_CHECK_GENERATION",
|
||||
"SUPPORTED_ARCHITECTURES",
|
||||
"BUILD_TARGETS",
|
||||
"OUTPUT_DIRECTORY",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# This file is used to create/update/query/erase a meta file table
|
||||
#
|
||||
# Copyright (c) 2008, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -225,6 +225,26 @@ class PackageTable(MetaFileTable):
|
|||
SqlCommand = "SELECT %s FROM %s WHERE %s" % (ValueString, self.Table, ConditionString)
|
||||
return self.Exec(SqlCommand)
|
||||
|
||||
def GetValidExpression(self, TokenSpaceGuid, PcdCName):
|
||||
SqlCommand = "select Value1 from %s WHERE Value2='%s' and Value3='%s'" % (self.Table, TokenSpaceGuid, PcdCName)
|
||||
self.Cur.execute(SqlCommand)
|
||||
validateranges = []
|
||||
validlists = []
|
||||
expressions = []
|
||||
for row in self.Cur:
|
||||
comment = row[0]
|
||||
comment = comment.strip("#")
|
||||
comment = comment.strip()
|
||||
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())
|
||||
return set(validateranges), set(validlists), set(expressions)
|
||||
## Python class representation of table storing platform data
|
||||
class PlatformTable(MetaFileTable):
|
||||
_COLUMN_ = '''
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# This file is used to create a database used by build tool
|
||||
#
|
||||
# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -38,7 +38,7 @@ from Common.Misc import AnalyzeDscPcd
|
|||
from Common.Misc import ProcessDuplicatedInf
|
||||
import re
|
||||
from Common.Parsing import IsValidWord
|
||||
|
||||
from Common.VariableAttributes import VariableAttributes
|
||||
import Common.GlobalData as GlobalData
|
||||
|
||||
## Platform build information from DSC file
|
||||
|
@ -133,6 +133,7 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
self._SkuName = None
|
||||
self._SkuIdentifier = None
|
||||
self._PcdInfoFlag = None
|
||||
self._VarCheckFlag = None
|
||||
self._FlashDefinition = None
|
||||
self._BuildNumber = None
|
||||
self._MakefileName = None
|
||||
|
@ -233,6 +234,8 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
self._SkuIdentifier = Record[2]
|
||||
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)
|
||||
|
@ -352,6 +355,13 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
return True
|
||||
else:
|
||||
return False
|
||||
def _GetVarCheckFlag(self):
|
||||
if self._VarCheckFlag == None or self._VarCheckFlag.upper() == 'FALSE':
|
||||
return False
|
||||
elif self._VarCheckFlag.upper() == 'TRUE':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _GetSkuIdentifier(self):
|
||||
if self._SkuName:
|
||||
|
@ -898,6 +908,17 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
|
||||
return Pcds
|
||||
|
||||
def CompareVarAttr(self, 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
|
||||
## Retrieve dynamic HII PCD settings
|
||||
#
|
||||
# @param Type PCD type
|
||||
|
@ -907,6 +928,7 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
def _GetDynamicHiiPcd(self, Type):
|
||||
|
||||
SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds)
|
||||
VariableAttrs = {}
|
||||
|
||||
Pcds = sdict()
|
||||
#
|
||||
|
@ -931,8 +953,12 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
|
||||
if Setting == None:
|
||||
continue
|
||||
VariableName, VariableGuid, VariableOffset, DefaultValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
|
||||
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():
|
||||
|
@ -955,8 +981,14 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
|
||||
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 self.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)]))
|
||||
|
||||
SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue)
|
||||
SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute = VarAttribute)
|
||||
pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid]
|
||||
if (PcdCName,TokenSpaceGuid) in Pcds.keys():
|
||||
pcdObject = Pcds[PcdCName,TokenSpaceGuid]
|
||||
pcdObject.SkuInfoList[SkuName] = SkuInfo
|
||||
|
@ -971,7 +1003,10 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
'',
|
||||
{SkuName : SkuInfo},
|
||||
False,
|
||||
None
|
||||
None,
|
||||
pcdDecObject.validateranges,
|
||||
pcdDecObject.validlists,
|
||||
pcdDecObject.expressions
|
||||
)
|
||||
|
||||
|
||||
|
@ -1143,6 +1178,7 @@ class DscBuildData(PlatformBuildClassObject):
|
|||
SkuName = property(_GetSkuName, _SetSkuName)
|
||||
SkuIdentifier = property(_GetSkuIdentifier)
|
||||
PcdInfoFlag = property(_GetPcdInfoFlag)
|
||||
VarCheckFlag = property(_GetVarCheckFlag)
|
||||
FlashDefinition = property(_GetFdfFile)
|
||||
BuildNumber = property(_GetBuildNumber)
|
||||
MakefileName = property(_GetMakefileName)
|
||||
|
@ -1462,6 +1498,7 @@ class DecBuildData(PackageBuildClassObject):
|
|||
|
||||
DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)
|
||||
|
||||
validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName)
|
||||
Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject(
|
||||
PcdCName,
|
||||
TokenSpaceGuid,
|
||||
|
@ -1472,7 +1509,10 @@ class DecBuildData(PackageBuildClassObject):
|
|||
'',
|
||||
{},
|
||||
False,
|
||||
None
|
||||
None,
|
||||
list(validateranges),
|
||||
list(validlists),
|
||||
list(expressions)
|
||||
)
|
||||
return Pcds
|
||||
|
||||
|
|
Loading…
Reference in New Issue