X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FMisc.py;h=3d205197abfc4a59500ac94d4e331b19d0e5e04e;hp=19a1319639a54326364ea47f29888eaa908e4436;hb=31ff1c443e25d6bff758bdcd9a248a907cff651b;hpb=9b9500a1c9e620c9aac565679e2eb77255ba3306
diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
index 19a1319639..3d205197ab 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 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2018, 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
@@ -24,6 +24,7 @@ import re
import cPickle
import array
import shutil
+from struct import pack
from UserDict import IterableUserDict
from UserList import UserList
@@ -34,9 +35,19 @@ from BuildToolError import *
from CommonDataClass.DataClass import *
from Parsing import GetSplitValueList
from Common.LongFilePathSupport import OpenLongFilePath as open
-
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+import uuid
+from CommonDataClass.Exceptions import BadExpression
+import subprocess
## 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)
+
+## regular expressions for map file processing
+startPatternGeneral = re.compile("^Start[' ']+Length[' ']+Name[' ']+Class")
+addressPatternGeneral = re.compile("^Address[' ']+Publics by Value[' ']+Rva\+Base")
+valuePatternGcc = re.compile('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$')
+pcdPatternGcc = re.compile('^([\da-fA-Fx]+) +([\da-fA-Fx]+)')
+secReGeneral = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE)
## Dictionary used to store file time stamp for quick re-access
gFileTimeStampCache = {} # {file path : file time stamp}
@@ -44,6 +55,162 @@ gFileTimeStampCache = {} # {file path : file time stamp}
## Dictionary used to store dependencies of files
gDependencyDatabase = {} # arch : {file path : [dependent files list]}
+def GetVariableOffset(mapfilepath, efifilepath, varnames):
+ """ Parse map file to get variable offset in current EFI file
+ @param mapfilepath Map file absolution path
+ @param efifilepath: EFI binary file full path
+ @param varnames iteratable container whose elements are variable names to be searched
+
+ @return List whos elements are tuple with variable name and raw offset
+ """
+ lines = []
+ try:
+ f = open(mapfilepath, 'r')
+ lines = f.readlines()
+ f.close()
+ except:
+ return None
+
+ if len(lines) == 0: return None
+ firstline = lines[0].strip()
+ 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 line in 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:
+ # cannot pregenerate this RegEx since it uses varname from varnames.
+ m = re.match('^([\da-fA-FxX]+)([\s\S]*)([_]*%s)$' % varname, line)
+ if m is not 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 index, line in enumerate(lines):
+ line = line.strip()
+ # status machine transection
+ if status == 0 and line == "Memory Configuration":
+ status = 1
+ continue
+ elif status == 1 and line == 'Linker script and memory map':
+ status = 2
+ continue
+ elif status ==2 and line == 'START GROUP':
+ status = 3
+ continue
+
+ # status handler
+ if status == 3:
+ m = valuePatternGcc.match(line)
+ if m is not None:
+ sections.append(m.groups(0))
+ for varname in varnames:
+ Str = ''
+ m = re.match("^.data.(%s)" % varname, line)
+ if m is not None:
+ m = re.match(".data.(%s)$" % varname, line)
+ if m is not None:
+ Str = lines[index + 1]
+ else:
+ Str = line[len(".data.%s" % varname):]
+ if Str:
+ m = pcdPatternGcc.match(Str.strip())
+ if m is not None:
+ varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0]))
+
+ if not varoffset:
+ return []
+ # get section information from efi file
+ efisecs = PeImageClass(efifilepath).SectionHeaderList
+ if efisecs is None or len(efisecs) == 0:
+ return []
+ #redirection
+ redirection = 0
+ for efisec in efisecs:
+ for section in sections:
+ if section[0].strip() == efisec[0].strip() and section[0].strip() == '.text':
+ redirection = int(section[1], 16) - efisec[1]
+
+ ret = []
+ for var in varoffset:
+ for efisec in efisecs:
+ if var[1] >= efisec[1] and var[1] < efisec[1]+efisec[3]:
+ ret.append((var[0], hex(efisec[2] + var[1] - efisec[1] - redirection)))
+ return ret
+
+def _parseGeneral(lines, efifilepath, varnames):
+ status = 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table
+ secs = [] # key = section name
+ varoffset = []
+ symRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re.UNICODE)
+
+ for line in lines:
+ line = line.strip()
+ if startPatternGeneral.match(line):
+ status = 1
+ continue
+ if addressPatternGeneral.match(line):
+ status = 2
+ continue
+ if line.startswith("entry point at"):
+ status = 3
+ continue
+ if status == 1 and len(line) != 0:
+ m = secReGeneral.match(line)
+ assert m is not None, "Fail to parse the section in map file , line is %s" % line
+ sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0)
+ secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class])
+ if status == 2 and len(line) != 0:
+ for varname in varnames:
+ m = symRe.match(line)
+ assert m is not None, "Fail to parse the symbol in map file, line is %s" % line
+ sec_no, sym_offset, sym_name, vir_addr = m.groups(0)
+ sec_no = int(sec_no, 16)
+ sym_offset = int(sym_offset, 16)
+ vir_addr = int(vir_addr, 16)
+ # cannot pregenerate this RegEx since it uses varname from varnames.
+ m2 = re.match('^[_]*(%s)' % varname, sym_name)
+ if m2 is not None:
+ # fond a binary pcd entry in map file
+ for sec in secs:
+ if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]):
+ varoffset.append([varname, sec[3], sym_offset, vir_addr, sec_no])
+
+ if not varoffset: return []
+
+ # get section information from efi file
+ efisecs = PeImageClass(efifilepath).SectionHeaderList
+ if efisecs is None or len(efisecs) == 0:
+ return []
+
+ ret = []
+ for var in varoffset:
+ index = 0
+ for efisec in efisecs:
+ index = index + 1
+ if var[1].strip() == efisec[0].strip():
+ ret.append((var[0], hex(efisec[2] + var[2])))
+ elif var[4] == index:
+ ret.append((var[0], hex(efisec[2] + var[2])))
+
+ return ret
+
## Routine to process duplicated INF
#
# This function is called by following two cases:
@@ -128,32 +295,6 @@ def ClearDuplicatedInf():
if os.path.exists(File):
os.remove(File)
-## callback routine for processing variable option
-#
-# This function can be used to process variable number of option values. The
-# typical usage of it is specify architecure list on command line.
-# (e.g. -a IA32 X64 IPF)
-#
-# @param Option Standard callback function parameter
-# @param OptionString Standard callback function parameter
-# @param Value Standard callback function parameter
-# @param Parser Standard callback function parameter
-#
-# @retval
-#
-def ProcessVariableArgument(Option, OptionString, Value, Parser):
- assert Value is None
- Value = []
- RawArgs = Parser.rargs
- while RawArgs:
- Arg = RawArgs[0]
- if (Arg[:2] == "--" and len(Arg) > 2) or \
- (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"):
- break
- Value.append(Arg)
- del RawArgs[0]
- setattr(Parser.values, Option.dest, Value)
-
## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
#
# @param Guid The GUID string
@@ -163,11 +304,11 @@ def ProcessVariableArgument(Option, OptionString, Value, Parser):
def GuidStringToGuidStructureString(Guid):
GuidList = Guid.split('-')
Result = '{'
- for Index in range(0,3,1):
+ for Index in range(0, 3, 1):
Result = Result + '0x' + GuidList[Index] + ', '
Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]
- for Index in range(0,12,2):
- Result = Result + ', 0x' + GuidList[4][Index:Index+2]
+ for Index in range(0, 12, 2):
+ Result = Result + ', 0x' + GuidList[4][Index:Index + 2]
Result += '}}'
return Result
@@ -264,7 +405,7 @@ def GuidStructureStringToGuidValueName(GuidValue):
# @param Directory The directory name
#
def CreateDirectory(Directory):
- if Directory == None or Directory.strip() == "":
+ if Directory is None or Directory.strip() == "":
return True
try:
if not os.access(Directory, os.F_OK):
@@ -278,7 +419,7 @@ def CreateDirectory(Directory):
# @param Directory The directory name
#
def RemoveDirectory(Directory, Recursively=False):
- if Directory == None or Directory.strip() == "" or not os.path.exists(Directory):
+ if Directory is None or Directory.strip() == "" or not os.path.exists(Directory):
return
if Recursively:
CurrentDirectory = os.getcwd()
@@ -291,32 +432,6 @@ def RemoveDirectory(Directory, Recursively=False):
os.chdir(CurrentDirectory)
os.rmdir(Directory)
-## Check if given file is changed or not
-#
-# This method is used to check if a file is changed or not between two build
-# actions. It makes use a cache to store files timestamp.
-#
-# @param File The path of file
-#
-# @retval True If the given file is changed, doesn't exist, or can't be
-# found in timestamp cache
-# @retval False If the given file is changed
-#
-def IsChanged(File):
- if not os.path.exists(File):
- return True
-
- FileState = os.stat(File)
- TimeStamp = FileState[-2]
-
- if File in gFileTimeStampCache and TimeStamp == gFileTimeStampCache[File]:
- FileChanged = False
- else:
- FileChanged = True
- gFileTimeStampCache[File] = TimeStamp
-
- return FileChanged
-
## Store content in file
#
# This method is used to save file only when its content is changed. This is
@@ -364,7 +479,7 @@ def SaveFileOnChange(File, Content, IsBinaryFile=True):
Fd.write(Content)
Fd.close()
except IOError, X:
- EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s'%X)
+ EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X)
return True
@@ -381,7 +496,7 @@ def DataDump(Data, File):
except:
EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False)
finally:
- if Fd != None:
+ if Fd is not None:
Fd.close()
## Restore a Python object from a file
@@ -401,7 +516,7 @@ def DataRestore(File):
EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e)))
Data = None
finally:
- if Fd != None:
+ if Fd is not None:
Fd.close()
return Data
@@ -476,47 +591,6 @@ class DirCache:
return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])
return None
-## Get all files of a directory
-#
-# @param Root: Root dir
-# @param SkipList : The files need be skipped
-#
-# @retval A list of all files
-#
-def GetFiles(Root, SkipList=None, FullPath = True):
- OriPath = Root
- FileList = []
- for Root, Dirs, Files in os.walk(Root):
- if SkipList:
- for Item in SkipList:
- if Item in Dirs:
- Dirs.remove(Item)
-
- for File in Files:
- File = os.path.normpath(os.path.join(Root, File))
- if not FullPath:
- File = File[len(OriPath) + 1:]
- FileList.append(File)
-
- return FileList
-
-## Check if gvien file exists or not
-#
-# @param File File name or path to be checked
-# @param Dir The directory the file is relative to
-#
-# @retval True if file exists
-# @retval False if file doesn't exists
-#
-def ValidFile(File, Ext=None):
- if Ext != None:
- Dummy, FileExt = os.path.splitext(File)
- if FileExt.lower() != Ext.lower():
- return False
- if not os.path.exists(File):
- return False
- return True
-
def RealPath(File, Dir='', OverrideDir=''):
NewFile = os.path.normpath(os.path.join(Dir, File))
NewFile = GlobalData.gAllFiles[NewFile]
@@ -533,7 +607,7 @@ def RealPath2(File, Dir='', OverrideDir=''):
if OverrideDir[-1] == os.path.sep:
return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]
else:
- return NewFile[len(OverrideDir)+1:], NewFile[0:len(OverrideDir)]
+ return NewFile[len(OverrideDir) + 1:], NewFile[0:len(OverrideDir)]
if GlobalData.gAllFiles:
NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))]
if not NewFile:
@@ -545,132 +619,28 @@ def RealPath2(File, Dir='', OverrideDir=''):
if Dir[-1] == os.path.sep:
return NewFile[len(Dir):], NewFile[0:len(Dir)]
else:
- return NewFile[len(Dir)+1:], NewFile[0:len(Dir)]
+ return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)]
else:
return NewFile, ''
return None, None
-## Check if gvien file exists or not
-#
-#
-def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):
- NewFile = File
- if Ext != None:
- Dummy, FileExt = os.path.splitext(File)
- if FileExt.lower() != Ext.lower():
- return False, File
-
- # Replace the Edk macros
- if OverrideDir != '' and OverrideDir != None:
- if OverrideDir.find('$(EFI_SOURCE)') > -1:
- OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)
- if OverrideDir.find('$(EDK_SOURCE)') > -1:
- OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)
-
- # Replace the default dir to current dir
- if Dir == '.':
- Dir = os.getcwd()
- Dir = Dir[len(Workspace)+1:]
-
- # First check if File has Edk definition itself
- if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:
- NewFile = File.replace('$(EFI_SOURCE)', EfiSource)
- NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource)
- NewFile = AllFiles[os.path.normpath(NewFile)]
- if NewFile != None:
- return True, NewFile
-
- # Second check the path with override value
- if OverrideDir != '' and OverrideDir != None:
- NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
- if NewFile != None:
- return True, NewFile
-
- # Last check the path with normal definitions
- File = os.path.join(Dir, File)
- NewFile = AllFiles[os.path.normpath(File)]
- if NewFile != None:
- return True, NewFile
-
- return False, File
-
-## Check if gvien file exists or not
-#
-#
-def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):
- # Replace the Edk macros
- if OverrideDir != '' and OverrideDir != None:
- if OverrideDir.find('$(EFI_SOURCE)') > -1:
- OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)
- if OverrideDir.find('$(EDK_SOURCE)') > -1:
- OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)
-
- # Replace the default dir to current dir
- # Dir is current module dir related to workspace
- if Dir == '.':
- Dir = os.getcwd()
- Dir = Dir[len(Workspace)+1:]
-
- NewFile = File
- RelaPath = AllFiles[os.path.normpath(Dir)]
- NewRelaPath = RelaPath
-
- while(True):
- # First check if File has Edk definition itself
- if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:
- File = File.replace('$(EFI_SOURCE)', EfiSource)
- File = File.replace('$(EDK_SOURCE)', EdkSource)
- NewFile = AllFiles[os.path.normpath(File)]
- if NewFile != None:
- NewRelaPath = os.path.dirname(NewFile)
- File = os.path.basename(NewFile)
- #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
- break
-
- # Second check the path with override value
- if OverrideDir != '' and OverrideDir != None:
- NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
- if NewFile != None:
- #NewRelaPath = os.path.dirname(NewFile)
- NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
- break
-
- # Last check the path with normal definitions
- NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))]
- if NewFile != None:
- break
-
- # No file found
- break
-
- return NewRelaPath, RelaPath, File
-
-
-def GetRelPath(Path1, Path2):
- FileName = os.path.basename(Path2)
- L1 = os.path.normpath(Path1).split(os.path.normpath('/'))
- L2 = os.path.normpath(Path2).split(os.path.normpath('/'))
- for Index in range(0, len(L1)):
- if L1[Index] != L2[Index]:
- FileName = '../' * (len(L1) - Index)
- for Index2 in range(Index, len(L2)):
- FileName = os.path.join(FileName, L2[Index2])
- break
- return os.path.normpath(FileName)
-
-
## Get GUID value from given packages
#
# @param CName The CName of the GUID
# @param PackageList List of packages looking-up in
+# @param Inffile The driver file
#
# @retval GuidValue if the CName is found in any given package
# @retval None if the CName is not found in all given packages
#
-def 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 = [x for x in P.Guids if x not in P._PrivateGuids]
+ if CName in GuidKeys:
return P.Guids[CName]
return None
@@ -678,13 +648,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 = [x for x in P.Protocols if x not in P._PrivateProtocols]
+ if CName in ProtocolKeys:
return P.Protocols[CName]
return None
@@ -692,13 +667,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 = [x for x in P.Ppis if x not in P._PrivatePpis]
+ if CName in PpiKeys:
return P.Ppis[CName]
return None
@@ -735,7 +715,7 @@ class TemplateString(object):
#
# PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
#
- for PlaceHolder,Start,End in PlaceHolderList:
+ for PlaceHolder, Start, End in PlaceHolderList:
self._SubSectionList.append(TemplateSection[SubSectionStart:Start])
self._SubSectionList.append(TemplateSection[Start:End])
self._PlaceHolderList.append(PlaceHolder)
@@ -888,7 +868,7 @@ class Progressor:
self.CodaMessage = CloseMessage
self.ProgressChar = ProgressChar
self.Interval = Interval
- if Progressor._StopFlag == None:
+ if Progressor._StopFlag is None:
Progressor._StopFlag = threading.Event()
## Start to print progress charater
@@ -896,10 +876,10 @@ class Progressor:
# @param OpenMessage The string printed before progress charaters
#
def Start(self, OpenMessage=None):
- if OpenMessage != None:
+ if OpenMessage is not None:
self.PromptMessage = OpenMessage
Progressor._StopFlag.clear()
- if Progressor._ProgressThread == None:
+ if Progressor._ProgressThread is None:
Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)
Progressor._ProgressThread.setDaemon(False)
Progressor._ProgressThread.start()
@@ -910,7 +890,7 @@ class Progressor:
#
def Stop(self, CloseMessage=None):
OriginalCodaMessage = self.CodaMessage
- if CloseMessage != None:
+ if CloseMessage is not None:
self.CodaMessage = CloseMessage
self.Abort()
self.CodaMessage = OriginalCodaMessage
@@ -933,9 +913,9 @@ class Progressor:
## Abort the progress display
@staticmethod
def Abort():
- if Progressor._StopFlag != None:
+ if Progressor._StopFlag is not None:
Progressor._StopFlag.set()
- if Progressor._ProgressThread != None:
+ if Progressor._ProgressThread is not None:
Progressor._ProgressThread.join()
Progressor._ProgressThread = None
@@ -1054,7 +1034,7 @@ class sdict(IterableUserDict):
return key, value
def update(self, dict=None, **kwargs):
- if dict != None:
+ if dict is not None:
for k, v in dict.items():
self[k] = v
if len(kwargs):
@@ -1121,13 +1101,13 @@ class tdict:
if len(key) > 1:
RestKeys = key[1:]
elif self._Level_ > 1:
- RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
+ RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
else:
FirstKey = key
if self._Level_ > 1:
- RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
+ RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
- if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:
+ if FirstKey is None or str(FirstKey).upper() in self._ValidWildcardList:
FirstKey = self._Wildcard
if self._Single_:
@@ -1142,24 +1122,24 @@ class tdict:
if FirstKey == self._Wildcard:
if FirstKey in self.data:
Value = self.data[FirstKey][RestKeys]
- if Value == None:
+ if Value is None:
for Key in self.data:
Value = self.data[Key][RestKeys]
- if Value != None: break
+ if Value is not None: break
else:
if FirstKey in self.data:
Value = self.data[FirstKey][RestKeys]
- if Value == None and self._Wildcard in self.data:
+ if Value is None and self._Wildcard in self.data:
#print "Value=None"
Value = self.data[self._Wildcard][RestKeys]
else:
if FirstKey == self._Wildcard:
if FirstKey in self.data:
Value = self.data[FirstKey]
- if Value == None:
+ if Value is None:
for Key in self.data:
Value = self.data[Key]
- if Value != None: break
+ if Value is not None: break
else:
if FirstKey in self.data:
Value = self.data[FirstKey]
@@ -1198,11 +1178,11 @@ class tdict:
if len(key) > 1:
RestKeys = key[1:]
else:
- RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
+ RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
else:
FirstKey = key
if self._Level_ > 1:
- RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
+ RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
if FirstKey in self._ValidWildcardList:
FirstKey = self._Wildcard
@@ -1237,40 +1217,215 @@ class tdict:
keys |= self.data[Key].GetKeys(KeyIndex - 1)
return keys
-## Boolean chain list
-#
-class Blist(UserList):
- def __init__(self, initlist=None):
- UserList.__init__(self, initlist)
- def __setitem__(self, i, item):
- if item not in [True, False]:
- if item == 0:
- item = False
- else:
- item = True
- self.data[i] = item
- def _GetResult(self):
- Value = True
- for item in self.data:
- Value &= item
- return Value
- Result = property(_GetResult)
+def IsFieldValueAnArray (Value):
+ Value = Value.strip()
+ if Value.startswith(TAB_GUID) and Value.endswith(')'):
+ return True
+ if Value.startswith('L"') and Value.endswith('"') and len(list(Value[2:-1])) > 1:
+ return True
+ if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
+ return True
+ if Value[0] == '{' and Value[-1] == '}':
+ return True
+ if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
+ return True
+ if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
+ return True
+ return False
-def ParseConsoleLog(Filename):
- Opr = open(os.path.normpath(Filename), 'r')
- Opw = open(os.path.normpath(Filename + '.New'), 'w+')
- for Line in Opr.readlines():
- if Line.find('.efi') > -1:
- Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip()
- Opw.write('%s\n' % Line)
+def AnalyzePcdExpression(Setting):
+ Setting = Setting.strip()
+ # There might be escaped quote in a string: \", \\\" , \', \\\'
+ Data = Setting
+ # There might be '|' in string and in ( ... | ... ), replace it with '-'
+ NewStr = ''
+ InSingleQuoteStr = False
+ InDoubleQuoteStr = False
+ Pair = 0
+ for Index, ch in enumerate(Data):
+ if ch == '"' and not InSingleQuoteStr:
+ if Data[Index - 1] != '\\':
+ InDoubleQuoteStr = not InDoubleQuoteStr
+ elif ch == "'" and not InDoubleQuoteStr:
+ if Data[Index - 1] != '\\':
+ InSingleQuoteStr = not InSingleQuoteStr
+ elif ch == '(' and not (InSingleQuoteStr or InDoubleQuoteStr):
+ Pair += 1
+ elif ch == ')' and not (InSingleQuoteStr or InDoubleQuoteStr):
+ Pair -= 1
- Opr.close()
- Opw.close()
+ if (Pair > 0 or InSingleQuoteStr or InDoubleQuoteStr) and ch == TAB_VALUE_SPLIT:
+ NewStr += '-'
+ else:
+ NewStr += ch
+ FieldList = []
+ StartPos = 0
+ while True:
+ Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos)
+ if Pos < 0:
+ FieldList.append(Setting[StartPos:].strip())
+ break
+ FieldList.append(Setting[StartPos:Pos].strip())
+ StartPos = Pos + 1
+
+ return FieldList
+
+def ParseDevPathValue (Value):
+ if '\\' in Value:
+ Value.replace('\\', '/').replace(' ', '')
+
+ Cmd = 'DevicePath ' + '"' + Value + '"'
+ try:
+ p = subprocess.Popen(Cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+ out, err = p.communicate()
+ except Exception, X:
+ raise BadExpression("DevicePath: %s" % (str(X)) )
+ finally:
+ subprocess._cleanup()
+ p.stdout.close()
+ p.stderr.close()
+ if err:
+ raise BadExpression("DevicePath: %s" % str(err))
+ Size = len(out.split())
+ out = ','.join(out.split())
+ return '{' + out + '}', Size
+
+def ParseFieldValue (Value):
+ if type(Value) == type(0):
+ return Value, (Value.bit_length() + 7) / 8
+ if type(Value) <> type(''):
+ raise BadExpression('Type %s is %s' %(Value, type(Value)))
+ Value = Value.strip()
+ if Value.startswith(TAB_UINT8) and Value.endswith(')'):
+ Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])
+ if Size > 1:
+ raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))
+ return Value, 1
+ if Value.startswith(TAB_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(TAB_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(TAB_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(TAB_GUID) and Value.endswith(')'):
+ Value = Value.split('(', 1)[1][:-1].strip()
+ if Value[0] == '{' and Value[-1] == '}':
+ TmpValue = GuidStructureStringToGuidString(Value)
+ if len(TmpValue) == 0:
+ raise BadExpression("Invalid GUID value string %s" % Value)
+ Value = TmpValue
+ 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
+ # translate escape character
+ Value = Value[1:]
+ try:
+ Value = eval(Value)
+ except:
+ Value = Value[1:-1]
+ List = list(Value)
+ 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
+ # translate escape character
+ try:
+ Value = eval(Value)
+ except:
+ Value = Value[1:-1]
+ List = list(Value)
+ 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
+ # translate escape character
+ Value = Value[1:]
+ try:
+ Value = eval(Value)
+ except:
+ Value = Value[1:-1]
+ List = list(Value)
+ if len(List) == 0:
+ raise BadExpression('Length %s is %s' % (Value, len(List)))
+ 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
+ # translate escape character
+ try:
+ Value = eval(Value)
+ except:
+ Value = Value[1:-1]
+ List = list(Value)
+ if len(List) == 0:
+ raise BadExpression('Length %s is %s' % (Value, len(List)))
+ 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.replace("DEVICE_PATH(", '').rstrip(')')
+ Value = Value.strip().strip('"')
+ 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
## 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
+# This fuction is used to match functions (AnalyzePcdData) used for retrieving PCD value from database
# 1. Feature flag: TokenSpace.PcdCName|PcdValue
# 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
# 3. Dynamic default:
@@ -1293,53 +1448,32 @@ def ParseConsoleLog(Filename):
# Index: The index where PcdValue is in ValueList
#
def AnalyzeDscPcd(Setting, PcdType, DataType=''):
- Setting = Setting.strip()
- # There might be escaped quote in a string: \", \\\"
- Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'')
- # There might be '|' in string and in ( ... | ... ), replace it with '-'
- NewStr = ''
- InStr = False
- Pair = 0
- for ch in Data:
- if ch == '"':
- InStr = not InStr
- elif ch == '(' and not InStr:
- Pair += 1
- elif ch == ')' and not InStr:
- Pair -= 1
-
- if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT:
- NewStr += '-'
- else:
- NewStr += ch
- FieldList = []
- StartPos = 0
- while True:
- Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos)
- if Pos < 0:
- FieldList.append(Setting[StartPos:].strip())
- break
- FieldList.append(Setting[StartPos:Pos].strip())
- StartPos = Pos + 1
+ 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)
+ if Size:
+ try:
+ int(Size,16) if Size.upper().startswith("0X") else int(Size)
+ except:
+ IsValid = False
+ Size = -1
+ return [str(Value), '', str(Size)], IsValid, 0
elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
Value = FieldList[0]
Size = Type = ''
@@ -1349,23 +1483,22 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
Type = DataType
if len(FieldList) > 2:
Size = FieldList[2]
+ if DataType == "":
+ IsValid = (len(FieldList) <= 1)
else:
- if Type == 'VOID*':
- if Value.startswith("L"):
- Size = str((len(Value)- 3 + 1) * 2)
- elif Value.startswith("{"):
- Size = str(len(Value.split(",")))
- else:
- Size = str(len(Value) -2 + 1 )
- if DataType == 'VOID*':
IsValid = (len(FieldList) <= 3)
- else:
- IsValid = (len(FieldList) <= 1)
- return [Value, Type, Size], IsValid, 0
+
+ if Size:
+ try:
+ int(Size,16) if Size.upper().startswith("0X") else int(Size)
+ except:
+ IsValid = False
+ Size = -1
+ return [Value, Type, str(Size)], IsValid, 0
elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):
VpdOffset = FieldList[0]
Value = Size = ''
- if not DataType == 'VOID*':
+ if not DataType == TAB_VOID:
if len(FieldList) > 1:
Value = FieldList[1]
else:
@@ -1373,22 +1506,30 @@ 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)
- return [VpdOffset, Size, Value], IsValid, 2
+ IsValid = (len(FieldList) <= 3)
+ if Size:
+ try:
+ int(Size,16) if Size.upper().startswith("0X") else int(Size)
+ except:
+ IsValid = False
+ Size = -1
+ return [VpdOffset, str(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
@@ -1400,17 +1541,17 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
#
# @retval ValueList: A List contain value, datum type and toke number.
#
-def AnalyzePcdData(Setting):
- ValueList = ['', '', '']
-
- ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
+def AnalyzePcdData(Setting):
+ ValueList = ['', '', '']
+
+ ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
PtrValue = ValueRe.findall(Setting)
ValueUpdateFlag = False
if len(PtrValue) >= 1:
Setting = re.sub(ValueRe, '', Setting)
- ValueUpdateFlag = True
+ ValueUpdateFlag = True
TokenList = Setting.split(TAB_VALUE_SPLIT)
ValueList[0:len(TokenList)] = TokenList
@@ -1420,64 +1561,18 @@ def AnalyzePcdData(Setting):
return ValueList
-## AnalyzeHiiPcdData
-#
-# Analyze the pcd Value, variable name, variable Guid and variable offset.
-# Used to avoid split issue while the value string contain "|" character
-#
-# @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
-#
-# @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
-#
-def AnalyzeHiiPcdData(Setting):
- ValueList = ['', '', '', '']
-
- TokenList = GetSplitValueList(Setting)
- ValueList[0:len(TokenList)] = TokenList
-
- return ValueList
-
-## AnalyzeVpdPcdData
-#
-# Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
-# Used to avoid split issue while the value string contain "|" character
-#
-# @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
-#
-# @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
-#
-def AnalyzeVpdPcdData(Setting):
- ValueList = ['', '', '']
-
- ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$')
- PtrValue = ValueRe.findall(Setting)
-
- ValueUpdateFlag = False
-
- if len(PtrValue) >= 1:
- Setting = re.sub(ValueRe, '', Setting)
- ValueUpdateFlag = True
-
- TokenList = Setting.split(TAB_VALUE_SPLIT)
- ValueList[0:len(TokenList)] = TokenList
-
- if ValueUpdateFlag:
- ValueList[2] = PtrValue[0]
-
- return ValueList
-
## check format of PCD value against its the datum type
#
# For PCD value setting
#
def CheckPcdDatum(Type, Value):
- if Type == "VOID*":
- ValueRe = re.compile(r'\s*L?\".*\"\s*$')
+ if Type == TAB_VOID:
+ ValueRe = re.compile(r'\s*L?\".*\"\s*$')
if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))
- or (Value.startswith('{') and Value.endswith('}'))
+ or (Value.startswith('{') and Value.endswith('}')) or (Value.startswith("L'") or Value.startswith("'") and Value.endswith("'"))
):
return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
- ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type)
+ ", \"...\" or \'...\' for string, L\"...\" or L\'...\' for unicode string" % (Value, Type)
elif ValueRe.match(Value):
# Check the chars in UnicodeString or CString is printable
if Value.startswith("L"):
@@ -1503,7 +1598,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, ""
@@ -1530,7 +1625,7 @@ def SplitOption(OptionString):
if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
if Index > OptionStart:
- OptionList.append(OptionString[OptionStart:Index-1])
+ OptionList.append(OptionString[OptionStart:Index - 1])
OptionStart = Index
LastChar = CurrentChar
OptionList.append(OptionString[OptionStart:])
@@ -1597,6 +1692,7 @@ class PathClass(object):
# Remove any '.' and '..' in path
if self.Root:
+ self.Root = mws.getWs(self.Root, self.File)
self.Path = os.path.normpath(os.path.join(self.Root, self.File))
self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
# eliminate the side-effect of 'C:'
@@ -1606,7 +1702,7 @@ class PathClass(object):
if self.Root[-1] == os.path.sep:
self.File = self.Path[len(self.Root):]
else:
- self.File = self.Path[len(self.Root)+1:]
+ self.File = self.Path[len(self.Root) + 1:]
else:
self.Path = os.path.normpath(self.File)
@@ -1687,7 +1783,7 @@ class PathClass(object):
return hash(self.Path)
def _GetFileKey(self):
- if self._Key == None:
+ if self._Key is None:
self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
return self._Key
@@ -1707,7 +1803,10 @@ class PathClass(object):
RealFile = os.path.join(self.AlterRoot, self.File)
elif self.Root:
RealFile = os.path.join(self.Root, self.File)
- return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
+ if len (mws.getPkgPath()) == 0:
+ return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
+ else:
+ return FILE_NOT_FOUND, "%s is not found in packages path:\n\t%s" % (self.File, '\n\t'.join(mws.getPkgPath()))
ErrorCode = 0
ErrorInfo = ''
@@ -1814,58 +1913,218 @@ 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])
+ return (str(minvalue), self.DefaultStores[str(minvalue)])
+ def GetMin(self,DefaultSIdList):
+ if not DefaultSIdList:
+ return TAB_DEFAULT_STORES_DEFAULT
+ 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 = {}
+
+ for SkuName in SkuIds:
+ SkuId = SkuIds[SkuName][0]
+ skuid_num = int(SkuId,16) if SkuId.upper().startswith("0X") else int(SkuId)
+ if skuid_num > 0xFFFFFFFFFFFFFFFF:
+ EdkLogger.error("build", PARAMETER_INVALID,
+ ExtraData = "SKU-ID [%s] value %s exceeds the max value of UINT64"
+ % (SkuName, SkuId))
self.AvailableSkuIds = sdict()
self.SkuIdSet = []
-
+ self.SkuIdNumberSet = []
+ self.SkuData = SkuIds
+ self.__SkuInherit = {}
+ self.__SkuIdentifier = SkuIdentifier
if SkuIdentifier == '' or SkuIdentifier is None:
self.SkuIdSet = ['DEFAULT']
+ self.SkuIdNumberSet = ['0U']
elif SkuIdentifier == 'ALL':
self.SkuIdSet = SkuIds.keys()
+ 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))]
- if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL':
- self.SkuIdSet.remove('DEFAULT')
-
+ self.SkuIdSet=[(r[k].strip()).upper() for k in range(len(r))]
+ k = None
+ try:
+ 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())))
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 self.SkuUsageType == self.SINGLE:
+ if len(GlobalData.gSkuids) != 1:
+ if 'DEFAULT' in GlobalData.gSkuids:
+ GlobalData.gSkuids.remove('DEFAULT')
+ 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 GetSkuChain(self,sku):
+ if sku == "DEFAULT":
+ return ["DEFAULT"]
+ skulist = [sku]
+ nextsku = sku
+ while 1:
+ nextsku = self.GetNextSkuId(nextsku)
+ skulist.append(nextsku)
+ if nextsku == "DEFAULT":
+ break
+ skulist.reverse()
+ return skulist
+ def SkuOverrideOrder(self):
+ skuorderset = []
+ for skuname in self.SkuIdSet:
+ skuorderset.append(self.GetSkuChain(skuname))
+ skuorder = []
+ for index in range(max([len(item) for item in skuorderset])):
+ for subset in skuorderset:
+ if index > len(subset)-1:
+ continue
+ if subset[index] in skuorder:
+ continue
+ skuorder.append(subset[index])
+
+ return skuorder
+
def __SkuUsageType(self):
+ if self.__SkuIdentifier.upper() == "ALL":
+ return SkuClass.MULTIPLE
+
if len(self.SkuIdSet) == 1:
if self.SkuIdSet[0] == 'DEFAULT':
return SkuClass.DEFAULT
else:
return SkuClass.SINGLE
+ elif len(self.SkuIdSet) == 2:
+ if 'DEFAULT' in self.SkuIdSet:
+ return SkuClass.SINGLE
+ else:
+ return SkuClass.MULTIPLE
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
def __GetSystemSkuID(self):
if self.__SkuUsageType() == SkuClass.SINGLE:
- return self.SkuIdSet[0]
+ if len(self.SkuIdSet) == 1:
+ return self.SkuIdSet[0]
+ else:
+ return self.SkuIdSet[0] if self.SkuIdSet[0] != 'DEFAULT' else self.SkuIdSet[1]
else:
return 'DEFAULT'
-
+ def __GetAvailableSkuIdNumber(self):
+ return self.SkuIdNumberSet
SystemSkuId = property(__GetSystemSkuID)
AvailableSkuIdSet = property(__GetAvailableSkuIds)
SkuUsageType = property(__SkuUsageType)
+ AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber)
+
+#
+# Pack a registry format GUID
+#
+def PackRegistryFormatGuid(Guid):
+ Guid = Guid.split('-')
+ return pack('=LHHBBBBBBBB',
+ int(Guid[0], 16),
+ int(Guid[1], 16),
+ int(Guid[2], 16),
+ int(Guid[3][-4:-2], 16),
+ int(Guid[3][-2:], 16),
+ int(Guid[4][-12:-10], 16),
+ int(Guid[4][-10:-8], 16),
+ int(Guid[4][-8:-6], 16),
+ int(Guid[4][-6:-4], 16),
+ int(Guid[4][-4:-2], 16),
+ int(Guid[4][-2:], 16)
+ )
+
+## 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)
##
#