BaseTools: Support PCD flexible values format

https://bugzilla.tianocore.org/show_bug.cgi?id=541

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
Yonghong Zhu
2017-12-26 16:17:13 +08:00
parent 68ba919f78
commit 726c501c2c
9 changed files with 430 additions and 114 deletions

View File

@ -271,6 +271,7 @@ class WorkspaceAutoGen(AutoGen):
self._FvDir = None self._FvDir = None
self._MakeFileDir = None self._MakeFileDir = None
self._BuildCommand = None self._BuildCommand = None
self._GuidDict = {}
# there's many relative directory operations, so ... # there's many relative directory operations, so ...
os.chdir(self.WorkspaceDir) os.chdir(self.WorkspaceDir)
@ -418,12 +419,23 @@ class WorkspaceAutoGen(AutoGen):
FoundFlag = False FoundFlag = False
PcdDatumType = '' PcdDatumType = ''
NewValue = '' NewValue = ''
for package in PGen.PackageList:
Guids = package.Guids
self._GuidDict.update(Guids)
for package in PGen.PackageList: for package in PGen.PackageList:
for key in package.Pcds: for key in package.Pcds:
PcdItem = package.Pcds[key] PcdItem = package.Pcds[key]
if HasTokenSpace: if HasTokenSpace:
if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName): if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
PcdDatumType = PcdItem.DatumType PcdDatumType = PcdItem.DatumType
if pcdvalue.startswith('H'):
try:
pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
except BadExpression, Value:
if Value.result > 1:
EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
(TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
pcdvalue = 'H' + pcdvalue
NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue) NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
FoundFlag = True FoundFlag = True
else: else:
@ -433,6 +445,13 @@ class WorkspaceAutoGen(AutoGen):
TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName) TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
PcdDatumType = PcdItem.DatumType PcdDatumType = PcdItem.DatumType
TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
if pcdvalue.startswith('H'):
try:
pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
(TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
pcdvalue = 'H' + pcdvalue
NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue) NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
FoundFlag = True FoundFlag = True
else: else:
@ -2446,6 +2465,26 @@ class PlatformAutoGen(AutoGen):
ToPcd.DatumType = FromPcd.DatumType ToPcd.DatumType = FromPcd.DatumType
if FromPcd.SkuInfoList not in [None, '', []]: if FromPcd.SkuInfoList not in [None, '', []]:
ToPcd.SkuInfoList = FromPcd.SkuInfoList ToPcd.SkuInfoList = FromPcd.SkuInfoList
# Add Flexible PCD format parse
PcdValue = ToPcd.DefaultValue
if PcdValue:
try:
ToPcd.DefaultValue = ValueExpression(PcdValue)(True)
except WrnExpression, Value:
ToPcd.DefaultValue = Value.result
except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
File=self.MetaFile)
if ToPcd.DefaultValue:
_GuidDict = {}
for Pkg in self.PackageList:
Guids = Pkg.Guids
_GuidDict.update(Guids)
try:
ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, _GuidDict)(True)
except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
File=self.MetaFile)
# check the validation of datum # check the validation of datum
IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue) IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)

View File

@ -1033,6 +1033,8 @@ def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd):
if Pcd.DatumType in ['UINT64', 'UINT32', 'UINT16', 'UINT8']: if Pcd.DatumType in ['UINT64', 'UINT32', 'UINT16', 'UINT8']:
try: try:
if Value.upper().endswith('L'):
Value = Value[:-1]
if Value.upper().startswith('0X'): if Value.upper().startswith('0X'):
ValueNumber = int (Value, 16) ValueNumber = int (Value, 16)
else: else:

View File

@ -15,7 +15,9 @@
from Common.GlobalData import * from Common.GlobalData import *
from CommonDataClass.Exceptions import BadExpression from CommonDataClass.Exceptions import BadExpression
from CommonDataClass.Exceptions import WrnExpression from CommonDataClass.Exceptions import WrnExpression
from Misc import GuidStringToGuidStructureString from Misc import GuidStringToGuidStructureString, ParseFieldValue
import Common.EdkLogger as EdkLogger
import copy
ERR_STRING_EXPR = 'This operator cannot be used in string expression: [%s].' 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_SNYTAX = 'Syntax error, the rest of expression cannot be evaluated: [%s].'
@ -114,6 +116,15 @@ def ReplaceExprMacro(String, Macros, ExceptionList = None):
StrList[i] = RetStr StrList[i] = RetStr
return ''.join(StrList) return ''.join(StrList)
# transfer int to string for in/not in expression
def IntToStr(Value):
StrList = []
while Value > 0:
StrList.append(chr(Value & 0xff))
Value = Value >> 8
Value = '"' + ''.join(StrList) + '"'
return Value
SupportedInMacroList = ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH', 'FAMILY'] SupportedInMacroList = ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH', 'FAMILY']
class ValueExpression(object): class ValueExpression(object):
@ -146,10 +157,24 @@ class ValueExpression(object):
def Eval(Operator, Oprand1, Oprand2 = None): def Eval(Operator, Oprand1, Oprand2 = None):
WrnExp = None WrnExp = None
if Operator not in ["==", "!=", ">=", "<=", ">", "<", "in", "not in"] and \ if Operator not in ["in", "not in"] and (type(Oprand1) == type('') or type(Oprand2) == type('')):
(type(Oprand1) == type('') or type(Oprand2) == type('')): if type(Oprand1) == type(''):
raise BadExpression(ERR_STRING_EXPR % Operator) if Oprand1[0] in ['"', "'"] or Oprand1.startswith('L"') or Oprand1.startswith("L'")or Oprand1.startswith('UINT'):
Oprand1, Size = ParseFieldValue(Oprand1)
else:
Oprand1,Size = ParseFieldValue('"' + Oprand1 + '"')
if type(Oprand2) == type(''):
if Oprand2[0] in ['"', "'", 'L'] or Oprand2.startswith('UINT'):
Oprand2, Size = ParseFieldValue(Oprand2)
else:
Oprand2, Size = ParseFieldValue('"' + Oprand2 + '"')
if type(Oprand1) == type('') or type(Oprand2) == type(''):
raise BadExpression(ERR_STRING_EXPR % Operator)
if Operator in ['in', 'not in']:
if type(Oprand1) != type(''):
Oprand1 = IntToStr(Oprand1)
if type(Oprand2) != type(''):
Oprand2 = IntToStr(Oprand2)
TypeDict = { TypeDict = {
type(0) : 0, type(0) : 0,
type(0L) : 0, type(0L) : 0,
@ -226,6 +251,9 @@ class ValueExpression(object):
self._Expr = Expression self._Expr = Expression
self._NoProcess = True self._NoProcess = True
return return
if Expression.strip().startswith('{') and Expression.strip().endswith('}'):
self._Expr = Expression
self._NoProcess = True
self._Expr = ReplaceExprMacro(Expression.strip(), self._Expr = ReplaceExprMacro(Expression.strip(),
SymbolTable, SymbolTable,
@ -237,7 +265,7 @@ class ValueExpression(object):
# #
# The symbol table including PCD and macro mapping # The symbol table including PCD and macro mapping
# #
self._Symb = SymbolTable self._Symb = copy.deepcopy(SymbolTable)
self._Symb.update(self.LogicalOperators) self._Symb.update(self.LogicalOperators)
self._Idx = 0 self._Idx = 0
self._Len = len(self._Expr) self._Len = len(self._Expr)
@ -284,7 +312,7 @@ class ValueExpression(object):
elif not Val: elif not Val:
Val = False Val = False
RealVal = '""' RealVal = '""'
elif not Val.startswith('L"') and not Val.startswith('{'): elif not Val.startswith('L"') and not Val.startswith('{') and not Val.startswith("L'"):
Val = True Val = True
RealVal = '"' + RealVal + '"' RealVal = '"' + RealVal + '"'
@ -426,6 +454,15 @@ class ValueExpression(object):
Radix = 10 Radix = 10
if self._Token.lower()[0:2] == '0x' and len(self._Token) > 2: if self._Token.lower()[0:2] == '0x' and len(self._Token) > 2:
Radix = 16 Radix = 16
if self._Token.startswith('"') or self._Token.startswith("'")\
or self._Token.startswith("L'") or self._Token.startswith('L"'):
Flag = 0
for Index in range(len(self._Token)):
if self._Token[Index] in ['"', "'"]:
Flag += 1
if Flag == 2:
self._Token = ParseFieldValue(self._Token)[0]
return True
try: try:
self._Token = int(self._Token, Radix) self._Token = int(self._Token, Radix)
return True return True
@ -473,10 +510,12 @@ class ValueExpression(object):
Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace('\\\"', '\\\'') Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace('\\\"', '\\\'')
for Ch in Expr: for Ch in Expr:
self._Idx += 1 self._Idx += 1
if Ch == '"': if Ch == '"' or Ch == "'":
break break
self._Token = self._LiteralToken = self._Expr[Idx:self._Idx] self._Token = self._LiteralToken = self._Expr[Idx:self._Idx]
if not self._Token.endswith('"'): if self._Token.startswith('"') and not self._Token.endswith('"'):
raise BadExpression(ERR_STRING_TOKEN % self._Token)
if self._Token.startswith("'") and not self._Token.endswith("'"):
raise BadExpression(ERR_STRING_TOKEN % self._Token) raise BadExpression(ERR_STRING_TOKEN % self._Token)
self._Token = self._Token[1:-1] self._Token = self._Token[1:-1]
return self._Token return self._Token
@ -578,7 +617,44 @@ class ValueExpression(object):
self._Idx += 1 self._Idx += 1
UStr = self.__GetString() UStr = self.__GetString()
self._Token = 'L"' + UStr + '"' self._Token = 'L"' + UStr + '"'
self._Token, Size = ParseFieldValue(self._Token)
return self._Token return self._Token
elif Expr.startswith("L'"):
# Skip L
self._Idx += 1
UStr = self.__GetString()
self._Token = "L'" + UStr + "'"
self._Token, Size = ParseFieldValue(self._Token)
return self._Token
elif Expr.startswith('"'):
UStr = self.__GetString()
self._Token = '"' + UStr + '"'
self._Token, Size = ParseFieldValue(self._Token)
return self._Token
elif Expr.startswith("'"):
UStr = self.__GetString()
self._Token = "'" + UStr + "'"
self._Token, Size = ParseFieldValue(self._Token)
return self._Token
elif Expr.startswith('UINT'):
Re = re.compile('(?:UINT8|UINT16|UINT32|UINT64)\((.+)\)')
try:
RetValue = Re.search(Expr).group(1)
except:
raise BadExpression('Invalid Expression %s' % Expr)
Idx = self._Idx
for Ch in Expr:
self._Idx += 1
if Ch == '(':
Prefix = self._Expr[Idx:self._Idx - 1]
Idx = self._Idx
if Ch == ')':
TmpValue = self._Expr[Idx :self._Idx - 1]
TmpValue = ValueExpression(TmpValue)(True)
TmpValue = '0x%x' % int(TmpValue) if type(TmpValue) != type('') else TmpValue
break
self._Token, Size = ParseFieldValue(Prefix + '(' + TmpValue + ')')
return self._Token
self._Token = '' self._Token = ''
if Expr: if Expr:
@ -648,6 +724,158 @@ class ValueExpression(object):
self._Idx = Idx self._Idx = Idx
return False return False
class ValueExpressionEx(ValueExpression):
def __init__(self, PcdValue, PcdType, SymbolTable={}):
ValueExpression.__init__(self, PcdValue, SymbolTable)
self.PcdValue = PcdValue
self.PcdType = PcdType
def __call__(self, RealValue=False, Depth=0):
PcdValue = self.PcdValue
try:
PcdValue = ValueExpression.__call__(self, RealValue, Depth)
except WrnExpression, Value:
PcdValue = Value.result
if PcdValue == 'True':
PcdValue = '1'
if PcdValue == 'False':
PcdValue = '0'
if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
PcdValue = PcdValue.strip()
if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):
PcdValue = PcdValue[1:-1].split(',')
if type(PcdValue) == type([]):
TmpValue = 0
Size = 0
for Item in PcdValue:
if Item.startswith('UINT16'):
ItemSize = 2
elif Item.startswith('UINT32'):
ItemSize = 4
elif Item.startswith('UINT64'):
ItemSize = 8
else:
ItemSize = 0
Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
if ItemSize == 0:
ItemValue, ItemSize = ParseFieldValue(Item)
else:
ItemValue = ParseFieldValue(Item)[0]
if type(ItemValue) == type(''):
ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)
TmpValue = (ItemValue << (Size * 8)) | TmpValue
Size = Size + ItemSize
else:
TmpValue, Size = ParseFieldValue(PcdValue)
if type(TmpValue) == type(''):
TmpValue = int(TmpValue)
else:
PcdValue = '0x%0{}X'.format(Size) % (TmpValue)
if TmpValue < 0:
raise BadExpression('Type %s PCD Value is negative' % self.PcdType)
if self.PcdType == 'UINT8' and Size > 1:
raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)
if self.PcdType == 'UINT16' and Size > 2:
raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)
if self.PcdType == 'UINT32' and Size > 4:
raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)
if self.PcdType == 'UINT64' and Size > 8:
raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)
if self.PcdType in ['VOID*']:
try:
TmpValue = long(PcdValue)
TmpList = []
if TmpValue.bit_length() == 0:
PcdValue = '{0x00}'
else:
for I in range((TmpValue.bit_length() + 7) / 8):
TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))
PcdValue = '{' + ', '.join(TmpList) + '}'
except:
if PcdValue.strip().startswith('{'):
PcdValue = PcdValue.strip()[1:-1].strip()
Size = 0
ValueStr = ''
TokenSpaceGuidName = ''
if PcdValue.startswith('GUID') and PcdValue.endswith(')'):
try:
TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)
except:
pass
if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:
PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'
elif TokenSpaceGuidName:
raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)
ListItem, Size = ParseFieldValue(PcdValue)
elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):
ListItem, Size = ParseFieldValue(PcdValue)
else:
ListItem = PcdValue.split(',')
if type(ListItem) == type(0) or type(ListItem) == type(0L):
for Index in range(0, Size):
ValueStr += '0x%02X' % (int(ListItem) & 255)
ListItem >>= 8
ValueStr += ', '
PcdValue = '{' + ValueStr[:-2] + '}'
elif type(ListItem) == type(''):
if ListItem.startswith('{') and ListItem.endswith('}'):
PcdValue = ListItem
else:
LabelDict = {}
ReLabel = re.compile('LABEL\((\w+)\)')
ReOffset = re.compile('OFFSET_OF\((\w+)\)')
for Index, Item in enumerate(ListItem):
# for LABEL parse
Item = Item.strip()
try:
LabelList = ReLabel.findall(Item)
for Label in LabelList:
if Label not in LabelDict.keys():
LabelDict[Label] = str(Index)
Item = ReLabel.sub('', Item)
except:
pass
try:
OffsetList = ReOffset.findall(Item)
except:
pass
for Offset in OffsetList:
if Offset in LabelDict.keys():
Re = re.compile('OFFSET_OF\(%s\)'% Offset)
Item = Re.sub(LabelDict[Offset], Item)
else:
raise BadExpression('%s not defined before use' % Offset)
if Item.startswith('UINT16'):
ItemSize = 2
elif Item.startswith('UINT32'):
ItemSize = 4
elif Item.startswith('UINT64'):
ItemSize = 8
else:
ItemSize = 0
TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)
Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue
if ItemSize == 0:
ItemValue, ItemSize = ParseFieldValue(Item)
else:
ItemValue = ParseFieldValue(Item)[0]
for I in range(0, ItemSize):
ValueStr += '0x%02X' % (int(ItemValue) & 255)
ItemValue >>= 8
ValueStr += ', '
Size += ItemSize
if Size > 0:
PcdValue = '{' + ValueStr[:-2] + '}'
if RealValue:
return PcdValue
if __name__ == '__main__': if __name__ == '__main__':
pass pass
while True: while True:

View File

@ -37,6 +37,7 @@ from Parsing import GetSplitValueList
from Common.LongFilePathSupport import OpenLongFilePath as open from Common.LongFilePathSupport import OpenLongFilePath as open
from Common.MultipleWorkspace import MultipleWorkspace as mws from Common.MultipleWorkspace import MultipleWorkspace as mws
import uuid import uuid
from CommonDataClass.Exceptions import BadExpression
## Regular expression used to find out place holders in string template ## Regular expression used to find out place holders in string template
gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE) gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)
@ -1472,99 +1473,119 @@ def AnalyzePcdExpression(Setting):
return FieldList return FieldList
def ParseDevPathValue (Value):
pass
def ParseFieldValue (Value): def ParseFieldValue (Value):
if type(Value) == type(0): if type(Value) == type(0):
return Value, (Value.bit_length() + 7) / 8 return Value, (Value.bit_length() + 7) / 8
if type(Value) <> type(''): if type(Value) <> type(''):
raise ValueError raise BadExpression('Type %s is %s' %(Value, type(Value)))
Value = Value.strip() Value = Value.strip()
if Value.startswith('UINT8') and Value.endswith(')'): if Value.startswith('UINT8') and Value.endswith(')'):
Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1]) Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
if Size > 1: if Size > 1:
raise ValueError raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))
return Value, 1
if Value.startswith('UINT16') and Value.endswith(')'):
Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
if Size > 2:
raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))
return Value, 2
if Value.startswith('UINT32') and Value.endswith(')'):
Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
if Size > 4:
raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))
return Value, 4
if Value.startswith('UINT64') and Value.endswith(')'):
Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
if Size > 8:
raise BadExpression('Value (%s) Size larger than %d' % (Value, Size))
return Value, 8
if Value.startswith('GUID') and Value.endswith(')'):
Value = Value.split('(', 1)[1][:-1].strip()
if Value[0] == '{' and Value[-1] == '}':
Value = Value[1:-1].strip()
Value = Value.split('{', 1)
Value = ['%02x' % int(Item, 16) for Item in (Value[0] + Value[1][:-1]).split(',')]
if len(Value[0]) != 8:
Value[0] = '%08X' % int(Value[0], 16)
if len(Value[1]) != 4:
Value[1] = '%04X' % int(Value[1], 16)
if len(Value[2]) != 4:
Value[2] = '%04X' % int(Value[2], 16)
Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11])
if Value[0] == '"' and Value[-1] == '"':
Value = Value[1:-1]
try:
Value = "'" + uuid.UUID(Value).get_bytes_le() + "'"
except ValueError, Message:
raise BadExpression('%s' % Message)
Value, Size = ParseFieldValue(Value)
return Value, 16
if Value.startswith('L"') and Value.endswith('"'):
# Unicode String
List = list(Value[2:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 16) | ord(Char)
return Value, (len(List) + 1) * 2
if Value.startswith('"') and Value.endswith('"'):
# ASCII String
List = list(Value[1:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 8) | ord(Char)
return Value, len(List) + 1
if Value.startswith("L'") and Value.endswith("'"):
# Unicode Character Constant
List = list(Value[2:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 16) | ord(Char)
return Value, len(List) * 2
if Value.startswith("'") and Value.endswith("'"):
# Character constant
List = list(Value[1:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 8) | ord(Char)
return Value, len(List)
if Value.startswith('{') and Value.endswith('}'):
# Byte array
Value = Value[1:-1]
List = [Item.strip() for Item in Value.split(',')]
List.reverse()
Value = 0
RetSize = 0
for Item in List:
ItemValue, Size = ParseFieldValue(Item)
RetSize += Size
for I in range(Size):
Value = (Value << 8) | ((ItemValue >> 8 * I) & 0xff)
return Value, RetSize
if Value.startswith('DEVICE_PATH(') and Value.endswith(')'):
Value = Value.split('"')[1]
return ParseDevPathValue(Value)
if Value.lower().startswith('0x'):
Value = int(Value, 16)
if Value == 0:
return 0, 1
return Value, (Value.bit_length() + 7) / 8
if Value[0].isdigit():
Value = int(Value, 10)
if Value == 0:
return 0, 1
return Value, (Value.bit_length() + 7) / 8
if Value.lower() == 'true':
return 1, 1
if Value.lower() == 'false':
return 0, 1
return Value, 1 return Value, 1
if Value.startswith('UINT16') and Value.endswith(')'):
Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
if Size > 2:
raise ValueError
return Value, 2
if Value.startswith('UINT32') and Value.endswith(')'):
Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
if Size > 4:
raise ValueError
return Value, 4
if Value.startswith('UINT64') and Value.endswith(')'):
Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
if Size > 8:
raise ValueError
return Value, 8
if Value.startswith('GUID') and Value.endswith(')'):
Value = Value.split('(', 1)[1][:-1].strip()
if Value[0] == '{' and Value[-1] == '}':
Value = Value[1:-1].strip()
Value = Value.split('{', 1)
Value = [Item.strip()[2:] for Item in (Value[0] + Value[1][:-1]).split(',')]
Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11])
if Value[0] == '"' and Value[-1] == '"':
Value = Value[1:-1]
Value = "'" + uuid.UUID(Value).get_bytes_le() + "'"
Value, Size = ParseFieldValue(Value)
return Value, 16
if Value.startswith('L"') and Value.endswith('"'):
# Unicode String
List = list(Value[2:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 16) | ord(Char)
return Value, (len(List) + 1) * 2
if Value.startswith('"') and Value.endswith('"'):
# ASCII String
List = list(Value[1:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 8) | ord(Char)
return Value, len(List) + 1
if Value.startswith("L'") and Value.endswith("'"):
# Unicode Character Constant
List = list(Value[2:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 16) | ord(Char)
return Value, len(List) * 2
if Value.startswith("'") and Value.endswith("'"):
# Character constant
List = list(Value[1:-1])
List.reverse()
Value = 0
for Char in List:
Value = (Value << 8) | ord(Char)
return Value, len(List)
if Value.startswith('{') and Value.endswith('}'):
# Byte array
Value = Value[1:-1]
List = [Item.strip() for Item in Value.split(',')]
List.reverse()
Value = 0
for Item in List:
ItemValue, Size = ParseFieldValue(Item)
if Size > 1:
raise ValueError
Value = (Value << 8) | ItemValue
return Value, len(List)
if Value.lower().startswith('0x'):
Value = int(Value, 16)
return Value, (Value.bit_length() + 7) / 8
if Value[0].isdigit():
Value = int(Value, 10)
return Value, (Value.bit_length() + 7) / 8
if Value.lower() == 'true':
return 1, 1
if Value.lower() == 'false':
return 0, 1
return Value, 1
## AnalyzeDscPcd ## AnalyzeDscPcd
# #

View File

@ -800,7 +800,7 @@ class DscBuildData(PlatformBuildClassObject):
ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain] ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
PkgSet.update(ModuleData.Packages) PkgSet.update(ModuleData.Packages)
self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet) self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
if (PcdCName, TokenSpaceGuid) not in self._DecPcds: if (PcdCName, TokenSpaceGuid) not in self._DecPcds:
@ -821,6 +821,8 @@ class DscBuildData(PlatformBuildClassObject):
ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True) ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)
except WrnExpression, Value: except WrnExpression, Value:
ValueList[Index] = Value.result ValueList[Index] = Value.result
except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
except EvaluationException, Excpt: except EvaluationException, Excpt:
if hasattr(Excpt, 'Pcd'): if hasattr(Excpt, 'Pcd'):
if Excpt.Pcd in GlobalData.gPlatformOtherPcds: if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
@ -834,11 +836,13 @@ class DscBuildData(PlatformBuildClassObject):
else: else:
EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt), EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
File=self.MetaFile, Line=LineNo) File=self.MetaFile, Line=LineNo)
if ValueList[Index] == 'True':
ValueList[Index] = '1'
elif ValueList[Index] == 'False':
ValueList[Index] = '0'
if ValueList[Index]: if ValueList[Index]:
DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType
try:
ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)
except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,
ExtraData="PCD [%s.%s] Value \"%s\" " % (TokenSpaceGuid, PcdCName, ValueList[Index]))
Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index]) Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])
if not Valid: if not Valid:
EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo, EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,
@ -2058,7 +2062,7 @@ class DscBuildData(PlatformBuildClassObject):
continue continue
ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain] ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
PkgSet.update(ModuleData.Packages) PkgSet.update(ModuleData.Packages)
self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet) self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)
return self._DecPcds return self._DecPcds
_Macros = property(_GetMacros) _Macros = property(_GetMacros)
Arch = property(_GetArch, _SetArch) Arch = property(_GetArch, _SetArch)

View File

@ -16,6 +16,7 @@ from Common.String import *
from Common.DataType import * from Common.DataType import *
from Common.Misc import * from Common.Misc import *
from types import * from types import *
from MetaFileParser import *
from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject
## Module build information from INF file ## Module build information from INF file
@ -1144,6 +1145,12 @@ class InfBuildData(ModuleBuildClassObject):
Pcd.InfDefaultValue = Pcd.DefaultValue Pcd.InfDefaultValue = Pcd.DefaultValue
if Pcd.DefaultValue in [None, '']: if Pcd.DefaultValue in [None, '']:
Pcd.DefaultValue = PcdInPackage.DefaultValue Pcd.DefaultValue = PcdInPackage.DefaultValue
else:
try:
Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue, Pcd.DatumType, self.Guids)(True)
except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid, PcdRealName, Pcd.DefaultValue, Value),
File=self.MetaFile, Line=LineNo)
break break
else: else:
EdkLogger.error( EdkLogger.error(

View File

@ -27,7 +27,7 @@ import Common.GlobalData as GlobalData
from CommonDataClass.DataClass import * from CommonDataClass.DataClass import *
from Common.DataType import * from Common.DataType import *
from Common.String import * from Common.String import *
from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue
from Common.Expression import * from Common.Expression import *
from CommonDataClass.Exceptions import * from CommonDataClass.Exceptions import *
from Common.LongFilePathSupport import OpenLongFilePath as open from Common.LongFilePathSupport import OpenLongFilePath as open
@ -182,6 +182,7 @@ class MetaFileParser(object):
self._PostProcessed = False self._PostProcessed = False
# Different version of meta-file has different way to parse. # Different version of meta-file has different way to parse.
self._Version = 0 self._Version = 0
self._GuidDict = {} # for Parser PCD value {GUID(gTokeSpaceGuidName)}
## Store the parsed data in table ## Store the parsed data in table
def _Store(self, *Args): def _Store(self, *Args):
@ -1871,6 +1872,8 @@ class DecParser(MetaFileParser):
File=self.MetaFile, Line=self._LineIndex + 1) File=self.MetaFile, Line=self._LineIndex + 1)
self._ValueList[0] = TokenList[0] self._ValueList[0] = TokenList[0]
self._ValueList[1] = TokenList[1] self._ValueList[1] = TokenList[1]
if self._ValueList[0] not in self._GuidDict:
self._GuidDict[self._ValueList[0]] = self._ValueList[1]
## PCD sections parser ## PCD sections parser
# #
@ -1987,12 +1990,14 @@ class DecParser(MetaFileParser):
ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True) ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)
except WrnExpression, Value: except WrnExpression, Value:
ValueList[0] = Value.result ValueList[0] = Value.result
except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)
if ValueList[0] == 'True': if ValueList[0]:
ValueList[0] = '1' try:
if ValueList[0] == 'False': ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
ValueList[0] = '0' except BadExpression, Value:
EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
# check format of default value against the datum type # check format of default value against the datum type
IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0]) IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
if not IsValid: if not IsValid:

View File

@ -1,7 +1,7 @@
## @file ## @file
# Common routines used by workspace # Common routines used by workspace
# #
# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials # This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # 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 # which accompanies this distribution. The full text of the license may be found at
@ -43,13 +43,17 @@ def GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain):
# @param Target: Current target # @param Target: Current target
# @param Toolchain: Current toolchain # @param Toolchain: Current toolchain
# @retval: A dictionary contains instances of PcdClassObject with key (PcdCName, TokenSpaceGuid) # @retval: A dictionary contains instances of PcdClassObject with key (PcdCName, TokenSpaceGuid)
# @retval: A dictionary contains real GUIDs of TokenSpaceGuid
# #
def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain,additionalPkgs): def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain,additionalPkgs):
PkgList = GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain) PkgList = GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain)
PkgList = set(PkgList) PkgList = set(PkgList)
PkgList |= additionalPkgs PkgList |= additionalPkgs
DecPcds = {} DecPcds = {}
GuidDict = {}
for Pkg in PkgList: for Pkg in PkgList:
Guids = Pkg.Guids
GuidDict.update(Guids)
for Pcd in Pkg.Pcds: for Pcd in Pkg.Pcds:
PcdCName = Pcd[0] PcdCName = Pcd[0]
PcdTokenName = Pcd[1] PcdTokenName = Pcd[1]
@ -60,7 +64,7 @@ def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain,additionalPk
break break
if (PcdCName, PcdTokenName) not in DecPcds.keys(): if (PcdCName, PcdTokenName) not in DecPcds.keys():
DecPcds[PcdCName, PcdTokenName] = Pkg.Pcds[Pcd] DecPcds[PcdCName, PcdTokenName] = Pkg.Pcds[Pcd]
return DecPcds return DecPcds, GuidDict
## Get all dependent libraries for a module ## Get all dependent libraries for a module
# #

View File

@ -45,6 +45,7 @@ from Common.Misc import PathClass
from Common.String import NormPath from Common.String import NormPath
from Common.DataType import * from Common.DataType import *
import collections import collections
from Common.Expression import ValueExpressionEx
## Pattern to extract contents in EDK DXS files ## Pattern to extract contents in EDK DXS files
gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL) gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)
@ -849,8 +850,11 @@ class PcdReport(object):
# Collect PCD DEC default value. # Collect PCD DEC default value.
# #
self.DecPcdDefault = {} self.DecPcdDefault = {}
self._GuidDict = {}
for Pa in Wa.AutoGenObjectList: for Pa in Wa.AutoGenObjectList:
for Package in Pa.PackageList: for Package in Pa.PackageList:
Guids = Package.Guids
self._GuidDict.update(Guids)
for (TokenCName, TokenSpaceGuidCName, DecType) in Package.Pcds: for (TokenCName, TokenSpaceGuidCName, DecType) in Package.Pcds:
DecDefaultValue = Package.Pcds[TokenCName, TokenSpaceGuidCName, DecType].DefaultValue DecDefaultValue = Package.Pcds[TokenCName, TokenSpaceGuidCName, DecType].DefaultValue
self.DecPcdDefault.setdefault((TokenCName, TokenSpaceGuidCName, DecType), DecDefaultValue) self.DecPcdDefault.setdefault((TokenCName, TokenSpaceGuidCName, DecType), DecDefaultValue)
@ -943,6 +947,8 @@ class PcdReport(object):
DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName)) DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
DscDefaultValBak= DscDefaultValue DscDefaultValBak= DscDefaultValue
DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue) DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue)
if DscDefaultValue:
DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)
InfDefaultValue = None InfDefaultValue = None
PcdValue = DecDefaultValue PcdValue = DecDefaultValue