]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/Misc.py
BaseTools: Fix eval parse string issue
[mirror_edk2.git] / BaseTools / Source / Python / Common / Misc.py
index 2883169f3c6888997e4c028c9a5e5c69d4121d30..af374d804d86b8a01a5fee2ae38b0c2968169eaf 100644 (file)
-## @file
-# Common routines used by all tools
-#
-# Copyright (c) 2007, 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
-# http://opensource.org/licenses/bsd-license.php
-#
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-
-##
-# Import Modules
-#
-import os
-import sys
-import string
-import thread
-import threading
-import time
-import re
-import cPickle
-from UserDict import IterableUserDict
-from UserList import UserList
-
-from Common import EdkLogger as EdkLogger
-from Common import GlobalData as GlobalData
-
-from BuildToolError import *
-
-## Regular expression used to find out place holders in string template
-gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE|re.UNICODE)
-
-## Dictionary used to store file time stamp for quick re-access
-gFileTimeStampCache = {}    # {file path : file time stamp}
-
-## Dictionary used to store dependencies of files
-gDependencyDatabase = {}    # arch : {file path : [dependent files list]}
-
-## 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. <tool> -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
-#
-#   @retval     string  The GUID string in C structure style
-#
-def GuidStringToGuidStructureString(Guid):
-    GuidList = Guid.split('-')
-    Result = '{'
-    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]
-    Result += '}}'
-    return Result
-
-## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
-#
-#   @param      GuidValue   The GUID value in byte array
-#
-#   @retval     string      The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
-#
-def GuidStructureByteArrayToGuidString(GuidValue):
-    guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
-    guidValueList = guidValueString.split(",")
-    if len(guidValueList) != 16:
-        return ''
-        #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
-    try:
-        return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
-                int(guidValueList[3], 16),
-                int(guidValueList[2], 16),
-                int(guidValueList[1], 16),
-                int(guidValueList[0], 16),
-                int(guidValueList[5], 16),
-                int(guidValueList[4], 16),
-                int(guidValueList[7], 16),
-                int(guidValueList[6], 16),
-                int(guidValueList[8], 16),
-                int(guidValueList[9], 16),
-                int(guidValueList[10], 16),
-                int(guidValueList[11], 16),
-                int(guidValueList[12], 16),
-                int(guidValueList[13], 16),
-                int(guidValueList[14], 16),
-                int(guidValueList[15], 16)
-                )
-    except:
-        return ''
-
-## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
-#
-#   @param      GuidValue   The GUID value in C structure format
-#
-#   @retval     string      The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
-#
-def GuidStructureStringToGuidString(GuidValue):
-    guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
-    guidValueList = guidValueString.split(",")
-    if len(guidValueList) != 11:
-        return ''
-        #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
-    try:
-        return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
-                int(guidValueList[0], 16),
-                int(guidValueList[1], 16),
-                int(guidValueList[2], 16),
-                int(guidValueList[3], 16),
-                int(guidValueList[4], 16),
-                int(guidValueList[5], 16),
-                int(guidValueList[6], 16),
-                int(guidValueList[7], 16),
-                int(guidValueList[8], 16),
-                int(guidValueList[9], 16),
-                int(guidValueList[10], 16)
-                )
-    except:
-        return ''
-
-## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
-#
-#   @param      GuidValue   The GUID value in C structure format
-#
-#   @retval     string      The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
-#
-def GuidStructureStringToGuidValueName(GuidValue):
-    guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "")
-    guidValueList = guidValueString.split(",")
-    if len(guidValueList) != 11:
-        EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
-    return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
-            int(guidValueList[0], 16),
-            int(guidValueList[1], 16),
-            int(guidValueList[2], 16),
-            int(guidValueList[3], 16),
-            int(guidValueList[4], 16),
-            int(guidValueList[5], 16),
-            int(guidValueList[6], 16),
-            int(guidValueList[7], 16),
-            int(guidValueList[8], 16),
-            int(guidValueList[9], 16),
-            int(guidValueList[10], 16)
-            )
-
-## Create directories
-#
-#   @param      Directory   The directory name
-#
-def CreateDirectory(Directory):
-    if Directory == None or Directory.strip() == "":
-        return True
-    try:
-        if not os.access(Directory, os.F_OK):
-            os.makedirs(Directory)
-    except:
-        return False
-    return True
-
-## Remove directories, including files and sub-directories in it
-#
-#   @param      Directory   The directory name
-#
-def RemoveDirectory(Directory, Recursively=False):
-    if Directory == None or Directory.strip() == "" or not os.path.exists(Directory):
-        return
-    if Recursively:
-        CurrentDirectory = os.getcwd()
-        os.chdir(Directory)
-        for File in os.listdir("."):
-            if os.path.isdir(File):
-                RemoveDirectory(File, Recursively)
-            else:
-                os.remove(File)
-        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
-#  quite useful for "make" system to decide what will be re-built and what won't.
-#
-#   @param      File            The path of file
-#   @param      Content         The new content of the file
-#   @param      IsBinaryFile    The flag indicating if the file is binary file or not
-#
-#   @retval     True            If the file content is changed and the file is renewed
-#   @retval     False           If the file content is the same
-#
-def SaveFileOnChange(File, Content, IsBinaryFile=True):
-    if not IsBinaryFile:
-        Content = Content.replace("\n", os.linesep)
-
-    if os.path.exists(File):
-        try:
-            if Content == open(File, "rb").read():
-                return False
-        except:
-            EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File)
-
-    CreateDirectory(os.path.dirname(File))
-    try:
-        if GlobalData.gIsWindows:
-            try:
-                from PyUtility import SaveFileToDisk
-                if not SaveFileToDisk(File, Content):
-                    EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File)
-            except:
-                Fd = open(File, "wb")
-                Fd.write(Content)
-                Fd.close()
-        else:
-            Fd = open(File, "wb")
-            Fd.write(Content)
-            Fd.close()
-    except:
-        EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File)
-
-    return True
-
-## Make a Python object persistent on file system
-#
-#   @param      Data    The object to be stored in file
-#   @param      File    The path of file to store the object
-#
-def DataDump(Data, File):
-    Fd = None
-    try:
-        Fd = open(File, 'wb')
-        cPickle.dump(Data, Fd, cPickle.HIGHEST_PROTOCOL)
-    except:
-        EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False)
-    finally:
-        if Fd != None:
-            Fd.close()
-
-## Restore a Python object from a file
-#
-#   @param      File    The path of file stored the object
-#
-#   @retval     object  A python object
-#   @retval     None    If failure in file operation
-#
-def DataRestore(File):
-    Data = None
-    Fd = None
-    try:
-        Fd = open(File, 'rb')
-        Data = cPickle.load(Fd)
-    except Exception, e:
-        EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e)))
-        Data = None
-    finally:
-        if Fd != None:
-            Fd.close()
-    return Data
-
-## Retrieve and cache the real path name in file system
-#
-#   @param      Root    The root directory of path relative to
-#
-#   @retval     str     The path string if the path exists
-#   @retval     None    If path doesn't exist
-#
-class DirCache:
-    _CACHE_ = set()
-    _UPPER_CACHE_ = {}
-
-    def __init__(self, Root):
-        self._Root = Root
-        for F in os.listdir(Root):
-            self._CACHE_.add(F)
-            self._UPPER_CACHE_[F.upper()] = F
-
-    # =[] operator
-    def __getitem__(self, Path):
-        Path = Path[len(os.path.commonprefix([Path, self._Root])):]
-        if not Path:
-            return self._Root
-        if Path and Path[0] == os.path.sep:
-            Path = Path[1:]
-        if Path in self._CACHE_:
-            return os.path.join(self._Root, Path)
-        UpperPath = Path.upper()
-        if UpperPath in self._UPPER_CACHE_:
-            return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])
-
-        IndexList = []
-        LastSepIndex = -1
-        SepIndex = Path.find(os.path.sep)
-        while SepIndex > -1:
-            Parent = UpperPath[:SepIndex]
-            if Parent not in self._UPPER_CACHE_:
-                break
-            LastSepIndex = SepIndex
-            SepIndex = Path.find(os.path.sep, LastSepIndex + 1)
-
-        if LastSepIndex == -1:
-            return None
-
-        Cwd = os.getcwd()
-        os.chdir(self._Root)
-        SepIndex = LastSepIndex
-        while SepIndex > -1:
-            Parent = Path[:SepIndex]
-            ParentKey = UpperPath[:SepIndex]
-            if ParentKey not in self._UPPER_CACHE_:
-                os.chdir(Cwd)
-                return None
-
-            if Parent in self._CACHE_:
-                ParentDir = Parent
-            else:
-                ParentDir = self._UPPER_CACHE_[ParentKey]
-            for F in os.listdir(ParentDir):
-                Dir = os.path.join(ParentDir, F)
-                self._CACHE_.add(Dir)
-                self._UPPER_CACHE_[Dir.upper()] = Dir
-
-            SepIndex = Path.find(os.path.sep, SepIndex + 1)
-
-        os.chdir(Cwd)
-        if Path in self._CACHE_:
-            return os.path.join(self._Root, Path)
-        elif UpperPath in self._UPPER_CACHE_:
-            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]
-    if not NewFile and OverrideDir:
-        NewFile = os.path.normpath(os.path.join(OverrideDir, File))
-        NewFile = GlobalData.gAllFiles[NewFile]
-    return NewFile
-
-def RealPath2(File, Dir='', OverrideDir=''):
-    if OverrideDir:
-        NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
-        if NewFile:
-            if OverrideDir[-1] == os.path.sep:
-                return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]
-            else:
-                return NewFile[len(OverrideDir)+1:], NewFile[0:len(OverrideDir)]
-
-    NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))]
-    if NewFile:
-        if Dir:
-            if Dir[-1] == os.path.sep:
-                return NewFile[len(Dir):], NewFile[0:len(Dir)]
-            else:
-                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 R8 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 R8 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 R8 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 R8 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
-#
-#   @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):
-    for P in PackageList:
-        if CName in P.Guids:
-            return P.Guids[CName]
-    return None
-
-## Get Protocol value from given packages
-#
-#   @param      CName           The CName of the GUID
-#   @param      PackageList     List of packages looking-up in
-#
-#   @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):
-    for P in PackageList:
-        if CName in P.Protocols:
-            return P.Protocols[CName]
-    return None
-
-## Get PPI value from given packages
-#
-#   @param      CName           The CName of the GUID
-#   @param      PackageList     List of packages looking-up in
-#
-#   @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):
-    for P in PackageList:
-        if CName in P.Ppis:
-            return P.Ppis[CName]
-    return None
-
-## A string template class
-#
-#  This class implements a template for string replacement. A string template
-#  looks like following
-#
-#       ${BEGIN} other_string ${placeholder_name} other_string ${END}
-#
-#  The string between ${BEGIN} and ${END} will be repeated as many times as the
-#  length of "placeholder_name", which is a list passed through a dict. The
-#  "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
-#  be not used and, in this case, the "placeholder_name" must not a list and it
-#  will just be replaced once.
-#
-class TemplateString(object):
-    _REPEAT_START_FLAG = "BEGIN"
-    _REPEAT_END_FLAG = "END"
-
-    class Section(object):
-        _LIST_TYPES = [type([]), type(set()), type((0,))]
-
-        def __init__(self, TemplateSection, PlaceHolderList):
-            self._Template = TemplateSection
-            self._PlaceHolderList = []
-
-            # Split the section into sub-sections according to the position of placeholders
-            if PlaceHolderList:
-                self._SubSectionList = []
-                SubSectionStart = 0
-                #
-                # The placeholders passed in must be in the format of
-                #
-                #   PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
-                #
-                for PlaceHolder,Start,End in PlaceHolderList:
-                    self._SubSectionList.append(TemplateSection[SubSectionStart:Start])
-                    self._SubSectionList.append(TemplateSection[Start:End])
-                    self._PlaceHolderList.append(PlaceHolder)
-                    SubSectionStart = End
-                if SubSectionStart < len(TemplateSection):
-                    self._SubSectionList.append(TemplateSection[SubSectionStart:])
-            else:
-                self._SubSectionList = [TemplateSection]
-
-        def __str__(self):
-            return self._Template + " : " + str(self._PlaceHolderList)
-
-        def Instantiate(self, PlaceHolderValues):
-            RepeatTime = -1
-            RepeatPlaceHolders = {}
-            NonRepeatPlaceHolders = {}
-
-            for PlaceHolder in self._PlaceHolderList:
-                if PlaceHolder not in PlaceHolderValues:
-                    continue
-                Value = PlaceHolderValues[PlaceHolder]
-                if type(Value) in self._LIST_TYPES:
-                    if RepeatTime < 0:
-                        RepeatTime = len(Value)
-                    elif RepeatTime != len(Value):
-                        EdkLogger.error(
-                                    "TemplateString",
-                                    PARAMETER_INVALID,
-                                    "${%s} has different repeat time from others!" % PlaceHolder,
-                                    ExtraData=str(self._Template)
-                                    )
-                    RepeatPlaceHolders["${%s}" % PlaceHolder] = Value
-                else:
-                    NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value
-
-            if NonRepeatPlaceHolders:
-                StringList = []
-                for S in self._SubSectionList:
-                    if S not in NonRepeatPlaceHolders:
-                        StringList.append(S)
-                    else:
-                        StringList.append(str(NonRepeatPlaceHolders[S]))
-            else:
-                StringList = self._SubSectionList
-
-            if RepeatPlaceHolders:
-                TempStringList = []
-                for Index in range(RepeatTime):
-                    for S in StringList:
-                        if S not in RepeatPlaceHolders:
-                            TempStringList.append(S)
-                        else:
-                            TempStringList.append(str(RepeatPlaceHolders[S][Index]))
-                StringList = TempStringList
-
-            return "".join(StringList)
-
-    ## Constructor
-    def __init__(self, Template=None):
-        self.String = ''
-        self.IsBinary = False
-        self._Template = Template
-        self._TemplateSectionList = self._Parse(Template)
-
-    ## str() operator
-    #
-    #   @retval     string  The string replaced
-    #
-    def __str__(self):
-        return self.String
-
-    ## Split the template string into fragments per the ${BEGIN} and ${END} flags
-    #
-    #   @retval     list    A list of TemplateString.Section objects
-    #
-    def _Parse(self, Template):
-        SectionStart = 0
-        SearchFrom = 0
-        MatchEnd = 0
-        PlaceHolderList = []
-        TemplateSectionList = []
-        while Template:
-            MatchObj = gPlaceholderPattern.search(Template, SearchFrom)
-            if not MatchObj:
-                if MatchEnd < len(Template):
-                    TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList)
-                    TemplateSectionList.append(TemplateSection)
-                break
-
-            MatchString = MatchObj.group(1)
-            MatchStart = MatchObj.start()
-            MatchEnd = MatchObj.end()
-
-            if MatchString == self._REPEAT_START_FLAG:
-                if MatchStart > SectionStart:
-                    TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
-                    TemplateSectionList.append(TemplateSection)
-                SectionStart = MatchEnd
-                PlaceHolderList = []
-            elif MatchString == self._REPEAT_END_FLAG:
-                TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
-                TemplateSectionList.append(TemplateSection)
-                SectionStart = MatchEnd
-                PlaceHolderList = []
-            else:
-                PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart))
-            SearchFrom = MatchEnd
-        return TemplateSectionList
-
-    ## Replace the string template with dictionary of placeholders and append it to previous one
-    #
-    #   @param      AppendString    The string template to append
-    #   @param      Dictionary      The placeholder dictionaries
-    #
-    def Append(self, AppendString, Dictionary=None):
-        if Dictionary:
-            SectionList = self._Parse(AppendString)
-            self.String += "".join([S.Instantiate(Dictionary) for S in SectionList])
-        else:
-            self.String += AppendString
-
-    ## Replace the string template with dictionary of placeholders
-    #
-    #   @param      Dictionary      The placeholder dictionaries
-    #
-    #   @retval     str             The string replaced with placeholder values
-    #
-    def Replace(self, Dictionary=None):
-        return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList])
-
-## Progress indicator class
-#
-#  This class makes use of thread to print progress on console.
-#
-class Progressor:
-    # for avoiding deadloop
-    _StopFlag = None
-    _ProgressThread = None
-    _CheckInterval = 0.25
-
-    ## Constructor
-    #
-    #   @param      OpenMessage     The string printed before progress charaters
-    #   @param      CloseMessage    The string printed after progress charaters
-    #   @param      ProgressChar    The charater used to indicate the progress
-    #   @param      Interval        The interval in seconds between two progress charaters
-    #
-    def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0):
-        self.PromptMessage = OpenMessage
-        self.CodaMessage = CloseMessage
-        self.ProgressChar = ProgressChar
-        self.Interval = Interval
-        if Progressor._StopFlag == None:
-            Progressor._StopFlag = threading.Event()
-
-    ## Start to print progress charater
-    #
-    #   @param      OpenMessage     The string printed before progress charaters
-    #
-    def Start(self, OpenMessage=None):
-        if OpenMessage != None:
-            self.PromptMessage = OpenMessage
-        Progressor._StopFlag.clear()
-        if Progressor._ProgressThread == None:
-            Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)
-            Progressor._ProgressThread.setDaemon(False)
-            Progressor._ProgressThread.start()
-
-    ## Stop printing progress charater
-    #
-    #   @param      CloseMessage    The string printed after progress charaters
-    #
-    def Stop(self, CloseMessage=None):
-        OriginalCodaMessage = self.CodaMessage
-        if CloseMessage != None:
-            self.CodaMessage = CloseMessage
-        self.Abort()
-        self.CodaMessage = OriginalCodaMessage
-
-    ## Thread entry method
-    def _ProgressThreadEntry(self):
-        sys.stdout.write(self.PromptMessage + " ")
-        sys.stdout.flush()
-        TimeUp = 0.0
-        while not Progressor._StopFlag.isSet():
-            if TimeUp <= 0.0:
-                sys.stdout.write(self.ProgressChar)
-                sys.stdout.flush()
-                TimeUp = self.Interval
-            time.sleep(self._CheckInterval)
-            TimeUp -= self._CheckInterval
-        sys.stdout.write(" " + self.CodaMessage + "\n")
-        sys.stdout.flush()
-
-    ## Abort the progress display
-    @staticmethod
-    def Abort():
-        if Progressor._StopFlag != None:
-            Progressor._StopFlag.set()
-        if Progressor._ProgressThread != None:
-            Progressor._ProgressThread.join()
-            Progressor._ProgressThread = None
-
-## A dict which can access its keys and/or values orderly
-#
-#  The class implements a new kind of dict which its keys or values can be
-#  accessed in the order they are added into the dict. It guarantees the order
-#  by making use of an internal list to keep a copy of keys.
-#
-class sdict(IterableUserDict):
-    ## Constructor
-    def __init__(self):
-        IterableUserDict.__init__(self)
-        self._key_list = []
-
-    ## [] operator
-    def __setitem__(self, key, value):
-        if key not in self._key_list:
-            self._key_list.append(key)
-        IterableUserDict.__setitem__(self, key, value)
-
-    ## del operator
-    def __delitem__(self, key):
-        self._key_list.remove(key)
-        IterableUserDict.__delitem__(self, key)
-
-    ## used in "for k in dict" loop to ensure the correct order
-    def __iter__(self):
-        return self.iterkeys()
-
-    ## len() support
-    def __len__(self):
-        return len(self._key_list)
-
-    ## "in" test support
-    def __contains__(self, key):
-        return key in self._key_list
-
-    ## indexof support
-    def index(self, key):
-        return self._key_list.index(key)
-
-    ## insert support
-    def insert(self, key, newkey, newvalue, order):
-        index = self._key_list.index(key)
-        if order == 'BEFORE':
-            self._key_list.insert(index, newkey)
-            IterableUserDict.__setitem__(self, newkey, newvalue)
-        elif order == 'AFTER':
-            self._key_list.insert(index + 1, newkey)
-            IterableUserDict.__setitem__(self, newkey, newvalue)
-
-    ## append support
-    def append(self, sdict):
-        for key in sdict:
-            if key not in self._key_list:
-                self._key_list.append(key)
-            IterableUserDict.__setitem__(self, key, sdict[key])
-
-    def has_key(self, key):
-        return key in self._key_list
-
-    ## Empty the dict
-    def clear(self):
-        self._key_list = []
-        IterableUserDict.clear(self)
-
-    ## Return a copy of keys
-    def keys(self):
-        keys = []
-        for key in self._key_list:
-            keys.append(key)
-        return keys
-
-    ## Return a copy of values
-    def values(self):
-        values = []
-        for key in self._key_list:
-            values.append(self[key])
-        return values
-
-    ## Return a copy of (key, value) list
-    def items(self):
-        items = []
-        for key in self._key_list:
-            items.append((key, self[key]))
-        return items
-
-    ## Iteration support
-    def iteritems(self):
-        return iter(self.items())
-
-    ## Keys interation support
-    def iterkeys(self):
-        return iter(self.keys())
-
-    ## Values interation support
-    def itervalues(self):
-        return iter(self.values())
-
-    ## Return value related to a key, and remove the (key, value) from the dict
-    def pop(self, key, *dv):
-        value = None
-        if key in self._key_list:
-            value = self[key]
-            self.__delitem__(key)
-        elif len(dv) != 0 :
-            value = kv[0]
-        return value
-
-    ## Return (key, value) pair, and remove the (key, value) from the dict
-    def popitem(self):
-        key = self._key_list[-1]
-        value = self[key]
-        self.__delitem__(key)
-        return key, value
-
-    def update(self, dict=None, **kwargs):
-        if dict != None:
-            for k, v in dict.items():
-                self[k] = v
-        if len(kwargs):
-            for k, v in kwargs.items():
-                self[k] = v
-
-## Dictionary with restricted keys
-#
-class rdict(dict):
-    ## Constructor
-    def __init__(self, KeyList):
-        for Key in KeyList:
-            dict.__setitem__(self, Key, "")
-
-    ## []= operator
-    def __setitem__(self, key, value):
-        if key not in self:
-            EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key,
-                            ExtraData=", ".join(dict.keys(self)))
-        dict.__setitem__(self, key, value)
-
-    ## =[] operator
-    def __getitem__(self, key):
-        if key not in self:
-            return ""
-        return dict.__getitem__(self, key)
-
-    ## del operator
-    def __delitem__(self, key):
-        EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del")
-
-    ## Empty the dict
-    def clear(self):
-        for Key in self:
-            self.__setitem__(Key, "")
-
-    ## Return value related to a key, and remove the (key, value) from the dict
-    def pop(self, key, *dv):
-        EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop")
-
-    ## Return (key, value) pair, and remove the (key, value) from the dict
-    def popitem(self):
-        EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem")
-
-## Dictionary using prioritized list as key
-#
-class tdict:
-    _ListType = type([])
-    _TupleType = type(())
-    _Wildcard = 'COMMON'
-    _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
-
-    def __init__(self, _Single_=False, _Level_=2):
-        self._Level_ = _Level_
-        self.data = {}
-        self._Single_ = _Single_
-
-    # =[] operator
-    def __getitem__(self, key):
-        KeyType = type(key)
-        RestKeys = None
-        if KeyType == self._ListType or KeyType == self._TupleType:
-            FirstKey = key[0]
-            if len(key) > 1:
-                RestKeys = key[1:]
-            elif 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)]
-
-        if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:
-            FirstKey = self._Wildcard
-
-        if self._Single_:
-            return self._GetSingleValue(FirstKey, RestKeys)
-        else:
-            return self._GetAllValues(FirstKey, RestKeys)
-
-    def _GetSingleValue(self, FirstKey, RestKeys):
-        Value = None
-        #print "%s-%s" % (FirstKey, self._Level_) ,
-        if self._Level_ > 1:
-            if FirstKey == self._Wildcard:
-                if FirstKey in self.data:
-                    Value = self.data[FirstKey][RestKeys]
-                if Value == None:
-                    for Key in self.data:
-                        Value = self.data[Key][RestKeys]
-                        if Value != None: break
-            else:
-                if FirstKey in self.data:
-                    Value = self.data[FirstKey][RestKeys]
-                if Value == 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:
-                    for Key in self.data:
-                        Value = self.data[Key]
-                        if Value != None: break
-            else:
-                if FirstKey in self.data:
-                    Value = self.data[FirstKey]
-                elif self._Wildcard in self.data:
-                    Value = self.data[self._Wildcard]
-        return Value
-
-    def _GetAllValues(self, FirstKey, RestKeys):
-        Value = []
-        if self._Level_ > 1:
-            if FirstKey == self._Wildcard:
-                for Key in self.data:
-                    Value += self.data[Key][RestKeys]
-            else:
-                if FirstKey in self.data:
-                    Value += self.data[FirstKey][RestKeys]
-                if self._Wildcard in self.data:
-                    Value += self.data[self._Wildcard][RestKeys]
-        else:
-            if FirstKey == self._Wildcard:
-                for Key in self.data:
-                    Value.append(self.data[Key])
-            else:
-                if FirstKey in self.data:
-                    Value.append(self.data[FirstKey])
-                if self._Wildcard in self.data:
-                    Value.append(self.data[self._Wildcard])
-        return Value
-
-    ## []= operator
-    def __setitem__(self, key, value):
-        KeyType = type(key)
-        RestKeys = None
-        if KeyType == self._ListType or KeyType == self._TupleType:
-            FirstKey = key[0]
-            if len(key) > 1:
-                RestKeys = key[1:]
-            else:
-                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)]
-
-        if FirstKey in self._ValidWildcardList:
-            FirstKey = self._Wildcard
-
-        if FirstKey not in self.data and self._Level_ > 0:
-            self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1)
-
-        if self._Level_ > 1:
-            self.data[FirstKey][RestKeys] = value
-        else:
-            self.data[FirstKey] = value
-
-    def SetGreedyMode(self):
-        self._Single_ = False
-        if self._Level_ > 1:
-            for Key in self.data:
-                self.data[Key].SetGreedyMode()
-
-    def SetSingleMode(self):
-        self._Single_ = True
-        if self._Level_ > 1:
-            for Key in self.data:
-                self.data[Key].SetSingleMode()
-
-    def GetKeys(self, KeyIndex=0):
-        assert KeyIndex >= 0
-        if KeyIndex == 0:
-            return set(self.data.keys())
-        else:
-            keys = set()
-            for Key in self.data:
-                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 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)
-
-    Opr.close()
-    Opw.close()
-
-## check format of PCD value against its the datum type
-#
-# For PCD value setting
-#
-def CheckPcdDatum(Type, Value):
-    if Type == "VOID*":
-        if not ((Value.startswith('L"') or Value.startswith('"') and Value.endswith('"'))
-                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)
-    elif Type == 'BOOLEAN':
-        if Value not in ['TRUE', 'FALSE']:
-            return False, "Invalid value [%s] of type [%s]; must be TRUE or FALSE" % (Value, Type)
-    elif type(Value) == type(""):
-        try:
-            Value = long(Value, 0)
-        except:
-            return False, "Invalid value [%s] of type [%s];"\
-                          " must be a hexadecimal, decimal or octal in C language format."\
-                            % (Value, Type)
-
-    return True, ""
-
-## Split command line option string to list
-#
-# subprocess.Popen needs the args to be a sequence. Otherwise there's problem
-# in non-windows platform to launch command
-#
-def SplitOption(OptionString):
-    OptionList = []
-    LastChar = " "
-    OptionStart = 0
-    QuotationMark = ""
-    for Index in range(0, len(OptionString)):
-        CurrentChar = OptionString[Index]
-        if CurrentChar in ['"', "'"]:
-            if QuotationMark == CurrentChar:
-                QuotationMark = ""
-            elif QuotationMark == "":
-                QuotationMark = CurrentChar
-            continue
-        elif QuotationMark:
-            continue
-
-        if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
-            if Index > OptionStart:
-                OptionList.append(OptionString[OptionStart:Index-1])
-            OptionStart = Index
-        LastChar = CurrentChar
-    OptionList.append(OptionString[OptionStart:])
-    return OptionList
-
-def CommonPath(PathList):
-    P1 = min(PathList).split(os.path.sep)
-    P2 = max(PathList).split(os.path.sep)
-    for Index in xrange(min(len(P1), len(P2))):
-        if P1[Index] != P2[Index]:
-            return os.path.sep.join(P1[:Index])
-    return os.path.sep.join(P1)
-
-class PathClass(object):
-    def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
-                 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''):
-        self.Arch = Arch
-        self.File = str(File)
-        if os.path.isabs(self.File):
-            self.Root = ''
-            self.AlterRoot = ''
-        else:
-            self.Root = str(Root)
-            self.AlterRoot = str(AlterRoot)
-
-        # Remove any '.' and '..' in path
-        if self.Root:
-            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:'
-            if self.Root[-1] == ':':
-                self.Root += os.path.sep
-            # file path should not start with path separator
-            if self.Root[-1] == os.path.sep:
-                self.File = self.Path[len(self.Root):]
-            else:
-                self.File = self.Path[len(self.Root)+1:]
-        else:
-            self.Path = os.path.normpath(self.File)
-
-        self.SubDir, self.Name = os.path.split(self.File)
-        self.BaseName, self.Ext = os.path.splitext(self.Name)
-
-        if self.Root:
-            if self.SubDir:
-                self.Dir = os.path.join(self.Root, self.SubDir)
-            else:
-                self.Dir = self.Root
-        else:
-            self.Dir = self.SubDir
-
-        if IsBinary:
-            self.Type = Type
-        else:
-            self.Type = self.Ext.lower()
-
-        self.IsBinary = IsBinary
-        self.Target = Target
-        self.TagName = TagName
-        self.ToolCode = ToolCode
-        self.ToolChainFamily = ToolChainFamily
-
-        self._Key = None
-
-    ## Convert the object of this class to a string
-    #
-    #  Convert member Path of the class to a string
-    #
-    #  @retval string Formatted String
-    #
-    def __str__(self):
-        return self.Path
-
-    ## Override __eq__ function
-    #
-    # Check whether PathClass are the same
-    #
-    # @retval False The two PathClass are different
-    # @retval True  The two PathClass are the same
-    #
-    def __eq__(self, Other):
-        if type(Other) == type(self):
-            return self.Path == Other.Path
-        else:
-            return self.Path == str(Other)
-
-    ## Override __hash__ function
-    #
-    # Use Path as key in hash table
-    #
-    # @retval string Key for hash table
-    #
-    def __hash__(self):
-        return hash(self.Path)
-
-    def _GetFileKey(self):
-        if self._Key == None:
-            self._Key = self.Path.upper()   # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
-        return self._Key
-
-    def Validate(self, Type='', CaseSensitive=True):
-        if GlobalData.gCaseInsensitive:
-            CaseSensitive = False
-        if Type and Type.lower() != self.Type:
-            return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type)
-
-        RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
-        if not RealRoot and not RealFile:
-            return FILE_NOT_FOUND, self.File
-
-        ErrorCode = 0
-        ErrorInfo = ''
-        if RealRoot != self.Root or RealFile != self.File:
-            if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)):
-                ErrorCode = FILE_CASE_MISMATCH
-                ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]"
-
-            self.SubDir, self.Name = os.path.split(RealFile)
-            self.BaseName, self.Ext = os.path.splitext(self.Name)
-            if self.SubDir:
-                self.Dir = os.path.join(RealRoot, self.SubDir)
-            else:
-                self.Dir = RealRoot
-            self.File = RealFile
-            self.Root = RealRoot
-            self.Path = os.path.join(RealRoot, RealFile)
-        return ErrorCode, ErrorInfo
-
-    Key = property(_GetFileKey)
-
-##
-#
-# This acts like the main() function for the script, unless it is 'import'ed into another
-# script.
-#
-if __name__ == '__main__':
-    pass
-
+## @file\r
+# Common routines used by all tools\r
+#\r
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+##\r
+# Import Modules\r
+#\r
+import Common.LongFilePathOs as os\r
+import sys\r
+import string\r
+import thread\r
+import threading\r
+import time\r
+import re\r
+import cPickle\r
+import array\r
+import shutil\r
+from struct import pack\r
+from UserDict import IterableUserDict\r
+from UserList import UserList\r
+\r
+from Common import EdkLogger as EdkLogger\r
+from Common import GlobalData as GlobalData\r
+from DataType import *\r
+from BuildToolError import *\r
+from CommonDataClass.DataClass import *\r
+from Parsing import GetSplitValueList\r
+from Common.LongFilePathSupport import OpenLongFilePath as open\r
+from Common.MultipleWorkspace import MultipleWorkspace as mws\r
+import uuid\r
+from CommonDataClass.Exceptions import BadExpression\r
+import subprocess\r
+## Regular expression used to find out place holders in string template\r
+gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)\r
+\r
+## Dictionary used to store file time stamp for quick re-access\r
+gFileTimeStampCache = {}    # {file path : file time stamp}\r
+\r
+## Dictionary used to store dependencies of files\r
+gDependencyDatabase = {}    # arch : {file path : [dependent files list]}\r
+\r
+def GetVariableOffset(mapfilepath, efifilepath, varnames):\r
+    """ Parse map file to get variable offset in current EFI file \r
+    @param mapfilepath    Map file absolution path\r
+    @param efifilepath:   EFI binary file full path\r
+    @param varnames       iteratable container whose elements are variable names to be searched\r
+    \r
+    @return List whos elements are tuple with variable name and raw offset\r
+    """\r
+    lines = []\r
+    try:\r
+        f = open(mapfilepath, 'r')\r
+        lines = f.readlines()\r
+        f.close()\r
+    except:\r
+        return None\r
+    \r
+    if len(lines) == 0: return None\r
+    firstline = lines[0].strip()\r
+    if (firstline.startswith("Archive member included ") and\r
+        firstline.endswith(" file (symbol)")):\r
+        return _parseForGCC(lines, efifilepath, varnames)\r
+    if firstline.startswith("# Path:"):\r
+        return _parseForXcode(lines, efifilepath, varnames)\r
+    return _parseGeneral(lines, efifilepath, varnames)\r
+\r
+def _parseForXcode(lines, efifilepath, varnames):\r
+    status = 0\r
+    ret = []\r
+    for index, line in enumerate(lines):\r
+        line = line.strip()\r
+        if status == 0 and line == "# Symbols:":\r
+            status = 1\r
+            continue\r
+        if status == 1 and len(line) != 0:\r
+            for varname in varnames:\r
+                if varname in line:\r
+                    m = re.match('^([\da-fA-FxX]+)([\s\S]*)([_]*%s)$' % varname, line)\r
+                    if m != None:\r
+                        ret.append((varname, m.group(1)))\r
+    return ret\r
+\r
+def _parseForGCC(lines, efifilepath, varnames):\r
+    """ Parse map file generated by GCC linker """\r
+    status = 0\r
+    sections = []\r
+    varoffset = []\r
+    for index, line in enumerate(lines):\r
+        line = line.strip()\r
+        # status machine transection\r
+        if status == 0 and line == "Memory Configuration":\r
+            status = 1\r
+            continue\r
+        elif status == 1 and line == 'Linker script and memory map':\r
+            status = 2\r
+            continue\r
+        elif status ==2 and line == 'START GROUP':\r
+            status = 3\r
+            continue\r
+\r
+        # status handler\r
+        if status == 3:\r
+            m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line)\r
+            if m != None:\r
+                sections.append(m.groups(0))\r
+            for varname in varnames:\r
+                Str = ''\r
+                m = re.match("^.data.(%s)" % varname, line)\r
+                if m != None:\r
+                    m = re.match(".data.(%s)$" % varname, line)\r
+                    if m != None:\r
+                        Str = lines[index + 1]\r
+                    else:\r
+                        Str = line[len(".data.%s" % varname):]\r
+                    if Str:\r
+                        m = re.match('^([\da-fA-Fx]+) +([\da-fA-Fx]+)', Str.strip())\r
+                        if m != None:\r
+                            varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0]))\r
+\r
+    if not varoffset:\r
+        return []\r
+    # get section information from efi file\r
+    efisecs = PeImageClass(efifilepath).SectionHeaderList\r
+    if efisecs == None or len(efisecs) == 0:\r
+        return []\r
+    #redirection\r
+    redirection = 0\r
+    for efisec in efisecs:\r
+        for section in sections:\r
+            if section[0].strip() == efisec[0].strip() and section[0].strip() == '.text':\r
+                redirection = int(section[1], 16) - efisec[1]\r
+\r
+    ret = []\r
+    for var in varoffset:\r
+        for efisec in efisecs:\r
+            if var[1] >= efisec[1] and var[1] < efisec[1]+efisec[3]:\r
+                ret.append((var[0], hex(efisec[2] + var[1] - efisec[1] - redirection)))\r
+    return ret\r
+\r
+def _parseGeneral(lines, efifilepath, varnames):\r
+    status = 0    #0 - beginning of file; 1 - PE section definition; 2 - symbol table\r
+    secs  = []    # key = section name\r
+    varoffset = []\r
+    secRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE)\r
+    symRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re.UNICODE)\r
+\r
+    for line in lines:\r
+        line = line.strip()\r
+        if re.match("^Start[' ']+Length[' ']+Name[' ']+Class", line):\r
+            status = 1\r
+            continue\r
+        if re.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line):\r
+            status = 2\r
+            continue\r
+        if re.match("^entry point at", line):\r
+            status = 3\r
+            continue        \r
+        if status == 1 and len(line) != 0:\r
+            m =  secRe.match(line)\r
+            assert m != None, "Fail to parse the section in map file , line is %s" % line\r
+            sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0)\r
+            secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class])\r
+        if status == 2 and len(line) != 0:\r
+            for varname in varnames:\r
+                m = symRe.match(line)\r
+                assert m != None, "Fail to parse the symbol in map file, line is %s" % line\r
+                sec_no, sym_offset, sym_name, vir_addr = m.groups(0)\r
+                sec_no     = int(sec_no,     16)\r
+                sym_offset = int(sym_offset, 16)\r
+                vir_addr   = int(vir_addr,   16)\r
+                m2 = re.match('^[_]*(%s)' % varname, sym_name)\r
+                if m2 != None:\r
+                    # fond a binary pcd entry in map file\r
+                    for sec in secs:\r
+                        if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]):\r
+                            varoffset.append([varname, sec[3], sym_offset, vir_addr, sec_no])\r
+\r
+    if not varoffset: return []\r
+\r
+    # get section information from efi file\r
+    efisecs = PeImageClass(efifilepath).SectionHeaderList\r
+    if efisecs == None or len(efisecs) == 0:\r
+        return []\r
+\r
+    ret = []\r
+    for var in varoffset:\r
+        index = 0\r
+        for efisec in efisecs:\r
+            index = index + 1\r
+            if var[1].strip() == efisec[0].strip():\r
+                ret.append((var[0], hex(efisec[2] + var[2])))\r
+            elif var[4] == index:\r
+                ret.append((var[0], hex(efisec[2] + var[2])))\r
+\r
+    return ret\r
+\r
+## Routine to process duplicated INF\r
+#\r
+#  This function is called by following two cases:\r
+#  Case 1 in DSC:\r
+#    [components.arch]\r
+#    Pkg/module/module.inf\r
+#    Pkg/module/module.inf {\r
+#      <Defines>\r
+#        FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836\r
+#    }\r
+#  Case 2 in FDF:\r
+#    INF Pkg/module/module.inf\r
+#    INF FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836 Pkg/module/module.inf\r
+#\r
+#  This function copies Pkg/module/module.inf to\r
+#  Conf/.cache/0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf\r
+#\r
+#  @param Path     Original PathClass object\r
+#  @param BaseName New file base name\r
+#\r
+#  @retval         return the new PathClass object\r
+#\r
+def ProcessDuplicatedInf(Path, BaseName, Workspace):\r
+    Filename = os.path.split(Path.File)[1]\r
+    if '.' in Filename:\r
+        Filename = BaseName + Path.BaseName + Filename[Filename.rfind('.'):]\r
+    else:\r
+        Filename = BaseName + Path.BaseName\r
+\r
+    #\r
+    # If -N is specified on command line, cache is disabled\r
+    # The directory has to be created\r
+    #\r
+    DbDir = os.path.split(GlobalData.gDatabasePath)[0]\r
+    if not os.path.exists(DbDir):\r
+        os.makedirs(DbDir)\r
+    #\r
+    # A temporary INF is copied to database path which must have write permission\r
+    # The temporary will be removed at the end of build\r
+    # In case of name conflict, the file name is \r
+    # FILE_GUIDBaseName (0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf)\r
+    #\r
+    TempFullPath = os.path.join(DbDir,\r
+                                Filename)\r
+    RtPath = PathClass(Path.File, Workspace)\r
+    #\r
+    # Modify the full path to temporary path, keep other unchanged\r
+    #\r
+    # To build same module more than once, the module path with FILE_GUID overridden has\r
+    # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path\r
+    # in DSC which is used as relative path by C files and other files in INF. \r
+    # A trick was used: all module paths are PathClass instances, after the initialization\r
+    # of PathClass, the PathClass.Path is overridden by the temporary INF path.\r
+    #\r
+    # The reason for creating a temporary INF is:\r
+    # Platform.Modules which is the base to create ModuleAutoGen objects is a dictionary,\r
+    # the key is the full path of INF, the value is an object to save overridden library instances, PCDs.\r
+    # A different key for the same module is needed to create different output directory,\r
+    # retrieve overridden PCDs, library instances.\r
+    #\r
+    # The BaseName is the FILE_GUID which is also the output directory name.\r
+    #\r
+    #\r
+    RtPath.Path = TempFullPath\r
+    RtPath.BaseName = BaseName\r
+    #\r
+    # If file exists, compare contents\r
+    #\r
+    if os.path.exists(TempFullPath):\r
+        with open(str(Path), 'rb') as f1: Src = f1.read()\r
+        with open(TempFullPath, 'rb') as f2: Dst = f2.read()\r
+        if Src == Dst:\r
+            return RtPath\r
+    GlobalData.gTempInfs.append(TempFullPath)\r
+    shutil.copy2(str(Path), TempFullPath)\r
+    return RtPath\r
+\r
+## Remove temporary created INFs whose paths were saved in gTempInfs\r
+#\r
+def ClearDuplicatedInf():\r
+    for File in GlobalData.gTempInfs:\r
+        if os.path.exists(File):\r
+            os.remove(File)\r
+\r
+## callback routine for processing variable option\r
+#\r
+# This function can be used to process variable number of option values. The\r
+# typical usage of it is specify architecure list on command line.\r
+# (e.g. <tool> -a IA32 X64 IPF)\r
+#\r
+# @param  Option        Standard callback function parameter\r
+# @param  OptionString  Standard callback function parameter\r
+# @param  Value         Standard callback function parameter\r
+# @param  Parser        Standard callback function parameter\r
+#\r
+# @retval\r
+#\r
+def ProcessVariableArgument(Option, OptionString, Value, Parser):\r
+    assert Value is None\r
+    Value = []\r
+    RawArgs = Parser.rargs\r
+    while RawArgs:\r
+        Arg = RawArgs[0]\r
+        if (Arg[:2] == "--" and len(Arg) > 2) or \\r
+           (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"):\r
+            break\r
+        Value.append(Arg)\r
+        del RawArgs[0]\r
+    setattr(Parser.values, Option.dest, Value)\r
+\r
+## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style\r
+#\r
+#   @param      Guid    The GUID string\r
+#\r
+#   @retval     string  The GUID string in C structure style\r
+#\r
+def GuidStringToGuidStructureString(Guid):\r
+    GuidList = Guid.split('-')\r
+    Result = '{'\r
+    for Index in range(0, 3, 1):\r
+        Result = Result + '0x' + GuidList[Index] + ', '\r
+    Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]\r
+    for Index in range(0, 12, 2):\r
+        Result = Result + ', 0x' + GuidList[4][Index:Index + 2]\r
+    Result += '}}'\r
+    return Result\r
+\r
+## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r
+#\r
+#   @param      GuidValue   The GUID value in byte array\r
+#\r
+#   @retval     string      The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format\r
+#\r
+def GuidStructureByteArrayToGuidString(GuidValue):\r
+    guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")\r
+    guidValueList = guidValueString.split(",")\r
+    if len(guidValueList) != 16:\r
+        return ''\r
+        #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)\r
+    try:\r
+        return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (\r
+                int(guidValueList[3], 16),\r
+                int(guidValueList[2], 16),\r
+                int(guidValueList[1], 16),\r
+                int(guidValueList[0], 16),\r
+                int(guidValueList[5], 16),\r
+                int(guidValueList[4], 16),\r
+                int(guidValueList[7], 16),\r
+                int(guidValueList[6], 16),\r
+                int(guidValueList[8], 16),\r
+                int(guidValueList[9], 16),\r
+                int(guidValueList[10], 16),\r
+                int(guidValueList[11], 16),\r
+                int(guidValueList[12], 16),\r
+                int(guidValueList[13], 16),\r
+                int(guidValueList[14], 16),\r
+                int(guidValueList[15], 16)\r
+                )\r
+    except:\r
+        return ''\r
+\r
+## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r
+#\r
+#   @param      GuidValue   The GUID value in C structure format\r
+#\r
+#   @retval     string      The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format\r
+#\r
+def GuidStructureStringToGuidString(GuidValue):\r
+    guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")\r
+    guidValueList = guidValueString.split(",")\r
+    if len(guidValueList) != 11:\r
+        return ''\r
+        #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)\r
+    try:\r
+        return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (\r
+                int(guidValueList[0], 16),\r
+                int(guidValueList[1], 16),\r
+                int(guidValueList[2], 16),\r
+                int(guidValueList[3], 16),\r
+                int(guidValueList[4], 16),\r
+                int(guidValueList[5], 16),\r
+                int(guidValueList[6], 16),\r
+                int(guidValueList[7], 16),\r
+                int(guidValueList[8], 16),\r
+                int(guidValueList[9], 16),\r
+                int(guidValueList[10], 16)\r
+                )\r
+    except:\r
+        return ''\r
+\r
+## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx\r
+#\r
+#   @param      GuidValue   The GUID value in C structure format\r
+#\r
+#   @retval     string      The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format\r
+#\r
+def GuidStructureStringToGuidValueName(GuidValue):\r
+    guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "")\r
+    guidValueList = guidValueString.split(",")\r
+    if len(guidValueList) != 11:\r
+        EdkLogger.error(None, FORMAT_INVALID, "Invalid GUID value string [%s]" % GuidValue)\r
+    return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (\r
+            int(guidValueList[0], 16),\r
+            int(guidValueList[1], 16),\r
+            int(guidValueList[2], 16),\r
+            int(guidValueList[3], 16),\r
+            int(guidValueList[4], 16),\r
+            int(guidValueList[5], 16),\r
+            int(guidValueList[6], 16),\r
+            int(guidValueList[7], 16),\r
+            int(guidValueList[8], 16),\r
+            int(guidValueList[9], 16),\r
+            int(guidValueList[10], 16)\r
+            )\r
+\r
+## Create directories\r
+#\r
+#   @param      Directory   The directory name\r
+#\r
+def CreateDirectory(Directory):\r
+    if Directory == None or Directory.strip() == "":\r
+        return True\r
+    try:\r
+        if not os.access(Directory, os.F_OK):\r
+            os.makedirs(Directory)\r
+    except:\r
+        return False\r
+    return True\r
+\r
+## Remove directories, including files and sub-directories in it\r
+#\r
+#   @param      Directory   The directory name\r
+#\r
+def RemoveDirectory(Directory, Recursively=False):\r
+    if Directory == None or Directory.strip() == "" or not os.path.exists(Directory):\r
+        return\r
+    if Recursively:\r
+        CurrentDirectory = os.getcwd()\r
+        os.chdir(Directory)\r
+        for File in os.listdir("."):\r
+            if os.path.isdir(File):\r
+                RemoveDirectory(File, Recursively)\r
+            else:\r
+                os.remove(File)\r
+        os.chdir(CurrentDirectory)\r
+    os.rmdir(Directory)\r
+\r
+## Check if given file is changed or not\r
+#\r
+#  This method is used to check if a file is changed or not between two build\r
+#  actions. It makes use a cache to store files timestamp.\r
+#\r
+#   @param      File    The path of file\r
+#\r
+#   @retval     True    If the given file is changed, doesn't exist, or can't be\r
+#                       found in timestamp cache\r
+#   @retval     False   If the given file is changed\r
+#\r
+def IsChanged(File):\r
+    if not os.path.exists(File):\r
+        return True\r
+\r
+    FileState = os.stat(File)\r
+    TimeStamp = FileState[-2]\r
+\r
+    if File in gFileTimeStampCache and TimeStamp == gFileTimeStampCache[File]:\r
+        FileChanged = False\r
+    else:\r
+        FileChanged = True\r
+        gFileTimeStampCache[File] = TimeStamp\r
+\r
+    return FileChanged\r
+\r
+## Store content in file\r
+#\r
+#  This method is used to save file only when its content is changed. This is\r
+#  quite useful for "make" system to decide what will be re-built and what won't.\r
+#\r
+#   @param      File            The path of file\r
+#   @param      Content         The new content of the file\r
+#   @param      IsBinaryFile    The flag indicating if the file is binary file or not\r
+#\r
+#   @retval     True            If the file content is changed and the file is renewed\r
+#   @retval     False           If the file content is the same\r
+#\r
+def SaveFileOnChange(File, Content, IsBinaryFile=True):\r
+    if not IsBinaryFile:\r
+        Content = Content.replace("\n", os.linesep)\r
+\r
+    if os.path.exists(File):\r
+        try:\r
+            if Content == open(File, "rb").read():\r
+                return False\r
+        except:\r
+            EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File)\r
+\r
+    DirName = os.path.dirname(File)\r
+    if not CreateDirectory(DirName):\r
+        EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName)\r
+    else:\r
+        if DirName == '':\r
+            DirName = os.getcwd()\r
+        if not os.access(DirName, os.W_OK):\r
+            EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)\r
+\r
+    try:\r
+        if GlobalData.gIsWindows:\r
+            try:\r
+                from PyUtility import SaveFileToDisk\r
+                if not SaveFileToDisk(File, Content):\r
+                    EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File)\r
+            except:\r
+                Fd = open(File, "wb")\r
+                Fd.write(Content)\r
+                Fd.close()\r
+        else:\r
+            Fd = open(File, "wb")\r
+            Fd.write(Content)\r
+            Fd.close()\r
+    except IOError, X:\r
+        EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X)\r
+\r
+    return True\r
+\r
+## Make a Python object persistent on file system\r
+#\r
+#   @param      Data    The object to be stored in file\r
+#   @param      File    The path of file to store the object\r
+#\r
+def DataDump(Data, File):\r
+    Fd = None\r
+    try:\r
+        Fd = open(File, 'wb')\r
+        cPickle.dump(Data, Fd, cPickle.HIGHEST_PROTOCOL)\r
+    except:\r
+        EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False)\r
+    finally:\r
+        if Fd != None:\r
+            Fd.close()\r
+\r
+## Restore a Python object from a file\r
+#\r
+#   @param      File    The path of file stored the object\r
+#\r
+#   @retval     object  A python object\r
+#   @retval     None    If failure in file operation\r
+#\r
+def DataRestore(File):\r
+    Data = None\r
+    Fd = None\r
+    try:\r
+        Fd = open(File, 'rb')\r
+        Data = cPickle.load(Fd)\r
+    except Exception, e:\r
+        EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e)))\r
+        Data = None\r
+    finally:\r
+        if Fd != None:\r
+            Fd.close()\r
+    return Data\r
+\r
+## Retrieve and cache the real path name in file system\r
+#\r
+#   @param      Root    The root directory of path relative to\r
+#\r
+#   @retval     str     The path string if the path exists\r
+#   @retval     None    If path doesn't exist\r
+#\r
+class DirCache:\r
+    _CACHE_ = set()\r
+    _UPPER_CACHE_ = {}\r
+\r
+    def __init__(self, Root):\r
+        self._Root = Root\r
+        for F in os.listdir(Root):\r
+            self._CACHE_.add(F)\r
+            self._UPPER_CACHE_[F.upper()] = F\r
+\r
+    # =[] operator\r
+    def __getitem__(self, Path):\r
+        Path = Path[len(os.path.commonprefix([Path, self._Root])):]\r
+        if not Path:\r
+            return self._Root\r
+        if Path and Path[0] == os.path.sep:\r
+            Path = Path[1:]\r
+        if Path in self._CACHE_:\r
+            return os.path.join(self._Root, Path)\r
+        UpperPath = Path.upper()\r
+        if UpperPath in self._UPPER_CACHE_:\r
+            return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])\r
+\r
+        IndexList = []\r
+        LastSepIndex = -1\r
+        SepIndex = Path.find(os.path.sep)\r
+        while SepIndex > -1:\r
+            Parent = UpperPath[:SepIndex]\r
+            if Parent not in self._UPPER_CACHE_:\r
+                break\r
+            LastSepIndex = SepIndex\r
+            SepIndex = Path.find(os.path.sep, LastSepIndex + 1)\r
+\r
+        if LastSepIndex == -1:\r
+            return None\r
+\r
+        Cwd = os.getcwd()\r
+        os.chdir(self._Root)\r
+        SepIndex = LastSepIndex\r
+        while SepIndex > -1:\r
+            Parent = Path[:SepIndex]\r
+            ParentKey = UpperPath[:SepIndex]\r
+            if ParentKey not in self._UPPER_CACHE_:\r
+                os.chdir(Cwd)\r
+                return None\r
+\r
+            if Parent in self._CACHE_:\r
+                ParentDir = Parent\r
+            else:\r
+                ParentDir = self._UPPER_CACHE_[ParentKey]\r
+            for F in os.listdir(ParentDir):\r
+                Dir = os.path.join(ParentDir, F)\r
+                self._CACHE_.add(Dir)\r
+                self._UPPER_CACHE_[Dir.upper()] = Dir\r
+\r
+            SepIndex = Path.find(os.path.sep, SepIndex + 1)\r
+\r
+        os.chdir(Cwd)\r
+        if Path in self._CACHE_:\r
+            return os.path.join(self._Root, Path)\r
+        elif UpperPath in self._UPPER_CACHE_:\r
+            return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])\r
+        return None\r
+\r
+## Get all files of a directory\r
+#\r
+# @param Root:       Root dir\r
+# @param SkipList :  The files need be skipped\r
+#\r
+# @retval  A list of all files\r
+#\r
+def GetFiles(Root, SkipList=None, FullPath=True):\r
+    OriPath = Root\r
+    FileList = []\r
+    for Root, Dirs, Files in os.walk(Root):\r
+        if SkipList:\r
+            for Item in SkipList:\r
+                if Item in Dirs:\r
+                    Dirs.remove(Item)\r
+\r
+        for File in Files:\r
+            File = os.path.normpath(os.path.join(Root, File))\r
+            if not FullPath:\r
+                File = File[len(OriPath) + 1:]\r
+            FileList.append(File)\r
+\r
+    return FileList\r
+\r
+## Check if gvien file exists or not\r
+#\r
+#   @param      File    File name or path to be checked\r
+#   @param      Dir     The directory the file is relative to\r
+#\r
+#   @retval     True    if file exists\r
+#   @retval     False   if file doesn't exists\r
+#\r
+def ValidFile(File, Ext=None):\r
+    if Ext != None:\r
+        Dummy, FileExt = os.path.splitext(File)\r
+        if FileExt.lower() != Ext.lower():\r
+            return False\r
+    if not os.path.exists(File):\r
+        return False\r
+    return True\r
+\r
+def RealPath(File, Dir='', OverrideDir=''):\r
+    NewFile = os.path.normpath(os.path.join(Dir, File))\r
+    NewFile = GlobalData.gAllFiles[NewFile]\r
+    if not NewFile and OverrideDir:\r
+        NewFile = os.path.normpath(os.path.join(OverrideDir, File))\r
+        NewFile = GlobalData.gAllFiles[NewFile]\r
+    return NewFile\r
+\r
+def RealPath2(File, Dir='', OverrideDir=''):\r
+    NewFile = None\r
+    if OverrideDir:\r
+        NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(OverrideDir, File))]\r
+        if NewFile:\r
+            if OverrideDir[-1] == os.path.sep:\r
+                return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]\r
+            else:\r
+                return NewFile[len(OverrideDir) + 1:], NewFile[0:len(OverrideDir)]\r
+    if GlobalData.gAllFiles:\r
+        NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))]\r
+    if not NewFile:\r
+        NewFile = os.path.normpath(os.path.join(Dir, File))\r
+        if not os.path.exists(NewFile):\r
+            return None, None\r
+    if NewFile:\r
+        if Dir:\r
+            if Dir[-1] == os.path.sep:\r
+                return NewFile[len(Dir):], NewFile[0:len(Dir)]\r
+            else:\r
+                return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)]\r
+        else:\r
+            return NewFile, ''\r
+\r
+    return None, None\r
+\r
+## Check if gvien file exists or not\r
+#\r
+#\r
+def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):\r
+    NewFile = File\r
+    if Ext != None:\r
+        Dummy, FileExt = os.path.splitext(File)\r
+        if FileExt.lower() != Ext.lower():\r
+            return False, File\r
+\r
+    # Replace the Edk macros\r
+    if OverrideDir != '' and OverrideDir != None:\r
+        if OverrideDir.find('$(EFI_SOURCE)') > -1:\r
+            OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)\r
+        if OverrideDir.find('$(EDK_SOURCE)') > -1:\r
+            OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)\r
+\r
+    # Replace the default dir to current dir\r
+    if Dir == '.':\r
+        Dir = os.getcwd()\r
+        Dir = Dir[len(Workspace) + 1:]\r
+\r
+    # First check if File has Edk definition itself\r
+    if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:\r
+        NewFile = File.replace('$(EFI_SOURCE)', EfiSource)\r
+        NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource)\r
+        NewFile = AllFiles[os.path.normpath(NewFile)]\r
+        if NewFile != None:\r
+            return True, NewFile\r
+\r
+    # Second check the path with override value\r
+    if OverrideDir != '' and OverrideDir != None:\r
+        NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]\r
+        if NewFile != None:\r
+            return True, NewFile\r
+\r
+    # Last check the path with normal definitions\r
+    File = os.path.join(Dir, File)\r
+    NewFile = AllFiles[os.path.normpath(File)]\r
+    if NewFile != None:\r
+        return True, NewFile\r
+\r
+    return False, File\r
+\r
+## Check if gvien file exists or not\r
+#\r
+#\r
+def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):\r
+    # Replace the Edk macros\r
+    if OverrideDir != '' and OverrideDir != None:\r
+        if OverrideDir.find('$(EFI_SOURCE)') > -1:\r
+            OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)\r
+        if OverrideDir.find('$(EDK_SOURCE)') > -1:\r
+            OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)\r
+\r
+    # Replace the default dir to current dir\r
+    # Dir is current module dir related to workspace\r
+    if Dir == '.':\r
+        Dir = os.getcwd()\r
+        Dir = Dir[len(Workspace) + 1:]\r
+\r
+    NewFile = File\r
+    RelaPath = AllFiles[os.path.normpath(Dir)]\r
+    NewRelaPath = RelaPath\r
+\r
+    while(True):\r
+        # First check if File has Edk definition itself\r
+        if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:\r
+            File = File.replace('$(EFI_SOURCE)', EfiSource)\r
+            File = File.replace('$(EDK_SOURCE)', EdkSource)\r
+            NewFile = AllFiles[os.path.normpath(File)]\r
+            if NewFile != None:\r
+                NewRelaPath = os.path.dirname(NewFile)\r
+                File = os.path.basename(NewFile)\r
+                #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]\r
+                break\r
+\r
+        # Second check the path with override value\r
+        if OverrideDir != '' and OverrideDir != None:\r
+            NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]\r
+            if NewFile != None:\r
+                #NewRelaPath = os.path.dirname(NewFile)\r
+                NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]\r
+                break\r
+\r
+        # Last check the path with normal definitions\r
+        NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))]\r
+        if NewFile != None:\r
+            break\r
+\r
+        # No file found\r
+        break\r
+\r
+    return NewRelaPath, RelaPath, File\r
+\r
+\r
+def GetRelPath(Path1, Path2):\r
+    FileName = os.path.basename(Path2)\r
+    L1 = os.path.normpath(Path1).split(os.path.normpath('/'))\r
+    L2 = os.path.normpath(Path2).split(os.path.normpath('/'))\r
+    for Index in range(0, len(L1)):\r
+        if L1[Index] != L2[Index]:\r
+            FileName = '../' * (len(L1) - Index)\r
+            for Index2 in range(Index, len(L2)):\r
+                FileName = os.path.join(FileName, L2[Index2])\r
+            break\r
+    return os.path.normpath(FileName)\r
+\r
+\r
+## Get GUID value from given packages\r
+#\r
+#   @param      CName           The CName of the GUID\r
+#   @param      PackageList     List of packages looking-up in\r
+#   @param      Inffile         The driver file\r
+#\r
+#   @retval     GuidValue   if the CName is found in any given package\r
+#   @retval     None        if the CName is not found in all given packages\r
+#\r
+def GuidValue(CName, PackageList, Inffile = None):\r
+    for P in PackageList:\r
+        GuidKeys = P.Guids.keys()\r
+        if Inffile and P._PrivateGuids:\r
+            if not Inffile.startswith(P.MetaFile.Dir):\r
+                GuidKeys = (dict.fromkeys(x for x in P.Guids if x not in P._PrivateGuids)).keys()\r
+        if CName in GuidKeys:\r
+            return P.Guids[CName]\r
+    return None\r
+\r
+## Get Protocol value from given packages\r
+#\r
+#   @param      CName           The CName of the GUID\r
+#   @param      PackageList     List of packages looking-up in\r
+#   @param      Inffile         The driver file\r
+#\r
+#   @retval     GuidValue   if the CName is found in any given package\r
+#   @retval     None        if the CName is not found in all given packages\r
+#\r
+def ProtocolValue(CName, PackageList, Inffile = None):\r
+    for P in PackageList:\r
+        ProtocolKeys = P.Protocols.keys()\r
+        if Inffile and P._PrivateProtocols:\r
+            if not Inffile.startswith(P.MetaFile.Dir):\r
+                ProtocolKeys = (dict.fromkeys(x for x in P.Protocols if x not in P._PrivateProtocols)).keys()\r
+        if CName in ProtocolKeys:\r
+            return P.Protocols[CName]\r
+    return None\r
+\r
+## Get PPI value from given packages\r
+#\r
+#   @param      CName           The CName of the GUID\r
+#   @param      PackageList     List of packages looking-up in\r
+#   @param      Inffile         The driver file\r
+#\r
+#   @retval     GuidValue   if the CName is found in any given package\r
+#   @retval     None        if the CName is not found in all given packages\r
+#\r
+def PpiValue(CName, PackageList, Inffile = None):\r
+    for P in PackageList:\r
+        PpiKeys = P.Ppis.keys()\r
+        if Inffile and P._PrivatePpis:\r
+            if not Inffile.startswith(P.MetaFile.Dir):\r
+                PpiKeys = (dict.fromkeys(x for x in P.Ppis if x not in P._PrivatePpis)).keys()\r
+        if CName in PpiKeys:\r
+            return P.Ppis[CName]\r
+    return None\r
+\r
+## A string template class\r
+#\r
+#  This class implements a template for string replacement. A string template\r
+#  looks like following\r
+#\r
+#       ${BEGIN} other_string ${placeholder_name} other_string ${END}\r
+#\r
+#  The string between ${BEGIN} and ${END} will be repeated as many times as the\r
+#  length of "placeholder_name", which is a list passed through a dict. The\r
+#  "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can\r
+#  be not used and, in this case, the "placeholder_name" must not a list and it\r
+#  will just be replaced once.\r
+#\r
+class TemplateString(object):\r
+    _REPEAT_START_FLAG = "BEGIN"\r
+    _REPEAT_END_FLAG = "END"\r
+\r
+    class Section(object):\r
+        _LIST_TYPES = [type([]), type(set()), type((0,))]\r
+\r
+        def __init__(self, TemplateSection, PlaceHolderList):\r
+            self._Template = TemplateSection\r
+            self._PlaceHolderList = []\r
+\r
+            # Split the section into sub-sections according to the position of placeholders\r
+            if PlaceHolderList:\r
+                self._SubSectionList = []\r
+                SubSectionStart = 0\r
+                #\r
+                # The placeholders passed in must be in the format of\r
+                #\r
+                #   PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint\r
+                #\r
+                for PlaceHolder, Start, End in PlaceHolderList:\r
+                    self._SubSectionList.append(TemplateSection[SubSectionStart:Start])\r
+                    self._SubSectionList.append(TemplateSection[Start:End])\r
+                    self._PlaceHolderList.append(PlaceHolder)\r
+                    SubSectionStart = End\r
+                if SubSectionStart < len(TemplateSection):\r
+                    self._SubSectionList.append(TemplateSection[SubSectionStart:])\r
+            else:\r
+                self._SubSectionList = [TemplateSection]\r
+\r
+        def __str__(self):\r
+            return self._Template + " : " + str(self._PlaceHolderList)\r
+\r
+        def Instantiate(self, PlaceHolderValues):\r
+            RepeatTime = -1\r
+            RepeatPlaceHolders = {}\r
+            NonRepeatPlaceHolders = {}\r
+\r
+            for PlaceHolder in self._PlaceHolderList:\r
+                if PlaceHolder not in PlaceHolderValues:\r
+                    continue\r
+                Value = PlaceHolderValues[PlaceHolder]\r
+                if type(Value) in self._LIST_TYPES:\r
+                    if RepeatTime < 0:\r
+                        RepeatTime = len(Value)\r
+                    elif RepeatTime != len(Value):\r
+                        EdkLogger.error(\r
+                                    "TemplateString",\r
+                                    PARAMETER_INVALID,\r
+                                    "${%s} has different repeat time from others!" % PlaceHolder,\r
+                                    ExtraData=str(self._Template)\r
+                                    )\r
+                    RepeatPlaceHolders["${%s}" % PlaceHolder] = Value\r
+                else:\r
+                    NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value\r
+\r
+            if NonRepeatPlaceHolders:\r
+                StringList = []\r
+                for S in self._SubSectionList:\r
+                    if S not in NonRepeatPlaceHolders:\r
+                        StringList.append(S)\r
+                    else:\r
+                        StringList.append(str(NonRepeatPlaceHolders[S]))\r
+            else:\r
+                StringList = self._SubSectionList\r
+\r
+            if RepeatPlaceHolders:\r
+                TempStringList = []\r
+                for Index in range(RepeatTime):\r
+                    for S in StringList:\r
+                        if S not in RepeatPlaceHolders:\r
+                            TempStringList.append(S)\r
+                        else:\r
+                            TempStringList.append(str(RepeatPlaceHolders[S][Index]))\r
+                StringList = TempStringList\r
+\r
+            return "".join(StringList)\r
+\r
+    ## Constructor\r
+    def __init__(self, Template=None):\r
+        self.String = ''\r
+        self.IsBinary = False\r
+        self._Template = Template\r
+        self._TemplateSectionList = self._Parse(Template)\r
+\r
+    ## str() operator\r
+    #\r
+    #   @retval     string  The string replaced\r
+    #\r
+    def __str__(self):\r
+        return self.String\r
+\r
+    ## Split the template string into fragments per the ${BEGIN} and ${END} flags\r
+    #\r
+    #   @retval     list    A list of TemplateString.Section objects\r
+    #\r
+    def _Parse(self, Template):\r
+        SectionStart = 0\r
+        SearchFrom = 0\r
+        MatchEnd = 0\r
+        PlaceHolderList = []\r
+        TemplateSectionList = []\r
+        while Template:\r
+            MatchObj = gPlaceholderPattern.search(Template, SearchFrom)\r
+            if not MatchObj:\r
+                if MatchEnd <= len(Template):\r
+                    TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList)\r
+                    TemplateSectionList.append(TemplateSection)\r
+                break\r
+\r
+            MatchString = MatchObj.group(1)\r
+            MatchStart = MatchObj.start()\r
+            MatchEnd = MatchObj.end()\r
+\r
+            if MatchString == self._REPEAT_START_FLAG:\r
+                if MatchStart > SectionStart:\r
+                    TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)\r
+                    TemplateSectionList.append(TemplateSection)\r
+                SectionStart = MatchEnd\r
+                PlaceHolderList = []\r
+            elif MatchString == self._REPEAT_END_FLAG:\r
+                TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)\r
+                TemplateSectionList.append(TemplateSection)\r
+                SectionStart = MatchEnd\r
+                PlaceHolderList = []\r
+            else:\r
+                PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart))\r
+            SearchFrom = MatchEnd\r
+        return TemplateSectionList\r
+\r
+    ## Replace the string template with dictionary of placeholders and append it to previous one\r
+    #\r
+    #   @param      AppendString    The string template to append\r
+    #   @param      Dictionary      The placeholder dictionaries\r
+    #\r
+    def Append(self, AppendString, Dictionary=None):\r
+        if Dictionary:\r
+            SectionList = self._Parse(AppendString)\r
+            self.String += "".join([S.Instantiate(Dictionary) for S in SectionList])\r
+        else:\r
+            self.String += AppendString\r
+\r
+    ## Replace the string template with dictionary of placeholders\r
+    #\r
+    #   @param      Dictionary      The placeholder dictionaries\r
+    #\r
+    #   @retval     str             The string replaced with placeholder values\r
+    #\r
+    def Replace(self, Dictionary=None):\r
+        return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList])\r
+\r
+## Progress indicator class\r
+#\r
+#  This class makes use of thread to print progress on console.\r
+#\r
+class Progressor:\r
+    # for avoiding deadloop\r
+    _StopFlag = None\r
+    _ProgressThread = None\r
+    _CheckInterval = 0.25\r
+\r
+    ## Constructor\r
+    #\r
+    #   @param      OpenMessage     The string printed before progress charaters\r
+    #   @param      CloseMessage    The string printed after progress charaters\r
+    #   @param      ProgressChar    The charater used to indicate the progress\r
+    #   @param      Interval        The interval in seconds between two progress charaters\r
+    #\r
+    def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0):\r
+        self.PromptMessage = OpenMessage\r
+        self.CodaMessage = CloseMessage\r
+        self.ProgressChar = ProgressChar\r
+        self.Interval = Interval\r
+        if Progressor._StopFlag == None:\r
+            Progressor._StopFlag = threading.Event()\r
+\r
+    ## Start to print progress charater\r
+    #\r
+    #   @param      OpenMessage     The string printed before progress charaters\r
+    #\r
+    def Start(self, OpenMessage=None):\r
+        if OpenMessage != None:\r
+            self.PromptMessage = OpenMessage\r
+        Progressor._StopFlag.clear()\r
+        if Progressor._ProgressThread == None:\r
+            Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)\r
+            Progressor._ProgressThread.setDaemon(False)\r
+            Progressor._ProgressThread.start()\r
+\r
+    ## Stop printing progress charater\r
+    #\r
+    #   @param      CloseMessage    The string printed after progress charaters\r
+    #\r
+    def Stop(self, CloseMessage=None):\r
+        OriginalCodaMessage = self.CodaMessage\r
+        if CloseMessage != None:\r
+            self.CodaMessage = CloseMessage\r
+        self.Abort()\r
+        self.CodaMessage = OriginalCodaMessage\r
+\r
+    ## Thread entry method\r
+    def _ProgressThreadEntry(self):\r
+        sys.stdout.write(self.PromptMessage + " ")\r
+        sys.stdout.flush()\r
+        TimeUp = 0.0\r
+        while not Progressor._StopFlag.isSet():\r
+            if TimeUp <= 0.0:\r
+                sys.stdout.write(self.ProgressChar)\r
+                sys.stdout.flush()\r
+                TimeUp = self.Interval\r
+            time.sleep(self._CheckInterval)\r
+            TimeUp -= self._CheckInterval\r
+        sys.stdout.write(" " + self.CodaMessage + "\n")\r
+        sys.stdout.flush()\r
+\r
+    ## Abort the progress display\r
+    @staticmethod\r
+    def Abort():\r
+        if Progressor._StopFlag != None:\r
+            Progressor._StopFlag.set()\r
+        if Progressor._ProgressThread != None:\r
+            Progressor._ProgressThread.join()\r
+            Progressor._ProgressThread = None\r
+\r
+## A dict which can access its keys and/or values orderly\r
+#\r
+#  The class implements a new kind of dict which its keys or values can be\r
+#  accessed in the order they are added into the dict. It guarantees the order\r
+#  by making use of an internal list to keep a copy of keys.\r
+#\r
+class sdict(IterableUserDict):\r
+    ## Constructor\r
+    def __init__(self):\r
+        IterableUserDict.__init__(self)\r
+        self._key_list = []\r
+\r
+    ## [] operator\r
+    def __setitem__(self, key, value):\r
+        if key not in self._key_list:\r
+            self._key_list.append(key)\r
+        IterableUserDict.__setitem__(self, key, value)\r
+\r
+    ## del operator\r
+    def __delitem__(self, key):\r
+        self._key_list.remove(key)\r
+        IterableUserDict.__delitem__(self, key)\r
+\r
+    ## used in "for k in dict" loop to ensure the correct order\r
+    def __iter__(self):\r
+        return self.iterkeys()\r
+\r
+    ## len() support\r
+    def __len__(self):\r
+        return len(self._key_list)\r
+\r
+    ## "in" test support\r
+    def __contains__(self, key):\r
+        return key in self._key_list\r
+\r
+    ## indexof support\r
+    def index(self, key):\r
+        return self._key_list.index(key)\r
+\r
+    ## insert support\r
+    def insert(self, key, newkey, newvalue, order):\r
+        index = self._key_list.index(key)\r
+        if order == 'BEFORE':\r
+            self._key_list.insert(index, newkey)\r
+            IterableUserDict.__setitem__(self, newkey, newvalue)\r
+        elif order == 'AFTER':\r
+            self._key_list.insert(index + 1, newkey)\r
+            IterableUserDict.__setitem__(self, newkey, newvalue)\r
+\r
+    ## append support\r
+    def append(self, sdict):\r
+        for key in sdict:\r
+            if key not in self._key_list:\r
+                self._key_list.append(key)\r
+            IterableUserDict.__setitem__(self, key, sdict[key])\r
+\r
+    def has_key(self, key):\r
+        return key in self._key_list\r
+\r
+    ## Empty the dict\r
+    def clear(self):\r
+        self._key_list = []\r
+        IterableUserDict.clear(self)\r
+\r
+    ## Return a copy of keys\r
+    def keys(self):\r
+        keys = []\r
+        for key in self._key_list:\r
+            keys.append(key)\r
+        return keys\r
+\r
+    ## Return a copy of values\r
+    def values(self):\r
+        values = []\r
+        for key in self._key_list:\r
+            values.append(self[key])\r
+        return values\r
+\r
+    ## Return a copy of (key, value) list\r
+    def items(self):\r
+        items = []\r
+        for key in self._key_list:\r
+            items.append((key, self[key]))\r
+        return items\r
+\r
+    ## Iteration support\r
+    def iteritems(self):\r
+        return iter(self.items())\r
+\r
+    ## Keys interation support\r
+    def iterkeys(self):\r
+        return iter(self.keys())\r
+\r
+    ## Values interation support\r
+    def itervalues(self):\r
+        return iter(self.values())\r
+\r
+    ## Return value related to a key, and remove the (key, value) from the dict\r
+    def pop(self, key, *dv):\r
+        value = None\r
+        if key in self._key_list:\r
+            value = self[key]\r
+            self.__delitem__(key)\r
+        elif len(dv) != 0 :\r
+            value = kv[0]\r
+        return value\r
+\r
+    ## Return (key, value) pair, and remove the (key, value) from the dict\r
+    def popitem(self):\r
+        key = self._key_list[-1]\r
+        value = self[key]\r
+        self.__delitem__(key)\r
+        return key, value\r
+\r
+    def update(self, dict=None, **kwargs):\r
+        if dict != None:\r
+            for k, v in dict.items():\r
+                self[k] = v\r
+        if len(kwargs):\r
+            for k, v in kwargs.items():\r
+                self[k] = v\r
+\r
+## Dictionary with restricted keys\r
+#\r
+class rdict(dict):\r
+    ## Constructor\r
+    def __init__(self, KeyList):\r
+        for Key in KeyList:\r
+            dict.__setitem__(self, Key, "")\r
+\r
+    ## []= operator\r
+    def __setitem__(self, key, value):\r
+        if key not in self:\r
+            EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key,\r
+                            ExtraData=", ".join(dict.keys(self)))\r
+        dict.__setitem__(self, key, value)\r
+\r
+    ## =[] operator\r
+    def __getitem__(self, key):\r
+        if key not in self:\r
+            return ""\r
+        return dict.__getitem__(self, key)\r
+\r
+    ## del operator\r
+    def __delitem__(self, key):\r
+        EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del")\r
+\r
+    ## Empty the dict\r
+    def clear(self):\r
+        for Key in self:\r
+            self.__setitem__(Key, "")\r
+\r
+    ## Return value related to a key, and remove the (key, value) from the dict\r
+    def pop(self, key, *dv):\r
+        EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop")\r
+\r
+    ## Return (key, value) pair, and remove the (key, value) from the dict\r
+    def popitem(self):\r
+        EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem")\r
+\r
+## Dictionary using prioritized list as key\r
+#\r
+class tdict:\r
+    _ListType = type([])\r
+    _TupleType = type(())\r
+    _Wildcard = 'COMMON'\r
+    _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']\r
+\r
+    def __init__(self, _Single_=False, _Level_=2):\r
+        self._Level_ = _Level_\r
+        self.data = {}\r
+        self._Single_ = _Single_\r
+\r
+    # =[] operator\r
+    def __getitem__(self, key):\r
+        KeyType = type(key)\r
+        RestKeys = None\r
+        if KeyType == self._ListType or KeyType == self._TupleType:\r
+            FirstKey = key[0]\r
+            if len(key) > 1:\r
+                RestKeys = key[1:]\r
+            elif self._Level_ > 1:\r
+                RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]\r
+        else:\r
+            FirstKey = key\r
+            if self._Level_ > 1:\r
+                RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]\r
+\r
+        if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:\r
+            FirstKey = self._Wildcard\r
+\r
+        if self._Single_:\r
+            return self._GetSingleValue(FirstKey, RestKeys)\r
+        else:\r
+            return self._GetAllValues(FirstKey, RestKeys)\r
+\r
+    def _GetSingleValue(self, FirstKey, RestKeys):\r
+        Value = None\r
+        #print "%s-%s" % (FirstKey, self._Level_) ,\r
+        if self._Level_ > 1:\r
+            if FirstKey == self._Wildcard:\r
+                if FirstKey in self.data:\r
+                    Value = self.data[FirstKey][RestKeys]\r
+                if Value == None:\r
+                    for Key in self.data:\r
+                        Value = self.data[Key][RestKeys]\r
+                        if Value != None: break\r
+            else:\r
+                if FirstKey in self.data:\r
+                    Value = self.data[FirstKey][RestKeys]\r
+                if Value == None and self._Wildcard in self.data:\r
+                    #print "Value=None"\r
+                    Value = self.data[self._Wildcard][RestKeys]\r
+        else:\r
+            if FirstKey == self._Wildcard:\r
+                if FirstKey in self.data:\r
+                    Value = self.data[FirstKey]\r
+                if Value == None:\r
+                    for Key in self.data:\r
+                        Value = self.data[Key]\r
+                        if Value != None: break\r
+            else:\r
+                if FirstKey in self.data:\r
+                    Value = self.data[FirstKey]\r
+                elif self._Wildcard in self.data:\r
+                    Value = self.data[self._Wildcard]\r
+        return Value\r
+\r
+    def _GetAllValues(self, FirstKey, RestKeys):\r
+        Value = []\r
+        if self._Level_ > 1:\r
+            if FirstKey == self._Wildcard:\r
+                for Key in self.data:\r
+                    Value += self.data[Key][RestKeys]\r
+            else:\r
+                if FirstKey in self.data:\r
+                    Value += self.data[FirstKey][RestKeys]\r
+                if self._Wildcard in self.data:\r
+                    Value += self.data[self._Wildcard][RestKeys]\r
+        else:\r
+            if FirstKey == self._Wildcard:\r
+                for Key in self.data:\r
+                    Value.append(self.data[Key])\r
+            else:\r
+                if FirstKey in self.data:\r
+                    Value.append(self.data[FirstKey])\r
+                if self._Wildcard in self.data:\r
+                    Value.append(self.data[self._Wildcard])\r
+        return Value\r
+\r
+    ## []= operator\r
+    def __setitem__(self, key, value):\r
+        KeyType = type(key)\r
+        RestKeys = None\r
+        if KeyType == self._ListType or KeyType == self._TupleType:\r
+            FirstKey = key[0]\r
+            if len(key) > 1:\r
+                RestKeys = key[1:]\r
+            else:\r
+                RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]\r
+        else:\r
+            FirstKey = key\r
+            if self._Level_ > 1:\r
+                RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]\r
+\r
+        if FirstKey in self._ValidWildcardList:\r
+            FirstKey = self._Wildcard\r
+\r
+        if FirstKey not in self.data and self._Level_ > 0:\r
+            self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1)\r
+\r
+        if self._Level_ > 1:\r
+            self.data[FirstKey][RestKeys] = value\r
+        else:\r
+            self.data[FirstKey] = value\r
+\r
+    def SetGreedyMode(self):\r
+        self._Single_ = False\r
+        if self._Level_ > 1:\r
+            for Key in self.data:\r
+                self.data[Key].SetGreedyMode()\r
+\r
+    def SetSingleMode(self):\r
+        self._Single_ = True\r
+        if self._Level_ > 1:\r
+            for Key in self.data:\r
+                self.data[Key].SetSingleMode()\r
+\r
+    def GetKeys(self, KeyIndex=0):\r
+        assert KeyIndex >= 0\r
+        if KeyIndex == 0:\r
+            return set(self.data.keys())\r
+        else:\r
+            keys = set()\r
+            for Key in self.data:\r
+                keys |= self.data[Key].GetKeys(KeyIndex - 1)\r
+            return keys\r
+\r
+## Boolean chain list\r
+#\r
+class Blist(UserList):\r
+    def __init__(self, initlist=None):\r
+        UserList.__init__(self, initlist)\r
+    def __setitem__(self, i, item):\r
+        if item not in [True, False]:\r
+            if item == 0:\r
+                item = False\r
+            else:\r
+                item = True\r
+        self.data[i] = item\r
+    def _GetResult(self):\r
+        Value = True\r
+        for item in self.data:\r
+            Value &= item\r
+        return Value\r
+    Result = property(_GetResult)\r
+\r
+def ParseConsoleLog(Filename):\r
+    Opr = open(os.path.normpath(Filename), 'r')\r
+    Opw = open(os.path.normpath(Filename + '.New'), 'w+')\r
+    for Line in Opr.readlines():\r
+        if Line.find('.efi') > -1:\r
+            Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip()\r
+            Opw.write('%s\n' % Line)\r
+\r
+    Opr.close()\r
+    Opw.close()\r
+\r
+def AnalyzePcdExpression(Setting):\r
+    Setting = Setting.strip()\r
+    # There might be escaped quote in a string: \", \\\" , \', \\\'\r
+    Data = Setting\r
+    # There might be '|' in string and in ( ... | ... ), replace it with '-'\r
+    NewStr = ''\r
+    InSingleQuoteStr = False\r
+    InDoubleQuoteStr = False\r
+    Pair = 0\r
+    for Index, ch in enumerate(Data):\r
+        if ch == '"' and not InSingleQuoteStr:\r
+            if Data[Index - 1] != '\\':\r
+                InDoubleQuoteStr = not InDoubleQuoteStr\r
+        elif ch == "'" and not InDoubleQuoteStr:\r
+            if Data[Index - 1] != '\\':\r
+                InSingleQuoteStr = not InSingleQuoteStr\r
+        elif ch == '(' and not (InSingleQuoteStr or InDoubleQuoteStr):\r
+            Pair += 1\r
+        elif ch == ')' and not (InSingleQuoteStr or InDoubleQuoteStr):\r
+            Pair -= 1\r
+\r
+        if (Pair > 0 or InSingleQuoteStr or InDoubleQuoteStr) and ch == TAB_VALUE_SPLIT:\r
+            NewStr += '-'\r
+        else:\r
+            NewStr += ch\r
+    FieldList = []\r
+    StartPos = 0\r
+    while True:\r
+        Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos)\r
+        if Pos < 0:\r
+            FieldList.append(Setting[StartPos:].strip())\r
+            break\r
+        FieldList.append(Setting[StartPos:Pos].strip())\r
+        StartPos = Pos + 1\r
+\r
+    return FieldList\r
+\r
+def ParseDevPathValue (Value):\r
+    DevPathList = [ "Path","HardwarePath","Pci","PcCard","MemoryMapped","VenHw","Ctrl","BMC","AcpiPath","Acpi","PciRoot",\r
+                    "PcieRoot","Floppy","Keyboard","Serial","ParallelPort","AcpiEx","AcpiExp","AcpiAdr","Msg","Ata","Scsi",\r
+                    "Fibre","FibreEx","I1394","USB","I2O","Infiniband","VenMsg","VenPcAnsi","VenVt100","VenVt100Plus",\r
+                    "VenUtf8","UartFlowCtrl","SAS","SasEx","NVMe","UFS","SD","eMMC","DebugPort","MAC","IPv4","IPv6","Uart",\r
+                    "UsbClass","UsbAudio","UsbCDCControl","UsbHID","UsbImage","UsbPrinter","UsbMassStorage","UsbHub",\r
+                    "UsbCDCData","UsbSmartCard","UsbVideo","UsbDiagnostic","UsbWireless","UsbDeviceFirmwareUpdate",\r
+                    "UsbIrdaBridge","UsbTestAndMeasurement","UsbWwid","Unit","iSCSI","Vlan","Uri","Bluetooth","Wi-Fi",\r
+                    "MediaPath","HD","CDROM","VenMedia","Media","Fv","FvFile","Offset","RamDisk","VirtualDisk","VirtualCD",\r
+                    "PersistentVirtualDisk","PersistentVirtualCD","BbsPath","BBS","Sata" ]\r
+    if '\\' in Value:\r
+        Value.replace('\\', '/').replace(' ', '')\r
+    for Item in Value.split('/'):\r
+        Key = Item.strip().split('(')[0]\r
+        if Key not in DevPathList:\r
+            pass\r
+\r
+    Cmd = 'DevicePath ' + '"' + Value + '"'\r
+    try:\r
+        p = subprocess.Popen(Cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)\r
+        out, err = p.communicate()\r
+    except Exception, X:\r
+        raise BadExpression("DevicePath: %s" % (str(X)) )\r
+    finally:\r
+        subprocess._cleanup()\r
+        p.stdout.close()\r
+        p.stderr.close()\r
+    if err:\r
+        raise BadExpression("DevicePath: %s" % str(err))\r
+    Size = len(out.split())\r
+    out = ','.join(out.split())\r
+    return '{' + out + '}', Size\r
+\r
+def ParseFieldValue (Value):\r
+    if type(Value) == type(0):\r
+        return Value, (Value.bit_length() + 7) / 8\r
+    if type(Value) <> type(''):\r
+        raise BadExpression('Type %s is %s' %(Value, type(Value)))\r
+    Value = Value.strip()\r
+    if Value.startswith('UINT8') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 1:\r
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))\r
+        return Value, 1\r
+    if Value.startswith('UINT16') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 2:\r
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))\r
+        return Value, 2\r
+    if Value.startswith('UINT32') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 4:\r
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))\r
+        return Value, 4\r
+    if Value.startswith('UINT64') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 8:\r
+            raise BadExpression('Value (%s) Size larger than %d' % (Value, Size))\r
+        return Value, 8\r
+    if Value.startswith('GUID') and Value.endswith(')'):\r
+        Value = Value.split('(', 1)[1][:-1].strip()\r
+        if Value[0] == '{' and Value[-1] == '}':\r
+            TmpValue = GuidStructureStringToGuidString(Value)\r
+            if len(TmpValue) == 0:\r
+                raise BadExpression("Invalid GUID value string %s" % Value)\r
+            Value = TmpValue\r
+        if Value[0] == '"' and Value[-1] == '"':\r
+            Value = Value[1:-1]\r
+        try:\r
+            Value = "'" + uuid.UUID(Value).get_bytes_le() + "'"\r
+        except ValueError, Message:\r
+            raise BadExpression('%s' % Message)\r
+        Value, Size = ParseFieldValue(Value)\r
+        return Value, 16\r
+    if Value.startswith('L"') and Value.endswith('"'):\r
+        # Unicode String\r
+        # translate escape character\r
+        Value = Value[1:]\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 16) | ord(Char)\r
+        return Value, (len(List) + 1) * 2\r
+    if Value.startswith('"') and Value.endswith('"'):\r
+        # ASCII String\r
+        # translate escape character\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 8) | ord(Char)\r
+        return Value, len(List) + 1\r
+    if Value.startswith("L'") and Value.endswith("'"):\r
+        # Unicode Character Constant\r
+        # translate escape character\r
+        Value = Value[1:]\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\r
+        if len(List) == 0:\r
+            raise BadExpression('Length %s is %s' % (Value, len(List)))\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 16) | ord(Char)\r
+        return Value, len(List) * 2\r
+    if Value.startswith("'") and Value.endswith("'"):\r
+        # Character constant\r
+        # translate escape character\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\r
+        if len(List) == 0:\r
+            raise BadExpression('Length %s is %s' % (Value, len(List)))\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 8) | ord(Char)\r
+        return Value, len(List)\r
+    if Value.startswith('{') and Value.endswith('}'):\r
+        # Byte array\r
+        Value = Value[1:-1]\r
+        List = [Item.strip() for Item in Value.split(',')]\r
+        List.reverse()\r
+        Value = 0\r
+        RetSize = 0\r
+        for Item in List:\r
+            ItemValue, Size = ParseFieldValue(Item)\r
+            RetSize += Size\r
+            for I in range(Size):\r
+                Value = (Value << 8) | ((ItemValue >> 8 * I) & 0xff)\r
+        return Value, RetSize\r
+    if Value.startswith('DEVICE_PATH(') and Value.endswith(')'):\r
+        Value = Value.replace("DEVICE_PATH(", '').rstrip(')')\r
+        Value = Value.strip().strip('"')\r
+        return ParseDevPathValue(Value)\r
+    if Value.lower().startswith('0x'):\r
+        Value = int(Value, 16)\r
+        if Value == 0:\r
+            return 0, 1\r
+        return Value, (Value.bit_length() + 7) / 8\r
+    if Value[0].isdigit():\r
+        Value = int(Value, 10)\r
+        if Value == 0:\r
+            return 0, 1\r
+        return Value, (Value.bit_length() + 7) / 8\r
+    if Value.lower() == 'true':\r
+        return 1, 1\r
+    if Value.lower() == 'false':\r
+        return 0, 1\r
+    return Value, 1\r
+\r
+## AnalyzeDscPcd\r
+#\r
+#  Analyze DSC PCD value, since there is no data type info in DSC\r
+#  This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database\r
+#  1. Feature flag: TokenSpace.PcdCName|PcdValue\r
+#  2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]\r
+#  3. Dynamic default:\r
+#     TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]\r
+#     TokenSpace.PcdCName|PcdValue\r
+#  4. Dynamic VPD:\r
+#     TokenSpace.PcdCName|VpdOffset[|VpdValue]\r
+#     TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]\r
+#  5. Dynamic HII:\r
+#     TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]\r
+#  PCD value needs to be located in such kind of string, and the PCD value might be an expression in which\r
+#    there might have "|" operator, also in string value.\r
+#\r
+#  @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped\r
+#  @param PcdType: PCD type: feature, fixed, dynamic default VPD HII\r
+#  @param DataType: The datum type of PCD: VOID*, UNIT, BOOL\r
+#  @retval:\r
+#    ValueList: A List contain fields described above\r
+#    IsValid:   True if conforming EBNF, otherwise False\r
+#    Index:     The index where PcdValue is in ValueList\r
+#\r
+def AnalyzeDscPcd(Setting, PcdType, DataType=''):\r
+    FieldList = AnalyzePcdExpression(Setting)\r
+\r
+    IsValid = True\r
+    if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG):\r
+        Value = FieldList[0]\r
+        Size = ''\r
+        if len(FieldList) > 1:\r
+            if FieldList[1].upper().startswith("0X") or FieldList[1].isdigit():\r
+                Size = FieldList[1]\r
+            else:\r
+                DataType = FieldList[1]\r
+\r
+        if len(FieldList) > 2:\r
+            Size = FieldList[2]\r
+        if DataType == "":\r
+            IsValid = (len(FieldList) <= 1)\r
+        else:\r
+            IsValid = (len(FieldList) <= 3)\r
+#         Value, Size = ParseFieldValue(Value)\r
+        if Size:\r
+            try:\r
+                int(Size,16) if Size.upper().startswith("0X") else int(Size)\r
+            except:\r
+                IsValid = False\r
+                Size = -1\r
+        return [str(Value), '', str(Size)], IsValid, 0\r
+    elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):\r
+        Value = FieldList[0]\r
+        Size = Type = ''\r
+        if len(FieldList) > 1:\r
+            Type = FieldList[1]\r
+        else:\r
+            Type = DataType\r
+        if len(FieldList) > 2:\r
+            Size = FieldList[2]\r
+        else:\r
+            if Type == 'VOID*':\r
+                if Value.startswith("L"):\r
+                    Size = str((len(Value)- 3 + 1) * 2)\r
+                elif Value.startswith("{"):\r
+                    Size = str(len(Value.split(",")))\r
+                else:\r
+                    Size = str(len(Value) -2 + 1 )\r
+        if DataType == "":\r
+            IsValid = (len(FieldList) <= 1)\r
+        else:\r
+            IsValid = (len(FieldList) <= 3)\r
+\r
+        if Size:\r
+            try:\r
+                int(Size,16) if Size.upper().startswith("0X") else int(Size)\r
+            except:\r
+                IsValid = False\r
+                Size = -1\r
+        return [Value, Type, str(Size)], IsValid, 0\r
+    elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):\r
+        VpdOffset = FieldList[0]\r
+        Value = Size = ''\r
+        if not DataType == 'VOID*':\r
+            if len(FieldList) > 1:\r
+                Value = FieldList[1]\r
+        else:\r
+            if len(FieldList) > 1:\r
+                Size = FieldList[1]\r
+            if len(FieldList) > 2:\r
+                Value = FieldList[2]\r
+        if DataType == "":\r
+            IsValid = (len(FieldList) <= 1)\r
+        else:\r
+            IsValid = (len(FieldList) <= 3)\r
+        if Size:\r
+            try:\r
+                int(Size,16) if Size.upper().startswith("0X") else int(Size)\r
+            except:\r
+                IsValid = False\r
+                Size = -1\r
+        return [VpdOffset, str(Size), Value], IsValid, 2\r
+    elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):\r
+        HiiString = FieldList[0]\r
+        Guid = Offset = Value = Attribute = ''\r
+        if len(FieldList) > 1:\r
+            Guid = FieldList[1]\r
+        if len(FieldList) > 2:\r
+            Offset = FieldList[2]\r
+        if len(FieldList) > 3:\r
+            Value = FieldList[3]\r
+        if len(FieldList) > 4:\r
+            Attribute = FieldList[4]\r
+        IsValid = (3 <= len(FieldList) <= 5)\r
+        return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3\r
+    return [], False, 0\r
+\r
+## AnalyzePcdData\r
+#\r
+#  Analyze the pcd Value, Datum type and TokenNumber.\r
+#  Used to avoid split issue while the value string contain "|" character\r
+#\r
+#  @param[in] Setting:  A String contain value/datum type/token number information;\r
+#  \r
+#  @retval   ValueList: A List contain value, datum type and toke number. \r
+#\r
+def AnalyzePcdData(Setting):\r
+    ValueList = ['', '', '']\r
+\r
+    ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
+    PtrValue = ValueRe.findall(Setting)\r
+    \r
+    ValueUpdateFlag = False\r
+    \r
+    if len(PtrValue) >= 1:\r
+        Setting = re.sub(ValueRe, '', Setting)\r
+        ValueUpdateFlag = True\r
+\r
+    TokenList = Setting.split(TAB_VALUE_SPLIT)\r
+    ValueList[0:len(TokenList)] = TokenList\r
+    \r
+    if ValueUpdateFlag:\r
+        ValueList[0] = PtrValue[0]\r
+        \r
+    return ValueList   \r
\r
+## AnalyzeHiiPcdData\r
+#\r
+#  Analyze the pcd Value, variable name, variable Guid and variable offset.\r
+#  Used to avoid split issue while the value string contain "|" character\r
+#\r
+#  @param[in] Setting:  A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;\r
+#  \r
+#  @retval   ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue. \r
+#\r
+def AnalyzeHiiPcdData(Setting):\r
+    ValueList = ['', '', '', '']\r
+\r
+    TokenList = GetSplitValueList(Setting)\r
+    ValueList[0:len(TokenList)] = TokenList\r
+\r
+    return ValueList\r
+\r
+## AnalyzeVpdPcdData\r
+#\r
+#  Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.\r
+#  Used to avoid split issue while the value string contain "|" character\r
+#\r
+#  @param[in] Setting:  A String contain VpdOffset/MaxDatumSize/InitialValue information;\r
+#  \r
+#  @retval   ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue. \r
+#\r
+def AnalyzeVpdPcdData(Setting):\r
+    ValueList = ['', '', '']\r
+\r
+    ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$')\r
+    PtrValue = ValueRe.findall(Setting)\r
+    \r
+    ValueUpdateFlag = False\r
+    \r
+    if len(PtrValue) >= 1:\r
+        Setting = re.sub(ValueRe, '', Setting)\r
+        ValueUpdateFlag = True\r
+\r
+    TokenList = Setting.split(TAB_VALUE_SPLIT)\r
+    ValueList[0:len(TokenList)] = TokenList\r
+    \r
+    if ValueUpdateFlag:\r
+        ValueList[2] = PtrValue[0]\r
+        \r
+    return ValueList     \r
+\r
+## check format of PCD value against its the datum type\r
+#\r
+# For PCD value setting\r
+#\r
+def CheckPcdDatum(Type, Value):\r
+    if Type == "VOID*":\r
+        ValueRe = re.compile(r'\s*L?\".*\"\s*$')\r
+        if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))\r
+                or (Value.startswith('{') and Value.endswith('}')) or (Value.startswith("L'") or Value.startswith("'") and Value.endswith("'"))\r
+               ):\r
+            return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\\r
+                          ", \"...\" or \'...\' for string, L\"...\" or L\'...\' for unicode string" % (Value, Type)\r
+        elif ValueRe.match(Value):\r
+            # Check the chars in UnicodeString or CString is printable\r
+            if Value.startswith("L"):\r
+                Value = Value[2:-1]\r
+            else:\r
+                Value = Value[1:-1]\r
+            Printset = set(string.printable)\r
+            Printset.remove(TAB_PRINTCHAR_VT)\r
+            Printset.add(TAB_PRINTCHAR_BS)\r
+            Printset.add(TAB_PRINTCHAR_NUL)\r
+            if not set(Value).issubset(Printset):\r
+                PrintList = list(Printset)\r
+                PrintList.sort()\r
+                return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type, PrintList)\r
+    elif Type == 'BOOLEAN':\r
+        if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:\r
+            return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\\r
+                          ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type)\r
+    elif Type in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64]:\r
+        try:\r
+            Value = long(Value, 0)\r
+        except:\r
+            return False, "Invalid value [%s] of type [%s];"\\r
+                          " must be a hexadecimal, decimal or octal in C language format." % (Value, Type)\r
+    else:\r
+        return True, "StructurePcd"\r
+\r
+    return True, ""\r
+\r
+## Split command line option string to list\r
+#\r
+# subprocess.Popen needs the args to be a sequence. Otherwise there's problem\r
+# in non-windows platform to launch command\r
+#\r
+def SplitOption(OptionString):\r
+    OptionList = []\r
+    LastChar = " "\r
+    OptionStart = 0\r
+    QuotationMark = ""\r
+    for Index in range(0, len(OptionString)):\r
+        CurrentChar = OptionString[Index]\r
+        if CurrentChar in ['"', "'"]:\r
+            if QuotationMark == CurrentChar:\r
+                QuotationMark = ""\r
+            elif QuotationMark == "":\r
+                QuotationMark = CurrentChar\r
+            continue\r
+        elif QuotationMark:\r
+            continue\r
+\r
+        if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:\r
+            if Index > OptionStart:\r
+                OptionList.append(OptionString[OptionStart:Index - 1])\r
+            OptionStart = Index\r
+        LastChar = CurrentChar\r
+    OptionList.append(OptionString[OptionStart:])\r
+    return OptionList\r
+\r
+def CommonPath(PathList):\r
+    P1 = min(PathList).split(os.path.sep)\r
+    P2 = max(PathList).split(os.path.sep)\r
+    for Index in xrange(min(len(P1), len(P2))):\r
+        if P1[Index] != P2[Index]:\r
+            return os.path.sep.join(P1[:Index])\r
+    return os.path.sep.join(P1)\r
+\r
+#\r
+# Convert string to C format array\r
+#\r
+def ConvertStringToByteArray(Value):\r
+    Value = Value.strip()\r
+    if not Value:\r
+        return None\r
+    if Value[0] == '{':\r
+        if not Value.endswith('}'):\r
+            return None\r
+        Value = Value.replace(' ', '').replace('{', '').replace('}', '')\r
+        ValFields = Value.split(',')\r
+        try:\r
+            for Index in range(len(ValFields)):\r
+                ValFields[Index] = str(int(ValFields[Index], 0))\r
+        except ValueError:\r
+            return None\r
+        Value = '{' + ','.join(ValFields) + '}'\r
+        return Value\r
+\r
+    Unicode = False\r
+    if Value.startswith('L"'):\r
+        if not Value.endswith('"'):\r
+            return None\r
+        Value = Value[1:]\r
+        Unicode = True\r
+    elif not Value.startswith('"') or not Value.endswith('"'):\r
+        return None\r
+\r
+    Value = eval(Value)         # translate escape character\r
+    NewValue = '{'\r
+    for Index in range(0,len(Value)):\r
+        if Unicode:\r
+            NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','\r
+        else:\r
+            NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','\r
+    Value = NewValue + '0}'\r
+    return Value\r
+\r
+class PathClass(object):\r
+    def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,\r
+                 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''):\r
+        self.Arch = Arch\r
+        self.File = str(File)\r
+        if os.path.isabs(self.File):\r
+            self.Root = ''\r
+            self.AlterRoot = ''\r
+        else:\r
+            self.Root = str(Root)\r
+            self.AlterRoot = str(AlterRoot)\r
+\r
+        # Remove any '.' and '..' in path\r
+        if self.Root:\r
+            self.Root = mws.getWs(self.Root, self.File)\r
+            self.Path = os.path.normpath(os.path.join(self.Root, self.File))\r
+            self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))\r
+            # eliminate the side-effect of 'C:'\r
+            if self.Root[-1] == ':':\r
+                self.Root += os.path.sep\r
+            # file path should not start with path separator\r
+            if self.Root[-1] == os.path.sep:\r
+                self.File = self.Path[len(self.Root):]\r
+            else:\r
+                self.File = self.Path[len(self.Root) + 1:]\r
+        else:\r
+            self.Path = os.path.normpath(self.File)\r
+\r
+        self.SubDir, self.Name = os.path.split(self.File)\r
+        self.BaseName, self.Ext = os.path.splitext(self.Name)\r
+\r
+        if self.Root:\r
+            if self.SubDir:\r
+                self.Dir = os.path.join(self.Root, self.SubDir)\r
+            else:\r
+                self.Dir = self.Root\r
+        else:\r
+            self.Dir = self.SubDir\r
+\r
+        if IsBinary:\r
+            self.Type = Type\r
+        else:\r
+            self.Type = self.Ext.lower()\r
+\r
+        self.IsBinary = IsBinary\r
+        self.Target = Target\r
+        self.TagName = TagName\r
+        self.ToolCode = ToolCode\r
+        self.ToolChainFamily = ToolChainFamily\r
+\r
+        self._Key = None\r
+\r
+    ## Convert the object of this class to a string\r
+    #\r
+    #  Convert member Path of the class to a string\r
+    #\r
+    #  @retval string Formatted String\r
+    #\r
+    def __str__(self):\r
+        return self.Path\r
+\r
+    ## Override __eq__ function\r
+    #\r
+    # Check whether PathClass are the same\r
+    #\r
+    # @retval False The two PathClass are different\r
+    # @retval True  The two PathClass are the same\r
+    #\r
+    def __eq__(self, Other):\r
+        if type(Other) == type(self):\r
+            return self.Path == Other.Path\r
+        else:\r
+            return self.Path == str(Other)\r
+\r
+    ## Override __cmp__ function\r
+    #\r
+    # Customize the comparsion operation of two PathClass\r
+    #\r
+    # @retval 0     The two PathClass are different\r
+    # @retval -1    The first PathClass is less than the second PathClass\r
+    # @retval 1     The first PathClass is Bigger than the second PathClass\r
+    def __cmp__(self, Other):\r
+        if type(Other) == type(self):\r
+            OtherKey = Other.Path\r
+        else:\r
+            OtherKey = str(Other)\r
+            \r
+        SelfKey = self.Path\r
+        if SelfKey == OtherKey:\r
+            return 0\r
+        elif SelfKey > OtherKey:\r
+            return 1\r
+        else:\r
+            return -1\r
+\r
+    ## Override __hash__ function\r
+    #\r
+    # Use Path as key in hash table\r
+    #\r
+    # @retval string Key for hash table\r
+    #\r
+    def __hash__(self):\r
+        return hash(self.Path)\r
+\r
+    def _GetFileKey(self):\r
+        if self._Key == None:\r
+            self._Key = self.Path.upper()   # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target\r
+        return self._Key\r
+\r
+    def _GetTimeStamp(self):\r
+        return os.stat(self.Path)[8]\r
+\r
+    def Validate(self, Type='', CaseSensitive=True):\r
+        if GlobalData.gCaseInsensitive:\r
+            CaseSensitive = False\r
+        if Type and Type.lower() != self.Type:\r
+            return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type)\r
+\r
+        RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)\r
+        if not RealRoot and not RealFile:\r
+            RealFile = self.File\r
+            if self.AlterRoot:\r
+                RealFile = os.path.join(self.AlterRoot, self.File)\r
+            elif self.Root:\r
+                RealFile = os.path.join(self.Root, self.File)\r
+            if len (mws.getPkgPath()) == 0:\r
+                return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)\r
+            else:\r
+                return FILE_NOT_FOUND, "%s is not found in packages path:\n\t%s" % (self.File, '\n\t'.join(mws.getPkgPath()))\r
+\r
+        ErrorCode = 0\r
+        ErrorInfo = ''\r
+        if RealRoot != self.Root or RealFile != self.File:\r
+            if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)):\r
+                ErrorCode = FILE_CASE_MISMATCH\r
+                ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]"\r
+\r
+            self.SubDir, self.Name = os.path.split(RealFile)\r
+            self.BaseName, self.Ext = os.path.splitext(self.Name)\r
+            if self.SubDir:\r
+                self.Dir = os.path.join(RealRoot, self.SubDir)\r
+            else:\r
+                self.Dir = RealRoot\r
+            self.File = RealFile\r
+            self.Root = RealRoot\r
+            self.Path = os.path.join(RealRoot, RealFile)\r
+        return ErrorCode, ErrorInfo\r
+\r
+    Key = property(_GetFileKey)\r
+    TimeStamp = property(_GetTimeStamp)\r
+\r
+## Parse PE image to get the required PE informaion.\r
+#\r
+class PeImageClass():\r
+    ## Constructor\r
+    #\r
+    #   @param  File FilePath of PeImage\r
+    #\r
+    def __init__(self, PeFile):\r
+        self.FileName   = PeFile\r
+        self.IsValid    = False\r
+        self.Size       = 0\r
+        self.EntryPoint = 0\r
+        self.SectionAlignment  = 0\r
+        self.SectionHeaderList = []\r
+        self.ErrorInfo = ''\r
+        try:\r
+            PeObject = open(PeFile, 'rb')\r
+        except:\r
+            self.ErrorInfo = self.FileName + ' can not be found\n'\r
+            return\r
+        # Read DOS header\r
+        ByteArray = array.array('B')\r
+        ByteArray.fromfile(PeObject, 0x3E)\r
+        ByteList = ByteArray.tolist()\r
+        # DOS signature should be 'MZ'\r
+        if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ':\r
+            self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ'\r
+            return\r
+\r
+        # Read 4 byte PE Signature\r
+        PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E])\r
+        PeObject.seek(PeOffset)\r
+        ByteArray = array.array('B')\r
+        ByteArray.fromfile(PeObject, 4)\r
+        # PE signature should be 'PE\0\0'\r
+        if ByteArray.tostring() != 'PE\0\0':\r
+            self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'\r
+            return\r
+\r
+        # Read PE file header\r
+        ByteArray = array.array('B')\r
+        ByteArray.fromfile(PeObject, 0x14)\r
+        ByteList = ByteArray.tolist()\r
+        SecNumber = self._ByteListToInt(ByteList[0x2:0x4])\r
+        if SecNumber == 0:\r
+            self.ErrorInfo = self.FileName + ' has no section header'\r
+            return\r
+\r
+        # Read PE optional header\r
+        OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12])\r
+        ByteArray = array.array('B')\r
+        ByteArray.fromfile(PeObject, OptionalHeaderSize)\r
+        ByteList = ByteArray.tolist()\r
+        self.EntryPoint       = self._ByteListToInt(ByteList[0x10:0x14])\r
+        self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24])\r
+        self.Size             = self._ByteListToInt(ByteList[0x38:0x3C])\r
+\r
+        # Read each Section Header\r
+        for Index in range(SecNumber):\r
+            ByteArray = array.array('B')\r
+            ByteArray.fromfile(PeObject, 0x28)\r
+            ByteList = ByteArray.tolist()\r
+            SecName  = self._ByteListToStr(ByteList[0:8])\r
+            SecVirtualSize = self._ByteListToInt(ByteList[8:12])\r
+            SecRawAddress  = self._ByteListToInt(ByteList[20:24])\r
+            SecVirtualAddress = self._ByteListToInt(ByteList[12:16])\r
+            self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize))\r
+        self.IsValid = True\r
+        PeObject.close()\r
+\r
+    def _ByteListToStr(self, ByteList):\r
+        String = ''\r
+        for index in range(len(ByteList)):\r
+            if ByteList[index] == 0: \r
+                break\r
+            String += chr(ByteList[index])\r
+        return String\r
+\r
+    def _ByteListToInt(self, ByteList):\r
+        Value = 0\r
+        for index in range(len(ByteList) - 1, -1, -1):\r
+            Value = (Value << 8) | int(ByteList[index])\r
+        return Value\r
+\r
+class DefaultStore():\r
+    def __init__(self,DefaultStores ):\r
+\r
+        self.DefaultStores = DefaultStores\r
+    def DefaultStoreID(self,DefaultStoreName):\r
+        for key,value in self.DefaultStores.items():\r
+            if value == DefaultStoreName:\r
+                return key\r
+        return None\r
+    def GetDefaultDefault(self):\r
+        if not self.DefaultStores or "0" in self.DefaultStores:\r
+            return "0",TAB_DEFAULT_STORES_DEFAULT\r
+        else:\r
+            minvalue = min([int(value_str) for value_str in self.DefaultStores.keys()])\r
+            return (str(minvalue), self.DefaultStores[str(minvalue)])\r
+    def GetMin(self,DefaultSIdList):\r
+        if not DefaultSIdList:\r
+            return "STANDARD"\r
+        storeidset = {storeid for storeid, storename in self.DefaultStores.values() if storename in DefaultSIdList}\r
+        if not storeidset:\r
+            return ""\r
+        minid = min(storeidset )\r
+        for sid,name in self.DefaultStores.values():\r
+            if sid == minid:\r
+                return name\r
+class SkuClass():\r
+    \r
+    DEFAULT = 0\r
+    SINGLE = 1\r
+    MULTIPLE =2\r
+    \r
+    def __init__(self,SkuIdentifier='', SkuIds=None):\r
+        if SkuIds is None:\r
+            SkuIds = {}\r
+\r
+        for SkuName in SkuIds:\r
+            SkuId = SkuIds[SkuName][0]\r
+            skuid_num = int(SkuId,16) if SkuId.upper().startswith("0X") else int(SkuId)\r
+            if skuid_num > 0xFFFFFFFFFFFFFFFF:\r
+                EdkLogger.error("build", PARAMETER_INVALID,\r
+                            ExtraData = "SKU-ID [%s] value %s exceeds the max value of UINT64"\r
+                                      % (SkuName, SkuId))\r
+        \r
+        self.AvailableSkuIds = sdict()\r
+        self.SkuIdSet = []\r
+        self.SkuIdNumberSet = []\r
+        self.SkuData = SkuIds\r
+        self.__SkuInherit = {}\r
+        self.__SkuIdentifier = SkuIdentifier\r
+        if SkuIdentifier == '' or SkuIdentifier is None:\r
+            self.SkuIdSet = ['DEFAULT']\r
+            self.SkuIdNumberSet = ['0U']\r
+        elif SkuIdentifier == 'ALL':\r
+            self.SkuIdSet = SkuIds.keys()\r
+            self.SkuIdNumberSet = [num[0].strip() + 'U' for num in SkuIds.values()]\r
+        else:\r
+            r = SkuIdentifier.split('|') \r
+            self.SkuIdSet=[(r[k].strip()).upper() for k in range(len(r))]\r
+            k = None\r
+            try: \r
+                self.SkuIdNumberSet = [SkuIds[k][0].strip() + 'U' for k in self.SkuIdSet]\r
+            except Exception:\r
+                EdkLogger.error("build", PARAMETER_INVALID,\r
+                            ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"\r
+                                      % (k, " | ".join(SkuIds.keys())))\r
+        for each in self.SkuIdSet:\r
+            if each in SkuIds:\r
+                self.AvailableSkuIds[each] = SkuIds[each][0]\r
+            else:\r
+                EdkLogger.error("build", PARAMETER_INVALID,\r
+                            ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"\r
+                                      % (each, " | ".join(SkuIds.keys())))\r
+        if self.SkuUsageType != self.SINGLE:\r
+            self.AvailableSkuIds.update({'DEFAULT':0, 'COMMON':0})\r
+        if self.SkuIdSet:\r
+            GlobalData.gSkuids = (self.SkuIdSet)\r
+            if 'COMMON' in GlobalData.gSkuids:\r
+                GlobalData.gSkuids.remove('COMMON')\r
+            if self.SkuUsageType == self.SINGLE:\r
+                if len(GlobalData.gSkuids) != 1:\r
+                    if 'DEFAULT' in GlobalData.gSkuids:\r
+                        GlobalData.gSkuids.remove('DEFAULT')\r
+            if GlobalData.gSkuids:\r
+                GlobalData.gSkuids.sort()\r
+\r
+    def GetNextSkuId(self, skuname):\r
+        if not self.__SkuInherit:\r
+            self.__SkuInherit = {}\r
+            for item in self.SkuData.values():\r
+                self.__SkuInherit[item[1]]=item[2] if item[2] else "DEFAULT"\r
+        return self.__SkuInherit.get(skuname,"DEFAULT")\r
+\r
+    def GetSkuChain(self,sku):\r
+        if sku == "DEFAULT":\r
+            return ["DEFAULT"]\r
+        skulist = [sku]\r
+        nextsku = sku\r
+        while 1:\r
+            nextsku = self.GetNextSkuId(nextsku)\r
+            skulist.append(nextsku)\r
+            if nextsku == "DEFAULT":\r
+                break\r
+        skulist.reverse()\r
+        return skulist\r
+    def SkuOverrideOrder(self):\r
+        skuorderset = []\r
+        for skuname in self.SkuIdSet:\r
+            skuorderset.append(self.GetSkuChain(skuname))\r
+        \r
+        skuorder = []\r
+        for index in range(max([len(item) for item in skuorderset])):\r
+            for subset in skuorderset:\r
+                if index > len(subset)-1:\r
+                    continue\r
+                if subset[index] in skuorder:\r
+                    continue\r
+                skuorder.append(subset[index])\r
+\r
+        return skuorder\r
+\r
+    def __SkuUsageType(self): \r
+        \r
+        if self.__SkuIdentifier.upper() == "ALL":\r
+            return SkuClass.MULTIPLE\r
+\r
+        if len(self.SkuIdSet) == 1:\r
+            if self.SkuIdSet[0] == 'DEFAULT':\r
+                return SkuClass.DEFAULT\r
+            else:\r
+                return SkuClass.SINGLE\r
+        elif len(self.SkuIdSet) == 2:\r
+            if 'DEFAULT' in self.SkuIdSet:\r
+                return SkuClass.SINGLE\r
+            else:\r
+                return SkuClass.MULTIPLE\r
+        else:\r
+            return SkuClass.MULTIPLE\r
+    def DumpSkuIdArrary(self):\r
+\r
+        ArrayStrList = []\r
+        if self.SkuUsageType == SkuClass.SINGLE:\r
+            ArrayStr = "{0x0}"\r
+        else:\r
+            for skuname in self.AvailableSkuIds:\r
+                if skuname == "COMMON":\r
+                    continue\r
+                while skuname != "DEFAULT":\r
+                    ArrayStrList.append(hex(int(self.AvailableSkuIds[skuname])))\r
+                    skuname = self.GetNextSkuId(skuname)\r
+                ArrayStrList.append("0x0")\r
+            ArrayStr = "{" + ",".join(ArrayStrList) +  "}"\r
+        return ArrayStr\r
+    def __GetAvailableSkuIds(self):\r
+        return self.AvailableSkuIds\r
+    \r
+    def __GetSystemSkuID(self):\r
+        if self.__SkuUsageType() == SkuClass.SINGLE:\r
+            if len(self.SkuIdSet) == 1:\r
+                return self.SkuIdSet[0]\r
+            else:\r
+                return self.SkuIdSet[0] if self.SkuIdSet[0] != 'DEFAULT' else self.SkuIdSet[1]\r
+        else:\r
+            return 'DEFAULT'\r
+    def __GetAvailableSkuIdNumber(self):\r
+        return self.SkuIdNumberSet\r
+    SystemSkuId = property(__GetSystemSkuID)\r
+    AvailableSkuIdSet = property(__GetAvailableSkuIds)\r
+    SkuUsageType = property(__SkuUsageType)\r
+    AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber)\r
+\r
+#\r
+# Pack a registry format GUID\r
+#\r
+def PackRegistryFormatGuid(Guid):\r
+    Guid = Guid.split('-')\r
+    return pack('=LHHBBBBBBBB',\r
+                int(Guid[0], 16),\r
+                int(Guid[1], 16),\r
+                int(Guid[2], 16),\r
+                int(Guid[3][-4:-2], 16),\r
+                int(Guid[3][-2:], 16),\r
+                int(Guid[4][-12:-10], 16),\r
+                int(Guid[4][-10:-8], 16),\r
+                int(Guid[4][-8:-6], 16),\r
+                int(Guid[4][-6:-4], 16),\r
+                int(Guid[4][-4:-2], 16),\r
+                int(Guid[4][-2:], 16)\r
+                )\r
+\r
+def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Value):\r
+    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64,'BOOLEAN']:\r
+        if Value.startswith('L') or Value.startswith('"'):\r
+            if not Value[1]:\r
+                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"{...}"')\r
+            Value = Value\r
+        elif Value.startswith('H'):\r
+            if not Value[1]:\r
+                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"{...}"')\r
+            Value = Value[1:]\r
+        else:\r
+            if not Value[0]:\r
+                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"{...}"')\r
+            Value = '"' + Value + '"'\r
+\r
+    IsValid, Cause = CheckPcdDatum(PcdDatumType, Value)\r
+    if not IsValid:\r
+        EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))\r
+    if PcdDatumType == 'BOOLEAN':\r
+        Value = Value.upper()\r
+        if Value == 'TRUE' or Value == '1':\r
+            Value = '1'\r
+        elif Value == 'FALSE' or Value == '0':\r
+            Value = '0'\r
+    return  Value\r
+##  Get the integer value from string like "14U" or integer like 2\r
+#\r
+#   @param      Input   The object that may be either a integer value or a string\r
+#\r
+#   @retval     Value    The integer value that the input represents\r
+#\r
+def GetIntegerValue(Input):\r
+    if type(Input) in (int, long):\r
+        return Input\r
+    String = Input\r
+    if String.endswith("U"):\r
+        String = String[:-1]\r
+    if String.endswith("ULL"):\r
+        String = String[:-3]\r
+    if String.endswith("LL"):\r
+        String = String[:-2]\r
+\r
+    if String.startswith("0x") or String.startswith("0X"):\r
+        return int(String, 16)\r
+    elif String == '':\r
+        return 0\r
+    else:\r
+        return int(String)\r
+\r
+##\r
+#\r
+# This acts like the main() function for the script, unless it is 'import'ed into another\r
+# script.\r
+#\r
+if __name__ == '__main__':\r
+    pass\r
+\r