X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FMisc.py;h=a2c6a6a0fbd842b00fce6a0a57523d7066ae5498;hb=e651d06c5ed167e706e2dbe122ec0953a54033f3;hp=777450d81860a1e9e92daf9d9405c68315a82eba;hpb=47fea6afd74af76c7e2a2b03d319b7ac035ac26a;p=mirror_edk2.git
diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
index 777450d818..a2c6a6a0fb 100644
--- a/BaseTools/Source/Python/Common/Misc.py
+++ b/BaseTools/Source/Python/Common/Misc.py
@@ -1,7 +1,7 @@
## @file
# Common routines used by all tools
#
-# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
# 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
@@ -36,6 +36,7 @@ from CommonDataClass.DataClass import *
from Parsing import GetSplitValueList
from Common.LongFilePathSupport import OpenLongFilePath as open
from Common.MultipleWorkspace import MultipleWorkspace as mws
+import uuid
## Regular expression used to find out place holders in string template
gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)
@@ -67,14 +68,32 @@ def GetVariableOffset(mapfilepath, efifilepath, varnames):
if (firstline.startswith("Archive member included ") and
firstline.endswith(" file (symbol)")):
return _parseForGCC(lines, efifilepath, varnames)
+ if firstline.startswith("# Path:"):
+ return _parseForXcode(lines, efifilepath, varnames)
return _parseGeneral(lines, efifilepath, varnames)
+def _parseForXcode(lines, efifilepath, varnames):
+ status = 0
+ ret = []
+ for index, line in enumerate(lines):
+ line = line.strip()
+ if status == 0 and line == "# Symbols:":
+ status = 1
+ continue
+ if status == 1 and len(line) != 0:
+ for varname in varnames:
+ if varname in line:
+ m = re.match('^([\da-fA-FxX]+)([\s\S]*)([_]*%s)$' % varname, line)
+ if m != None:
+ ret.append((varname, m.group(1)))
+ return ret
+
def _parseForGCC(lines, efifilepath, varnames):
""" Parse map file generated by GCC linker """
status = 0
sections = []
varoffset = []
- for line in lines:
+ for index, line in enumerate(lines):
line = line.strip()
# status machine transection
if status == 0 and line == "Memory Configuration":
@@ -88,14 +107,23 @@ def _parseForGCC(lines, efifilepath, varnames):
continue
# status handler
- if status == 2:
+ if status == 3:
m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line)
if m != None:
sections.append(m.groups(0))
for varname in varnames:
- m = re.match("^([\da-fA-Fx]+) +[_]*(%s)$" % varname, line)
+ Str = ''
+ m = re.match("^.data.(%s)" % varname, line)
if m != None:
- varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0]))
+ m = re.match(".data.(%s)$" % varname, line)
+ if m != None:
+ Str = lines[index + 1]
+ else:
+ Str = line[len(".data.%s" % varname):]
+ if Str:
+ m = re.match('^([\da-fA-Fx]+) +([\da-fA-Fx]+)', Str.strip())
+ if m != None:
+ varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0]))
if not varoffset:
return []
@@ -794,13 +822,18 @@ def GetRelPath(Path1, Path2):
#
# @param CName The CName of the GUID
# @param PackageList List of packages looking-up in
+# @param Inffile The driver file
#
# @retval GuidValue if the CName is found in any given package
# @retval None if the CName is not found in all given packages
#
-def GuidValue(CName, PackageList):
+def GuidValue(CName, PackageList, Inffile = None):
for P in PackageList:
- if CName in P.Guids:
+ GuidKeys = P.Guids.keys()
+ if Inffile and P._PrivateGuids:
+ if not Inffile.startswith(P.MetaFile.Dir):
+ GuidKeys = (dict.fromkeys(x for x in P.Guids if x not in P._PrivateGuids)).keys()
+ if CName in GuidKeys:
return P.Guids[CName]
return None
@@ -808,13 +841,18 @@ def GuidValue(CName, PackageList):
#
# @param CName The CName of the GUID
# @param PackageList List of packages looking-up in
+# @param Inffile The driver file
#
# @retval GuidValue if the CName is found in any given package
# @retval None if the CName is not found in all given packages
#
-def ProtocolValue(CName, PackageList):
+def ProtocolValue(CName, PackageList, Inffile = None):
for P in PackageList:
- if CName in P.Protocols:
+ ProtocolKeys = P.Protocols.keys()
+ if Inffile and P._PrivateProtocols:
+ if not Inffile.startswith(P.MetaFile.Dir):
+ ProtocolKeys = (dict.fromkeys(x for x in P.Protocols if x not in P._PrivateProtocols)).keys()
+ if CName in ProtocolKeys:
return P.Protocols[CName]
return None
@@ -822,13 +860,18 @@ def ProtocolValue(CName, PackageList):
#
# @param CName The CName of the GUID
# @param PackageList List of packages looking-up in
+# @param Inffile The driver file
#
# @retval GuidValue if the CName is found in any given package
# @retval None if the CName is not found in all given packages
#
-def PpiValue(CName, PackageList):
+def PpiValue(CName, PackageList, Inffile = None):
for P in PackageList:
- if CName in P.Ppis:
+ PpiKeys = P.Ppis.keys()
+ if Inffile and P._PrivatePpis:
+ if not Inffile.startswith(P.MetaFile.Dir):
+ PpiKeys = (dict.fromkeys(x for x in P.Ppis if x not in P._PrivatePpis)).keys()
+ if CName in PpiKeys:
return P.Ppis[CName]
return None
@@ -1397,32 +1440,7 @@ def ParseConsoleLog(Filename):
Opr.close()
Opw.close()
-## AnalyzeDscPcd
-#
-# Analyze DSC PCD value, since there is no data type info in DSC
-# This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
-# 1. Feature flag: TokenSpace.PcdCName|PcdValue
-# 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
-# 3. Dynamic default:
-# TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
-# TokenSpace.PcdCName|PcdValue
-# 4. Dynamic VPD:
-# TokenSpace.PcdCName|VpdOffset[|VpdValue]
-# TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
-# 5. Dynamic HII:
-# TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
-# PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
-# there might have "|" operator, also in string value.
-#
-# @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
-# @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
-# @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
-# @retval:
-# ValueList: A List contain fields described above
-# IsValid: True if conforming EBNF, otherwise False
-# Index: The index where PcdValue is in ValueList
-#
-def AnalyzeDscPcd(Setting, PcdType, DataType=''):
+def AnalyzePcdExpression(Setting):
Setting = Setting.strip()
# There might be escaped quote in a string: \", \\\"
Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'')
@@ -1452,24 +1470,148 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
FieldList.append(Setting[StartPos:Pos].strip())
StartPos = Pos + 1
+ return FieldList
+
+def ParseFieldValue (Value):
+ if type(Value) == type(0):
+ return Value, (Value.bit_length() + 7) / 8
+ if type(Value) <> type(''):
+ raise ValueError
+ Value = Value.strip()
+ if Value.startswith('UINT8') and Value.endswith(')'):
+ Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
+ if Size > 1:
+ raise ValueError
+ 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
+#
+# Analyze DSC PCD value, since there is no data type info in DSC
+# This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
+# 1. Feature flag: TokenSpace.PcdCName|PcdValue
+# 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
+# 3. Dynamic default:
+# TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
+# TokenSpace.PcdCName|PcdValue
+# 4. Dynamic VPD:
+# TokenSpace.PcdCName|VpdOffset[|VpdValue]
+# TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
+# 5. Dynamic HII:
+# TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
+# PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
+# there might have "|" operator, also in string value.
+#
+# @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
+# @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
+# @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
+# @retval:
+# ValueList: A List contain fields described above
+# IsValid: True if conforming EBNF, otherwise False
+# Index: The index where PcdValue is in ValueList
+#
+def AnalyzeDscPcd(Setting, PcdType, DataType=''):
+ FieldList = AnalyzePcdExpression(Setting)
+
IsValid = True
if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG):
Value = FieldList[0]
Size = ''
if len(FieldList) > 1:
- Type = FieldList[1]
- # Fix the PCD type when no DataType input
- if Type == 'VOID*':
- DataType = 'VOID*'
- else:
+ if FieldList[1].upper().startswith("0X") or FieldList[1].isdigit():
Size = FieldList[1]
+ else:
+ DataType = FieldList[1]
+
if len(FieldList) > 2:
Size = FieldList[2]
- if DataType == 'VOID*':
- IsValid = (len(FieldList) <= 3)
- else:
+ if DataType == "":
IsValid = (len(FieldList) <= 1)
- return [Value, '', Size], IsValid, 0
+ else:
+ IsValid = (len(FieldList) <= 3)
+# Value, Size = ParseFieldValue(Value)
+ return [str(Value), '', str(Size)], IsValid, 0
elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
Value = FieldList[0]
Size = Type = ''
@@ -1487,10 +1629,10 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
Size = str(len(Value.split(",")))
else:
Size = str(len(Value) -2 + 1 )
- if DataType == 'VOID*':
- IsValid = (len(FieldList) <= 3)
- else:
+ if DataType == "":
IsValid = (len(FieldList) <= 1)
+ else:
+ IsValid = (len(FieldList) <= 3)
return [Value, Type, Size], IsValid, 0
elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):
VpdOffset = FieldList[0]
@@ -1503,10 +1645,11 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
Size = FieldList[1]
if len(FieldList) > 2:
Value = FieldList[2]
- if DataType == 'VOID*':
- IsValid = (len(FieldList) <= 3)
+ if DataType == "":
+ IsValid = (len(FieldList) <= 1)
else:
- IsValid = (len(FieldList) <= 2)
+ IsValid = (len(FieldList) <= 3)
+
return [VpdOffset, Size, Value], IsValid, 2
elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):
HiiString = FieldList[0]
@@ -1635,7 +1778,7 @@ def CheckPcdDatum(Type, Value):
return False, "Invalid value [%s] of type [%s];"\
" must be a hexadecimal, decimal or octal in C language format." % (Value, Type)
else:
- return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type)
+ return True, "StructurePcd"
return True, ""
@@ -1950,44 +2093,84 @@ class PeImageClass():
Value = (Value << 8) | int(ByteList[index])
return Value
+class DefaultStore():
+ def __init__(self,DefaultStores ):
+ self.DefaultStores = DefaultStores
+ def DefaultStoreID(self,DefaultStoreName):
+ for key,value in self.DefaultStores.items():
+ if value == DefaultStoreName:
+ return key
+ return None
+ def GetDefaultDefault(self):
+ if not self.DefaultStores or "0" in self.DefaultStores:
+ return "0",TAB_DEFAULT_STORES_DEFAULT
+ else:
+ minvalue = min([int(value_str) for value_str in self.DefaultStores.keys()])
+ return (str(minvalue), self.DefaultStores[str(minvalue)])
+ def GetMin(self,DefaultSIdList):
+ if not DefaultSIdList:
+ return "STANDARD"
+ storeidset = {storeid for storeid, storename in self.DefaultStores.values() if storename in DefaultSIdList}
+ if not storeidset:
+ return ""
+ minid = min(storeidset )
+ for sid,name in self.DefaultStores.values():
+ if sid == minid:
+ return name
class SkuClass():
DEFAULT = 0
SINGLE = 1
MULTIPLE =2
- def __init__(self,SkuIdentifier='', SkuIds={}):
+ def __init__(self,SkuIdentifier='', SkuIds=None):
+ if SkuIds is None:
+ SkuIds = {}
self.AvailableSkuIds = sdict()
self.SkuIdSet = []
self.SkuIdNumberSet = []
+ self.SkuData = SkuIds
+ self.__SkuInherit = {}
if SkuIdentifier == '' or SkuIdentifier is None:
self.SkuIdSet = ['DEFAULT']
self.SkuIdNumberSet = ['0U']
elif SkuIdentifier == 'ALL':
self.SkuIdSet = SkuIds.keys()
- self.SkuIdNumberSet = [num.strip() + 'U' for num in SkuIds.values()]
+ self.SkuIdNumberSet = [num[0].strip() + 'U' for num in SkuIds.values()]
else:
r = SkuIdentifier.split('|')
- self.SkuIdSet=[r[k].strip() for k in range(len(r))]
+ self.SkuIdSet=[(r[k].strip()).upper() for k in range(len(r))]
k = None
try:
- self.SkuIdNumberSet = [SkuIds[k].strip() + 'U' for k in self.SkuIdSet]
+ self.SkuIdNumberSet = [SkuIds[k][0].strip() + 'U' for k in self.SkuIdSet]
except Exception:
EdkLogger.error("build", PARAMETER_INVALID,
ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
- % (k, " ".join(SkuIds.keys())))
- if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL':
- self.SkuIdSet.remove('DEFAULT')
- self.SkuIdNumberSet.remove('0U')
+ % (k, " | ".join(SkuIds.keys())))
for each in self.SkuIdSet:
if each in SkuIds:
- self.AvailableSkuIds[each] = SkuIds[each]
+ self.AvailableSkuIds[each] = SkuIds[each][0]
else:
EdkLogger.error("build", PARAMETER_INVALID,
ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
- % (each, " ".join(SkuIds.keys())))
+ % (each, " | ".join(SkuIds.keys())))
+ if self.SkuUsageType != self.SINGLE:
+ self.AvailableSkuIds.update({'DEFAULT':0, 'COMMON':0})
+ if self.SkuIdSet:
+ GlobalData.gSkuids = (self.SkuIdSet)
+ if 'COMMON' in GlobalData.gSkuids:
+ GlobalData.gSkuids.remove('COMMON')
+ if GlobalData.gSkuids:
+ GlobalData.gSkuids.sort()
+
+ def GetNextSkuId(self, skuname):
+ if not self.__SkuInherit:
+ self.__SkuInherit = {}
+ for item in self.SkuData.values():
+ self.__SkuInherit[item[1]]=item[2] if item[2] else "DEFAULT"
+ return self.__SkuInherit.get(skuname,"DEFAULT")
def __SkuUsageType(self):
@@ -1998,7 +2181,21 @@ class SkuClass():
return SkuClass.SINGLE
else:
return SkuClass.MULTIPLE
+ def DumpSkuIdArrary(self):
+ ArrayStrList = []
+ if self.SkuUsageType == SkuClass.SINGLE:
+ ArrayStr = "{0x0}"
+ else:
+ for skuname in self.AvailableSkuIds:
+ if skuname == "COMMON":
+ continue
+ while skuname != "DEFAULT":
+ ArrayStrList.append(hex(int(self.AvailableSkuIds[skuname])))
+ skuname = self.GetNextSkuId(skuname)
+ ArrayStrList.append("0x0")
+ ArrayStr = "{" + ",".join(ArrayStrList) + "}"
+ return ArrayStr
def __GetAvailableSkuIds(self):
return self.AvailableSkuIds
@@ -2033,6 +2230,55 @@ def PackRegistryFormatGuid(Guid):
int(Guid[4][-2:], 16)
)
+def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Value):
+ if PcdDatumType == 'VOID*':
+ if Value.startswith('L'):
+ if not Value[1]:
+ EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
+ Value = Value[0] + '"' + Value[1:] + '"'
+ elif Value.startswith('H'):
+ if not Value[1]:
+ EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
+ Value = Value[1:]
+ else:
+ if not Value[0]:
+ EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
+ Value = '"' + Value + '"'
+
+ IsValid, Cause = CheckPcdDatum(PcdDatumType, Value)
+ if not IsValid:
+ EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))
+ if PcdDatumType == 'BOOLEAN':
+ Value = Value.upper()
+ if Value == 'TRUE' or Value == '1':
+ Value = '1'
+ elif Value == 'FALSE' or Value == '0':
+ Value = '0'
+ return Value
+## Get the integer value from string like "14U" or integer like 2
+#
+# @param Input The object that may be either a integer value or a string
+#
+# @retval Value The integer value that the input represents
+#
+def GetIntegerValue(Input):
+ if type(Input) in (int, long):
+ return Input
+ String = Input
+ if String.endswith("U"):
+ String = String[:-1]
+ if String.endswith("ULL"):
+ String = String[:-3]
+ if String.endswith("LL"):
+ String = String[:-2]
+
+ if String.startswith("0x") or String.startswith("0X"):
+ return int(String, 16)
+ elif String == '':
+ return 0
+ else:
+ return int(String)
+
##
#
# This acts like the main() function for the script, unless it is 'import'ed into another