public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v1 1/1] BaseTools: Add missing content to EOT tool.
       [not found] <cover.1527171329.git.jaben.carsey@intel.com>
@ 2018-05-24 14:17 ` Jaben Carsey
  2018-05-28  1:16   ` Zhu, Yonghong
  0 siblings, 1 reply; 2+ messages in thread
From: Jaben Carsey @ 2018-05-24 14:17 UTC (permalink / raw)
  To: edk2-devel; +Cc: Liming Gao, Yonghong Zhu

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/Eot/Eot.py           | 1444 +++++++++++++++++++-
 BaseTools/Source/Python/Eot/EotGlobalData.py |   17 +
 2 files changed, 1460 insertions(+), 1 deletion(-)

diff --git a/BaseTools/Source/Python/Eot/Eot.py b/BaseTools/Source/Python/Eot/Eot.py
index fcde8fd3e22f..786868d55d99 100644
--- a/BaseTools/Source/Python/Eot/Eot.py
+++ b/BaseTools/Source/Python/Eot/Eot.py
@@ -20,7 +20,7 @@ import EotGlobalData
 from optparse import OptionParser
 from Common.String import NormPath
 from Common import BuildToolError
-from Common.Misc import GuidStructureStringToGuidString
+from Common.Misc import GuidStructureStringToGuidString, sdict
 from InfParserLite import *
 import c
 import Database
@@ -29,6 +29,1446 @@ from Report import Report
 from Common.BuildVersion import gBUILD_VERSION
 from Parser import ConvertGuid
 from Common.LongFilePathSupport import OpenLongFilePath as open
+import struct
+import uuid
+import copy
+import codecs
+
+gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
+gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'
+gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'
+gIndention = -4
+
+class Image(array):
+    _HEADER_ = struct.Struct("")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    def __new__(cls, *args, **kwargs):
+        return array.__new__(cls, 'B')
+
+    def __init__(self, ID=None):
+        if ID is None:
+            self._ID_ = str(uuid.uuid1()).upper()
+        else:
+            self._ID_ = ID
+        self._BUF_ = None
+        self._LEN_ = None
+        self._OFF_ = None
+
+        self._SubImages = sdict() # {offset: Image()}
+
+        array.__init__(self, 'B')
+
+    def __repr__(self):
+        return self._ID_
+
+    def __len__(self):
+        Len = array.__len__(self)
+        for Offset in self._SubImages:
+            Len += len(self._SubImages[Offset])
+        return Len
+
+    def _Unpack(self):
+        self.extend(self._BUF_[self._OFF_ : self._OFF_ + self._LEN_])
+        return len(self)
+
+    def _Pack(self, PadByte=0xFF):
+        raise NotImplementedError
+
+    def frombuffer(self, Buffer, Offset=0, Size=None):
+        self._BUF_ = Buffer
+        self._OFF_ = Offset
+        # we may need the Size information in advance if it's given
+        self._LEN_ = Size
+        self._LEN_ = self._Unpack()
+
+    def empty(self):
+        del self[0:]
+
+    def GetField(self, FieldStruct, Offset=0):
+        return FieldStruct.unpack_from(self, Offset)
+
+    def SetField(self, FieldStruct, Offset, *args):
+        # check if there's enough space
+        Size = FieldStruct.size
+        if Size > len(self):
+            self.extend([0] * (Size - len(self)))
+        FieldStruct.pack_into(self, Offset, *args)
+
+    def _SetData(self, Data):
+        if len(self) < self._HEADER_SIZE_:
+            self.extend([0] * (self._HEADER_SIZE_ - len(self)))
+        else:
+            del self[self._HEADER_SIZE_:]
+        self.extend(Data)
+
+    def _GetData(self):
+        if len(self) > self._HEADER_SIZE_:
+            return self[self._HEADER_SIZE_:]
+        return None
+
+    Data = property(_GetData, _SetData)
+
+## CompressedImage() class
+#
+#  A class for Compressed Image
+#
+class CompressedImage(Image):
+    # UncompressedLength = 4-byte
+    # CompressionType = 1-byte
+    _HEADER_ = struct.Struct("1I 1B")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _ORIG_SIZE_     = struct.Struct("1I")
+    _CMPRS_TYPE_    = struct.Struct("4x 1B")
+
+    def __init__(m, CompressedData=None, CompressionType=None, UncompressedLength=None):
+        Image.__init__(m)
+        if UncompressedLength is not None:
+            m.UncompressedLength = UncompressedLength
+        if CompressionType is not None:
+            m.CompressionType = CompressionType
+        if CompressedData is not None:
+            m.Data = CompressedData
+
+    def __str__(m):
+        global gIndention
+        S = "algorithm=%s uncompressed=%x" % (m.CompressionType, m.UncompressedLength)
+        for Sec in m.Sections:
+            S += '\n' + str(Sec)
+
+        return S
+
+    def _SetOriginalSize(m, Size):
+        m.SetField(m._ORIG_SIZE_, 0, Size)
+
+    def _GetOriginalSize(m):
+        return m.GetField(m._ORIG_SIZE_)[0]
+
+    def _SetCompressionType(m, Type):
+        m.SetField(m._CMPRS_TYPE_, 0, Type)
+
+    def _GetCompressionType(m):
+        return m.GetField(m._CMPRS_TYPE_)[0]
+
+    def _GetSections(m):
+        try:
+            import EfiCompressor
+            TmpData = EfiCompressor.FrameworkDecompress(
+                                        m[m._HEADER_SIZE_:],
+                                        len(m) - m._HEADER_SIZE_
+                                        )
+            DecData = array('B')
+            DecData.fromstring(TmpData)
+        except:
+            import EfiCompressor
+            TmpData = EfiCompressor.UefiDecompress(
+                                        m[m._HEADER_SIZE_:],
+                                        len(m) - m._HEADER_SIZE_
+                                        )
+            DecData = array('B')
+            DecData.fromstring(TmpData)
+
+        SectionList = []
+        Offset = 0
+        while Offset < len(DecData):
+            Sec = Section()
+            try:
+                Sec.frombuffer(DecData, Offset)
+                Offset += Sec.Size
+                # the section is aligned to 4-byte boundary
+            except:
+                break
+            SectionList.append(Sec)
+        return SectionList
+
+    UncompressedLength = property(_GetOriginalSize, _SetOriginalSize)
+    CompressionType = property(_GetCompressionType, _SetCompressionType)
+    Sections = property(_GetSections)
+
+## Ui() class
+#
+#  A class for Ui
+#
+class Ui(Image):
+    _HEADER_ = struct.Struct("")
+    _HEADER_SIZE_ = 0
+
+    def __init__(m):
+        Image.__init__(m)
+
+    def __str__(m):
+        return m.String
+
+    def _Unpack(m):
+        # keep header in this Image object
+        m.empty()
+        m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
+        return len(m)
+
+    def _GetUiString(m):
+        return codecs.utf_16_decode(m[0:-2].tostring())[0]
+
+    String = property(_GetUiString)
+
+## Depex() class
+#
+#  A class for Depex
+#
+class Depex(Image):
+    _HEADER_ = struct.Struct("")
+    _HEADER_SIZE_ = 0
+
+    _GUID_          = struct.Struct("1I2H8B")
+    _OPCODE_        = struct.Struct("1B")
+
+    _OPCODE_STRING_ = {
+        0x00    :   "BEFORE",
+        0x01    :   "AFTER",
+        0x02    :   "PUSH",
+        0x03    :   "AND",
+        0x04    :   "OR",
+        0x05    :   "NOT",
+        0x06    :   "TRUE",
+        0x07    :   "FALSE",
+        0x08    :   "END",
+        0x09    :   "SOR"
+    }
+
+    _NEXT_ = {
+        -1      :   _OPCODE_,   # first one in depex must be an opcdoe
+        0x00    :   _GUID_,     #"BEFORE",
+        0x01    :   _GUID_,     #"AFTER",
+        0x02    :   _GUID_,     #"PUSH",
+        0x03    :   _OPCODE_,   #"AND",
+        0x04    :   _OPCODE_,   #"OR",
+        0x05    :   _OPCODE_,   #"NOT",
+        0x06    :   _OPCODE_,   #"TRUE",
+        0x07    :   _OPCODE_,   #"FALSE",
+        0x08    :   None,       #"END",
+        0x09    :   _OPCODE_,   #"SOR"
+    }
+
+    def __init__(m):
+        Image.__init__(m)
+        m._ExprList = []
+
+    def __str__(m):
+        global gIndention
+        gIndention += 4
+        Indention = ' ' * gIndention
+        S = '\n'
+        for T in m.Expression:
+            if T in m._OPCODE_STRING_:
+                S += Indention + m._OPCODE_STRING_[T]
+                if T not in [0x00, 0x01, 0x02]:
+                    S += '\n'
+            else:
+                S += ' ' + gGuidStringFormat % T + '\n'
+        gIndention -= 4
+        return S
+
+    def _Unpack(m):
+        # keep header in this Image object
+        m.empty()
+        m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
+        return len(m)
+
+    def _GetExpression(m):
+        if m._ExprList == []:
+            Offset = 0
+            CurrentData = m._OPCODE_
+            while Offset < len(m):
+                Token = CurrentData.unpack_from(m, Offset)
+                Offset += CurrentData.size
+                if len(Token) == 1:
+                    Token = Token[0]
+                    if Token in m._NEXT_:
+                        CurrentData = m._NEXT_[Token]
+                    else:
+                        CurrentData = m._GUID_
+                else:
+                    CurrentData = m._OPCODE_
+                m._ExprList.append(Token)
+                if CurrentData is None:
+                    break
+        return m._ExprList
+
+    Expression = property(_GetExpression)
+
+## FirmwareVolume() class
+#
+#  A class for Firmware Volume
+#
+class FirmwareVolume(Image):
+    # Read FvLength, Attributes, HeaderLength, Checksum
+    _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
+
+    _GUID_      = struct.Struct("16x 1I2H8B")
+    _LENGTH_    = struct.Struct("16x 16x 1Q")
+    _SIG_       = struct.Struct("16x 16x 8x 1I")
+    _ATTR_      = struct.Struct("16x 16x 8x 4x 1I")
+    _HLEN_      = struct.Struct("16x 16x 8x 4x 4x 1H")
+    _CHECKSUM_  = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
+
+    def __init__(self, Name=''):
+        Image.__init__(self)
+        self.Name = Name
+        self.FfsDict = sdict()
+        self.OrderedFfsDict = sdict()
+        self.UnDispatchedFfsDict = sdict()
+        self.ProtocolList = sdict()
+
+    def CheckArchProtocol(self):
+        for Item in EotGlobalData.gArchProtocolGuids:
+            if Item.lower() not in EotGlobalData.gProtocolList:
+
+                return False
+
+        return True
+
+    def ParseDepex(self, Depex, Type):
+        List = None
+        if Type == 'Ppi':
+            List = EotGlobalData.gPpiList
+        if Type == 'Protocol':
+            List = EotGlobalData.gProtocolList
+        DepexStack = []
+        DepexList = []
+        DepexString = ''
+        FileDepex = None
+        CouldBeLoaded = True
+        for Index in range(0, len(Depex.Expression)):
+            Item = Depex.Expression[Index]
+            if Item == 0x00:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
+            elif Item == 0x01:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
+            elif Item == 0x02:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid.lower() in List:
+                    DepexStack.append(True)
+                    DepexList.append(Guid)
+                else:
+                    DepexStack.append(False)
+                    DepexList.append(Guid)
+                continue
+            elif Item == 0x03 or Item == 0x04:
+                DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
+            elif Item == 0x05:
+                DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
+            elif Item == 0x06:
+                DepexStack.append(True)
+                DepexList.append('TRUE')
+                DepexString = DepexString + 'TRUE' + ' '
+            elif Item == 0x07:
+                DepexStack.append(False)
+                DepexList.append('False')
+                DepexString = DepexString + 'FALSE' + ' '
+            elif Item == 0x08:
+                if Index != len(Depex.Expression) - 1:
+                    CouldBeLoaded = False
+                else:
+                    CouldBeLoaded = DepexStack.pop()
+            else:
+                CouldBeLoaded = False
+        if DepexList != []:
+            DepexString = DepexList[0].strip()
+        return (CouldBeLoaded, DepexString, FileDepex)
+
+    def Dispatch(self, Db = None):
+        if Db is None:
+            return False
+        self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
+        # Find PeiCore, DexCore, PeiPriori, DxePriori first
+        FfsSecCoreGuid = None
+        FfsPeiCoreGuid = None
+        FfsDxeCoreGuid = None
+        FfsPeiPrioriGuid = None
+        FfsDxePrioriGuid = None
+        for FfsID in self.UnDispatchedFfsDict:
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x03:
+                FfsSecCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x04:
+                FfsPeiCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x05:
+                FfsDxeCoreGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
+                FfsPeiPrioriGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gAprioriGuid:
+                FfsDxePrioriGuid = FfsID
+                continue
+
+        # Parse SEC_CORE first
+        if FfsSecCoreGuid is not None:
+            self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
+            self.LoadPpi(Db, FfsSecCoreGuid)
+
+        # Parse PEI first
+        if FfsPeiCoreGuid is not None:
+            self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
+            self.LoadPpi(Db, FfsPeiCoreGuid)
+            if FfsPeiPrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
+                if len(FfsPeiPriori.Sections) == 1:
+                    Section = FfsPeiPriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadPpi(Db, GuidString)
+
+        self.DisPatchPei(Db)
+
+        # Parse DXE then
+        if FfsDxeCoreGuid is not None:
+            self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
+            self.LoadProtocol(Db, FfsDxeCoreGuid)
+            if FfsDxePrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
+                if len(FfsDxePriori.Sections) == 1:
+                    Section = FfsDxePriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadProtocol(Db, GuidString)
+
+        self.DisPatchDxe(Db)
+
+    def LoadProtocol(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            SqlCommand = """select Value2 from Inf where BelongsToFile =
+                            (select DISTINCT BelongsToFile from Inf
+                            where Value1 =
+                            (select SourceFileFullPath from Report
+                            where GuidValue like '%s' and ItemMode = 'Callback'))
+                            and Value1 = 'FILE_GUID'""" % Record[0]
+            CallBackSet = Db.TblReport.Exec(SqlCommand)
+            if CallBackSet != []:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+            else:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+
+    def LoadPpi(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
+
+    def DisPatchDxe(self, Db):
+        IsInstalled = False
+        ScheduleList = sdict()
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = False
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x07:
+                # Get Depex
+                IsFoundDepex = False
+                for Section in Ffs.Sections.values():
+                    # Find Depex
+                    if Section.Type == 0x13:
+                        IsFoundDepex = True
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
+                        break
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x13:
+                                IsFoundDepex = True
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x13:
+                                        IsFoundDepex = True
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
+                                        break
+
+                # Not find Depex
+                if not IsFoundDepex:
+                    CouldBeLoaded = self.CheckArchProtocol()
+                    DepexString = ''
+                    FileDepex = None
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    if FileDepex is not None:
+                        ScheduleList.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
+                    else:
+                        ScheduleList[FfsID] = NewFfs
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        for FfsID in ScheduleList:
+            NewFfs = ScheduleList.pop(FfsID)
+            FfsName = 'UnKnown'
+            self.OrderedFfsDict[FfsID] = NewFfs
+            self.LoadProtocol(Db, FfsID)
+
+            SqlCommand = """select Value2 from Inf
+                            where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
+                            and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
+            RecordSet = Db.TblReport.Exec(SqlCommand)
+            if RecordSet != []:
+                FfsName = RecordSet[0][0]
+
+        if IsInstalled:
+            self.DisPatchDxe(Db)
+
+    def DisPatchPei(self, Db):
+        IsInstalled = False
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = True
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x06 or Ffs.Type == 0x08:
+                # Get Depex
+                for Section in Ffs.Sections.values():
+                    if Section.Type == 0x1B:
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
+                        break
+
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x1B:
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x1B:
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
+                                        break
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    self.OrderedFfsDict[FfsID] = NewFfs
+                    self.LoadPpi(Db, FfsID)
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        if IsInstalled:
+            self.DisPatchPei(Db)
+
+
+    def __str__(self):
+        global gIndention
+        gIndention += 4
+        FvInfo = '\n' + ' ' * gIndention
+        FvInfo +=  "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
+        FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
+        gIndention -= 4
+        return FvInfo + FfsInfo
+
+    def _Unpack(self):
+        Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
+        self.empty()
+        self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
+
+        # traverse the FFS
+        EndOfFv = Size
+        FfsStartAddress = self.HeaderSize
+        LastFfsObj = None
+        while FfsStartAddress < EndOfFv:
+            FfsObj = Ffs()
+            FfsObj.frombuffer(self, FfsStartAddress)
+            FfsId = repr(FfsObj)
+            if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
+                or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
+            else:
+                if FfsId in self.FfsDict:
+                    EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
+                                    ExtraData="\t%s @ %s\n\t%s @ %s" \
+                                    % (FfsObj.Guid, FfsObj.Offset,
+                                       self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
+                self.FfsDict[FfsId] = FfsObj
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
+
+            FfsStartAddress += len(FfsObj)
+            #
+            # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
+            # The next FFS must be at the latest next 8-byte aligned address
+            #
+            FfsStartAddress = (FfsStartAddress + 7) & (~7)
+            LastFfsObj = FfsObj
+
+    def _GetAttributes(self):
+        return self.GetField(self._ATTR_, 0)[0]
+
+    def _GetSize(self):
+        return self.GetField(self._LENGTH_, 0)[0]
+
+    def _GetChecksum(self):
+        return self.GetField(self._CHECKSUM_, 0)[0]
+
+    def _GetHeaderLength(self):
+        return self.GetField(self._HLEN_, 0)[0]
+
+    def _GetFileSystemGuid(self):
+        return gGuidStringFormat % self.GetField(self._GUID_, 0)
+
+    Attributes = property(_GetAttributes)
+    Size = property(_GetSize)
+    Checksum = property(_GetChecksum)
+    HeaderSize = property(_GetHeaderLength)
+    FileSystemGuid = property(_GetFileSystemGuid)
+
+## GuidDefinedImage() class
+#
+#  A class for GUID Defined Image
+#
+class GuidDefinedImage(Image):
+    _HEADER_ = struct.Struct("1I2H8B 1H 1H")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _GUID_          = struct.Struct("1I2H8B")
+    _DATA_OFFSET_   = struct.Struct("16x 1H")
+    _ATTR_          = struct.Struct("18x 1H")
+
+    CRC32_GUID          = "FC1BCDB0-7D31-49AA-936A-A4600D9DD083"
+    TIANO_COMPRESS_GUID = 'A31280AD-481E-41B6-95E8-127F4C984779'
+    LZMA_COMPRESS_GUID  = 'EE4E5898-3914-4259-9D6E-DC7BD79403CF'
+
+    def __init__(m, SectionDefinitionGuid=None, DataOffset=None, Attributes=None, Data=None):
+        Image.__init__(m)
+        if SectionDefinitionGuid is not None:
+            m.SectionDefinitionGuid = SectionDefinitionGuid
+        if DataOffset is not None:
+            m.DataOffset = DataOffset
+        if Attributes is not None:
+            m.Attributes = Attributes
+        if Data is not None:
+            m.Data = Data
+
+    def __str__(m):
+        S = "guid=%s" % (gGuidStringFormat % m.SectionDefinitionGuid)
+        for Sec in m.Sections:
+            S += "\n" + str(Sec)
+        return S
+
+    def _Unpack(m):
+        # keep header in this Image object
+        m.empty()
+        m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
+        return len(m)
+
+    def _SetAttribute(m, Attribute):
+        m.SetField(m._ATTR_, 0, Attribute)
+
+    def _GetAttribute(m):
+        return m.GetField(m._ATTR_)[0]
+
+    def _SetGuid(m, Guid):
+        m.SetField(m._GUID_, 0, Guid)
+
+    def _GetGuid(m):
+        return m.GetField(m._GUID_)
+
+    def _SetDataOffset(m, Offset):
+        m.SetField(m._DATA_OFFSET_, 0, Offset)
+
+    def _GetDataOffset(m):
+        return m.GetField(m._DATA_OFFSET_)[0]
+
+    def _GetSections(m):
+        SectionList = []
+        Guid = gGuidStringFormat % m.SectionDefinitionGuid
+        if Guid == m.CRC32_GUID:
+            # skip the CRC32 value, we don't do CRC32 verification here
+            Offset = m.DataOffset - 4
+            while Offset < len(m):
+                Sec = Section()
+                try:
+                    Sec.frombuffer(m, Offset)
+                    Offset += Sec.Size
+                    # the section is aligned to 4-byte boundary
+                    Offset = (Offset + 3) & (~3)
+                except:
+                    break
+                SectionList.append(Sec)
+        elif Guid == m.TIANO_COMPRESS_GUID:
+            try:
+                import EfiCompressor
+                # skip the header
+                Offset = m.DataOffset - 4
+                TmpData = EfiCompressor.FrameworkDecompress(m[Offset:], len(m)-Offset)
+                DecData = array('B')
+                DecData.fromstring(TmpData)
+                Offset = 0
+                while Offset < len(DecData):
+                    Sec = Section()
+                    try:
+                        Sec.frombuffer(DecData, Offset)
+                        Offset += Sec.Size
+                        # the section is aligned to 4-byte boundary
+                        Offset = (Offset + 3) & (~3)
+                    except:
+                        break
+                    SectionList.append(Sec)
+            except:
+                pass
+        elif Guid == m.LZMA_COMPRESS_GUID:
+            try:
+                import LzmaCompressor
+                # skip the header
+                Offset = m.DataOffset - 4
+                TmpData = LzmaCompressor.LzmaDecompress(m[Offset:], len(m)-Offset)
+                DecData = array('B')
+                DecData.fromstring(TmpData)
+                Offset = 0
+                while Offset < len(DecData):
+                    Sec = Section()
+                    try:
+                        Sec.frombuffer(DecData, Offset)
+                        Offset += Sec.Size
+                        # the section is aligned to 4-byte boundary
+                        Offset = (Offset + 3) & (~3)
+                    except:
+                        break
+                    SectionList.append(Sec)
+            except:
+                pass
+
+        return SectionList
+
+    Attributes = property(_GetAttribute, _SetAttribute)
+    SectionDefinitionGuid = property(_GetGuid, _SetGuid)
+    DataOffset = property(_GetDataOffset, _SetDataOffset)
+    Sections = property(_GetSections)
+
+## Section() class
+#
+#  A class for Section
+#
+class Section(Image):
+    _TypeName = {
+        0x00    :   "<unknown>",
+        0x01    :   "COMPRESSION",
+        0x02    :   "GUID_DEFINED",
+        0x10    :   "PE32",
+        0x11    :   "PIC",
+        0x12    :   "TE",
+        0x13    :   "DXE_DEPEX",
+        0x14    :   "VERSION",
+        0x15    :   "USER_INTERFACE",
+        0x16    :   "COMPATIBILITY16",
+        0x17    :   "FIRMWARE_VOLUME_IMAGE",
+        0x18    :   "FREEFORM_SUBTYPE_GUID",
+        0x19    :   "RAW",
+        0x1B    :   "PEI_DEPEX"
+    }
+
+    _SectionSubImages = {
+        0x01    :   CompressedImage,
+        0x02    :   GuidDefinedImage,
+        0x17    :   FirmwareVolume,
+        0x13    :   Depex,
+        0x1B    :   Depex,
+        0x15    :   Ui
+    }
+
+    # Size = 3-byte
+    # Type = 1-byte
+    _HEADER_ = struct.Struct("3B 1B")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    # SubTypeGuid
+    # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
+
+    _SIZE_          = struct.Struct("3B")
+    _TYPE_          = struct.Struct("3x 1B")
+
+    def __init__(m, Type=None, Size=None):
+        Image.__init__(m)
+        m._Alignment = 1
+        if Type is not None:
+            m.Type = Type
+        if Size is not None:
+            m.Size = Size
+
+    def __str__(m):
+        global gIndention
+        gIndention += 4
+        SectionInfo = ' ' * gIndention
+        if m.Type in m._TypeName:
+            SectionInfo += "[SECTION:%s] offset=%x size=%x" % (m._TypeName[m.Type], m._OFF_, m.Size)
+        else:
+            SectionInfo += "[SECTION:%x<unknown>] offset=%x size=%x " % (m.Type, m._OFF_, m.Size)
+        for Offset in m._SubImages:
+            SectionInfo += ", " + str(m._SubImages[Offset])
+        gIndention -= 4
+        return SectionInfo
+
+    def _Unpack(m):
+        m.empty()
+        Type, = m._TYPE_.unpack_from(m._BUF_, m._OFF_)
+        Size1, Size2, Size3 = m._SIZE_.unpack_from(m._BUF_, m._OFF_)
+        Size = Size1 + (Size2 << 8) + (Size3 << 16)
+
+        if Type not in m._SectionSubImages:
+            # no need to extract sub-image, keep all in this Image object
+            m.extend(m._BUF_[m._OFF_ : m._OFF_ + Size])
+        else:
+            # keep header in this Image object
+            m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._HEADER_SIZE_])
+            #
+            # use new Image object to represent payload, which may be another kind
+            # of image such as PE32
+            #
+            PayloadOffset = m._HEADER_SIZE_
+            PayloadLen = m.Size - m._HEADER_SIZE_
+            Payload = m._SectionSubImages[m.Type]()
+            Payload.frombuffer(m._BUF_, m._OFF_ + m._HEADER_SIZE_, PayloadLen)
+            m._SubImages[PayloadOffset] = Payload
+
+        return Size
+
+    def _SetSize(m, Size):
+        Size1 = Size & 0xFF
+        Size2 = (Size & 0xFF00) >> 8
+        Size3 = (Size & 0xFF0000) >> 16
+        m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
+
+    def _GetSize(m):
+        Size1, Size2, Size3 = m.GetField(m._SIZE_)
+        return Size1 + (Size2 << 8) + (Size3 << 16)
+
+    def _SetType(m, Type):
+        m.SetField(m._TYPE_, 0, Type)
+
+    def _GetType(m):
+        return m.GetField(m._TYPE_)[0]
+
+    def _GetAlignment(m):
+        return m._Alignment
+
+    def _SetAlignment(m, Alignment):
+        m._Alignment = Alignment
+        AlignmentMask = Alignment - 1
+        # section alignment is actually for payload, so we need to add header size
+        PayloadOffset = m._OFF_ + m._HEADER_SIZE_
+        if (PayloadOffset & (~AlignmentMask)) == 0:
+            return
+        NewOffset = (PayloadOffset + AlignmentMask) & (~AlignmentMask)
+        while (NewOffset - PayloadOffset) < m._HEADER_SIZE_:
+            NewOffset += m._Alignment
+
+    def tofile(m, f):
+        m.Size = len(m)
+        Image.tofile(m, f)
+        for Offset in m._SubImages:
+            m._SubImages[Offset].tofile(f)
+
+    Type = property(_GetType, _SetType)
+    Size = property(_GetSize, _SetSize)
+    Alignment = property(_GetAlignment, _SetAlignment)
+
+## Ffs() class
+#
+#  A class for Ffs Section
+#
+class Ffs(Image):
+    _FfsFormat = "24B%(payload_size)sB"
+    # skip IntegrityCheck
+    _HEADER_ = struct.Struct("1I2H8B 2x 1B 1B 3B 1B")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _NAME_      = struct.Struct("1I2H8B")
+    _INT_CHECK_ = struct.Struct("16x 1H")
+    _TYPE_      = struct.Struct("18x 1B")
+    _ATTR_      = struct.Struct("19x 1B")
+    _SIZE_      = struct.Struct("20x 3B")
+    _STATE_     = struct.Struct("23x 1B")
+
+    VTF_GUID = "1BA0062E-C779-4582-8566-336AE8F78F09"
+
+    FFS_ATTRIB_FIXED              = 0x04
+    FFS_ATTRIB_DATA_ALIGNMENT     = 0x38
+    FFS_ATTRIB_CHECKSUM           = 0x40
+
+    _TypeName = {
+        0x00    :   "<unknown>",
+        0x01    :   "RAW",
+        0x02    :   "FREEFORM",
+        0x03    :   "SECURITY_CORE",
+        0x04    :   "PEI_CORE",
+        0x05    :   "DXE_CORE",
+        0x06    :   "PEIM",
+        0x07    :   "DRIVER",
+        0x08    :   "COMBINED_PEIM_DRIVER",
+        0x09    :   "APPLICATION",
+        0x0A    :   "SMM",
+        0x0B    :   "FIRMWARE_VOLUME_IMAGE",
+        0x0C    :   "COMBINED_SMM_DXE",
+        0x0D    :   "SMM_CORE",
+        0x0E    :   "MM_STANDALONE",
+        0x0F    :   "MM_CORE_STANDALONE",
+        0xc0    :   "OEM_MIN",
+        0xdf    :   "OEM_MAX",
+        0xe0    :   "DEBUG_MIN",
+        0xef    :   "DEBUG_MAX",
+        0xf0    :   "FFS_MIN",
+        0xff    :   "FFS_MAX",
+        0xf0    :   "FFS_PAD",
+    }
+
+    def __init__(self):
+        Image.__init__(self)
+        self.FreeSpace = 0
+
+        self.Sections = sdict()
+        self.Depex = ''
+
+        self.__ID__ = None
+
+    def __str__(self):
+        global gIndention
+        gIndention += 4
+        Indention = ' ' * gIndention
+        FfsInfo = Indention
+        FfsInfo +=  "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
+                    (Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment)
+        SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections])
+        gIndention -= 4
+        return FfsInfo + SectionInfo + "\n"
+
+    def __len__(self):
+        return self.Size
+
+    def __repr__(self):
+        return self.__ID__
+
+    def _Unpack(self):
+        Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_)
+        Size = Size1 + (Size2 << 8) + (Size3 << 16)
+        self.empty()
+        self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size])
+
+        # Pad FFS may use the same GUID. We need to avoid it.
+        if self.Type == 0xf0:
+            self.__ID__ = str(uuid.uuid1()).upper()
+        else:
+            self.__ID__ = self.Guid
+
+        # Traverse the SECTION. RAW and PAD do not have sections
+        if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF:
+            EndOfFfs = Size
+            SectionStartAddress = self._HEADER_SIZE_
+            while SectionStartAddress < EndOfFfs:
+                SectionObj = Section()
+                SectionObj.frombuffer(self, SectionStartAddress)
+                #f = open(repr(SectionObj), 'wb')
+                #SectionObj.Size = 0
+                #SectionObj.tofile(f)
+                #f.close()
+                self.Sections[SectionStartAddress] = SectionObj
+                SectionStartAddress += len(SectionObj)
+                SectionStartAddress = (SectionStartAddress + 3) & (~3)
+
+    def Pack(self):
+        pass
+
+    def SetFreeSpace(self, Size):
+        self.FreeSpace = Size
+
+    def _GetGuid(self):
+        return gGuidStringFormat % self.Name
+
+    def _SetName(self, Value):
+        # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
+        self.SetField(self._NAME_, 0, Value)
+
+    def _GetName(self):
+        # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
+        return self.GetField(self._NAME_)
+
+    def _SetSize(m, Size):
+        Size1 = Size & 0xFF
+        Size2 = (Size & 0xFF00) >> 8
+        Size3 = (Size & 0xFF0000) >> 16
+        m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
+
+    def _GetSize(m):
+        Size1, Size2, Size3 = m.GetField(m._SIZE_)
+        return Size1 + (Size2 << 8) + (Size3 << 16)
+
+    def _SetType(m, Type):
+        m.SetField(m._TYPE_, 0, Type)
+
+    def _GetType(m):
+        return m.GetField(m._TYPE_)[0]
+
+    def _SetAttributes(self, Value):
+        self.SetField(m._ATTR_, 0, Value)
+
+    def _GetAttributes(self):
+        return self.GetField(self._ATTR_)[0]
+
+    def _GetFixed(self):
+        if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0:
+            return True
+        return False
+
+    def _GetCheckSum(self):
+        if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0:
+            return True
+        return False
+
+    def _GetAlignment(self):
+        return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3
+
+    def _SetState(self, Value):
+        self.SetField(m._STATE_, 0, Value)
+
+    def _GetState(self):
+        return self.GetField(m._STATE_)[0]
+
+    Name = property(_GetName, _SetName)
+    Guid = property(_GetGuid)
+    Type = property(_GetType, _SetType)
+    Size = property(_GetSize, _SetSize)
+    Attributes = property(_GetAttributes, _SetAttributes)
+    Fixed = property(_GetFixed)
+    Checksum = property(_GetCheckSum)
+    Alignment = property(_GetAlignment)
+    State = property(_GetState, _SetState)
+
+## FirmwareVolume() class
+#
+#  A class for Firmware Volume
+#
+class FirmwareVolume(Image):
+    # Read FvLength, Attributes, HeaderLength, Checksum
+    _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
+
+    _GUID_      = struct.Struct("16x 1I2H8B")
+    _LENGTH_    = struct.Struct("16x 16x 1Q")
+    _SIG_       = struct.Struct("16x 16x 8x 1I")
+    _ATTR_      = struct.Struct("16x 16x 8x 4x 1I")
+    _HLEN_      = struct.Struct("16x 16x 8x 4x 4x 1H")
+    _CHECKSUM_  = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
+
+    def __init__(self, Name=''):
+        Image.__init__(self)
+        self.Name = Name
+        self.FfsDict = sdict()
+        self.OrderedFfsDict = sdict()
+        self.UnDispatchedFfsDict = sdict()
+        self.ProtocolList = sdict()
+
+    def CheckArchProtocol(self):
+        for Item in EotGlobalData.gArchProtocolGuids:
+            if Item.lower() not in EotGlobalData.gProtocolList:
+
+                return False
+
+        return True
+
+    def ParseDepex(self, Depex, Type):
+        List = None
+        if Type == 'Ppi':
+            List = EotGlobalData.gPpiList
+        if Type == 'Protocol':
+            List = EotGlobalData.gProtocolList
+        DepexStack = []
+        DepexList = []
+        DepexString = ''
+        FileDepex = None
+        CouldBeLoaded = True
+        for Index in range(0, len(Depex.Expression)):
+            Item = Depex.Expression[Index]
+            if Item == 0x00:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
+            elif Item == 0x01:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
+            elif Item == 0x02:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid.lower() in List:
+                    DepexStack.append(True)
+                    DepexList.append(Guid)
+                else:
+                    DepexStack.append(False)
+                    DepexList.append(Guid)
+                continue
+            elif Item == 0x03 or Item == 0x04:
+                DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
+            elif Item == 0x05:
+                DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
+            elif Item == 0x06:
+                DepexStack.append(True)
+                DepexList.append('TRUE')
+                DepexString = DepexString + 'TRUE' + ' '
+            elif Item == 0x07:
+                DepexStack.append(False)
+                DepexList.append('False')
+                DepexString = DepexString + 'FALSE' + ' '
+            elif Item == 0x08:
+                if Index != len(Depex.Expression) - 1:
+                    CouldBeLoaded = False
+                else:
+                    CouldBeLoaded = DepexStack.pop()
+            else:
+                CouldBeLoaded = False
+        if DepexList != []:
+            DepexString = DepexList[0].strip()
+        return (CouldBeLoaded, DepexString, FileDepex)
+
+    def Dispatch(self, Db = None):
+        if Db is None:
+            return False
+        self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
+        # Find PeiCore, DexCore, PeiPriori, DxePriori first
+        FfsSecCoreGuid = None
+        FfsPeiCoreGuid = None
+        FfsDxeCoreGuid = None
+        FfsPeiPrioriGuid = None
+        FfsDxePrioriGuid = None
+        for FfsID in self.UnDispatchedFfsDict:
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x03:
+                FfsSecCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x04:
+                FfsPeiCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x05:
+                FfsDxeCoreGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
+                FfsPeiPrioriGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gAprioriGuid:
+                FfsDxePrioriGuid = FfsID
+                continue
+
+        # Parse SEC_CORE first
+        if FfsSecCoreGuid is not None:
+            self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
+            self.LoadPpi(Db, FfsSecCoreGuid)
+
+        # Parse PEI first
+        if FfsPeiCoreGuid is not None:
+            self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
+            self.LoadPpi(Db, FfsPeiCoreGuid)
+            if FfsPeiPrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
+                if len(FfsPeiPriori.Sections) == 1:
+                    Section = FfsPeiPriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadPpi(Db, GuidString)
+
+        self.DisPatchPei(Db)
+
+        # Parse DXE then
+        if FfsDxeCoreGuid is not None:
+            self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
+            self.LoadProtocol(Db, FfsDxeCoreGuid)
+            if FfsDxePrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
+                if len(FfsDxePriori.Sections) == 1:
+                    Section = FfsDxePriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadProtocol(Db, GuidString)
+
+        self.DisPatchDxe(Db)
+
+    def LoadProtocol(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            SqlCommand = """select Value2 from Inf where BelongsToFile =
+                            (select DISTINCT BelongsToFile from Inf
+                            where Value1 =
+                            (select SourceFileFullPath from Report
+                            where GuidValue like '%s' and ItemMode = 'Callback'))
+                            and Value1 = 'FILE_GUID'""" % Record[0]
+            CallBackSet = Db.TblReport.Exec(SqlCommand)
+            if CallBackSet != []:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+            else:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+
+    def LoadPpi(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
+
+    def DisPatchDxe(self, Db):
+        IsInstalled = False
+        ScheduleList = sdict()
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = False
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x07:
+                # Get Depex
+                IsFoundDepex = False
+                for Section in Ffs.Sections.values():
+                    # Find Depex
+                    if Section.Type == 0x13:
+                        IsFoundDepex = True
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
+                        break
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x13:
+                                IsFoundDepex = True
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x13:
+                                        IsFoundDepex = True
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
+                                        break
+
+                # Not find Depex
+                if not IsFoundDepex:
+                    CouldBeLoaded = self.CheckArchProtocol()
+                    DepexString = ''
+                    FileDepex = None
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    if FileDepex is not None:
+                        ScheduleList.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
+                    else:
+                        ScheduleList[FfsID] = NewFfs
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        for FfsID in ScheduleList:
+            NewFfs = ScheduleList.pop(FfsID)
+            FfsName = 'UnKnown'
+            self.OrderedFfsDict[FfsID] = NewFfs
+            self.LoadProtocol(Db, FfsID)
+
+            SqlCommand = """select Value2 from Inf
+                            where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
+                            and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
+            RecordSet = Db.TblReport.Exec(SqlCommand)
+            if RecordSet != []:
+                FfsName = RecordSet[0][0]
+
+        if IsInstalled:
+            self.DisPatchDxe(Db)
+
+    def DisPatchPei(self, Db):
+        IsInstalled = False
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = True
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x06 or Ffs.Type == 0x08:
+                # Get Depex
+                for Section in Ffs.Sections.values():
+                    if Section.Type == 0x1B:
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
+                        break
+
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x1B:
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x1B:
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
+                                        break
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    self.OrderedFfsDict[FfsID] = NewFfs
+                    self.LoadPpi(Db, FfsID)
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        if IsInstalled:
+            self.DisPatchPei(Db)
+
+
+    def __str__(self):
+        global gIndention
+        gIndention += 4
+        FvInfo = '\n' + ' ' * gIndention
+        FvInfo +=  "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
+        FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
+        gIndention -= 4
+        return FvInfo + FfsInfo
+
+    def _Unpack(self):
+        Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
+        self.empty()
+        self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
+
+        # traverse the FFS
+        EndOfFv = Size
+        FfsStartAddress = self.HeaderSize
+        LastFfsObj = None
+        while FfsStartAddress < EndOfFv:
+            FfsObj = Ffs()
+            FfsObj.frombuffer(self, FfsStartAddress)
+            FfsId = repr(FfsObj)
+            if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
+                or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
+            else:
+                if FfsId in self.FfsDict:
+                    EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
+                                    ExtraData="\t%s @ %s\n\t%s @ %s" \
+                                    % (FfsObj.Guid, FfsObj.Offset,
+                                       self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
+                self.FfsDict[FfsId] = FfsObj
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
+
+            FfsStartAddress += len(FfsObj)
+            #
+            # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
+            # The next FFS must be at the latest next 8-byte aligned address
+            #
+            FfsStartAddress = (FfsStartAddress + 7) & (~7)
+            LastFfsObj = FfsObj
+
+    def _GetAttributes(self):
+        return self.GetField(self._ATTR_, 0)[0]
+
+    def _GetSize(self):
+        return self.GetField(self._LENGTH_, 0)[0]
+
+    def _GetChecksum(self):
+        return self.GetField(self._CHECKSUM_, 0)[0]
+
+    def _GetHeaderLength(self):
+        return self.GetField(self._HLEN_, 0)[0]
+
+    def _GetFileSystemGuid(self):
+        return gGuidStringFormat % self.GetField(self._GUID_, 0)
+
+    Attributes = property(_GetAttributes)
+    Size = property(_GetSize)
+    Checksum = property(_GetChecksum)
+    HeaderSize = property(_GetHeaderLength)
+    FileSystemGuid = property(_GetFileSystemGuid)
 
 ## MultipleFv() class
 #
@@ -390,6 +1830,8 @@ class Eot(object):
         SqlCommand = """select DISTINCT GuidValue, ItemType from Report where ModuleID = -2 and ItemMode = 'Produced'"""
         RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
         for Record in RecordSet:
+            if Record[1] == 'Ppi':
+                EotGlobalData.gPpiList[Record[0].lower()] = -2
             if Record[1] == 'Protocol':
                 EotGlobalData.gProtocolList[Record[0].lower()] = -2
 
diff --git a/BaseTools/Source/Python/Eot/EotGlobalData.py b/BaseTools/Source/Python/Eot/EotGlobalData.py
index a9f51189c1eb..cb6a940ab8f9 100644
--- a/BaseTools/Source/Python/Eot/EotGlobalData.py
+++ b/BaseTools/Source/Python/Eot/EotGlobalData.py
@@ -65,6 +65,9 @@ gGuidDict = dict()
 
 # Dict for PROTOCOL
 gProtocolList = {}
+# Dict for PPI
+gPpiList = {}
+
 
 # Dict for consumed PPI function calling
 gConsumedPpiLibrary = OrderedDict()
@@ -92,3 +95,17 @@ gConsumedProtocolLibrary['EfiHandleProtocol'] = 1
 # Dict for callback PROTOCOL function callling
 gCallbackProtocolLibrary = OrderedDict()
 gCallbackProtocolLibrary['EfiRegisterProtocolCallback'] = 2
+
+gArchProtocolGuids = {'665e3ff6-46cc-11d4-9a38-0090273fc14d',
+                      '26baccb1-6f42-11d4-bce7-0080c73c8881',
+                      '26baccb2-6f42-11d4-bce7-0080c73c8881',
+                      '1da97072-bddc-4b30-99f1-72a0b56fff2a',
+                      '27cfac87-46cc-11d4-9a38-0090273fc14d',
+                      '27cfac88-46cc-11d4-9a38-0090273fc14d',
+                      'b7dfb4e1-052f-449f-87be-9818fc91b733',
+                      'a46423e3-4617-49f1-b9ff-d1bfa9115839',
+                      'd2b2b828-0826-48a7-b3df-983c006024f0',
+                      '26baccb3-6f42-11d4-bce7-0080c73c8881',
+                      '1e5668e2-8481-11d4-bcf1-0080c73c8881',
+                      '6441f818-6362-4e44-b570-7dba31dd2453',
+                      '665e3ff5-46cc-11d4-9a38-0090273fc14d'}
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v1 1/1] BaseTools: Add missing content to EOT tool.
  2018-05-24 14:17 ` [PATCH v1 1/1] BaseTools: Add missing content to EOT tool Jaben Carsey
@ 2018-05-28  1:16   ` Zhu, Yonghong
  0 siblings, 0 replies; 2+ messages in thread
From: Zhu, Yonghong @ 2018-05-28  1:16 UTC (permalink / raw)
  To: Carsey, Jaben, edk2-devel@lists.01.org; +Cc: Gao, Liming, Zhu, Yonghong

Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com> 

Best Regards,
Zhu Yonghong

-----Original Message-----
From: Carsey, Jaben 
Sent: Thursday, May 24, 2018 10:18 PM
To: edk2-devel@lists.01.org
Cc: Gao, Liming <liming.gao@intel.com>; Zhu, Yonghong <yonghong.zhu@intel.com>
Subject: [PATCH v1 1/1] BaseTools: Add missing content to EOT tool.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jaben Carsey <jaben.carsey@intel.com>
---
 BaseTools/Source/Python/Eot/Eot.py           | 1444 +++++++++++++++++++-
 BaseTools/Source/Python/Eot/EotGlobalData.py |   17 +
 2 files changed, 1460 insertions(+), 1 deletion(-)

diff --git a/BaseTools/Source/Python/Eot/Eot.py b/BaseTools/Source/Python/Eot/Eot.py
index fcde8fd3e22f..786868d55d99 100644
--- a/BaseTools/Source/Python/Eot/Eot.py
+++ b/BaseTools/Source/Python/Eot/Eot.py
@@ -20,7 +20,7 @@ import EotGlobalData
 from optparse import OptionParser
 from Common.String import NormPath
 from Common import BuildToolError
-from Common.Misc import GuidStructureStringToGuidString
+from Common.Misc import GuidStructureStringToGuidString, sdict
 from InfParserLite import *
 import c
 import Database
@@ -29,6 +29,1446 @@ from Report import Report
 from Common.BuildVersion import gBUILD_VERSION
 from Parser import ConvertGuid
 from Common.LongFilePathSupport import OpenLongFilePath as open
+import struct
+import uuid
+import copy
+import codecs
+
+gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
+gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'
+gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'
+gIndention = -4
+
+class Image(array):
+    _HEADER_ = struct.Struct("")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    def __new__(cls, *args, **kwargs):
+        return array.__new__(cls, 'B')
+
+    def __init__(self, ID=None):
+        if ID is None:
+            self._ID_ = str(uuid.uuid1()).upper()
+        else:
+            self._ID_ = ID
+        self._BUF_ = None
+        self._LEN_ = None
+        self._OFF_ = None
+
+        self._SubImages = sdict() # {offset: Image()}
+
+        array.__init__(self, 'B')
+
+    def __repr__(self):
+        return self._ID_
+
+    def __len__(self):
+        Len = array.__len__(self)
+        for Offset in self._SubImages:
+            Len += len(self._SubImages[Offset])
+        return Len
+
+    def _Unpack(self):
+        self.extend(self._BUF_[self._OFF_ : self._OFF_ + self._LEN_])
+        return len(self)
+
+    def _Pack(self, PadByte=0xFF):
+        raise NotImplementedError
+
+    def frombuffer(self, Buffer, Offset=0, Size=None):
+        self._BUF_ = Buffer
+        self._OFF_ = Offset
+        # we may need the Size information in advance if it's given
+        self._LEN_ = Size
+        self._LEN_ = self._Unpack()
+
+    def empty(self):
+        del self[0:]
+
+    def GetField(self, FieldStruct, Offset=0):
+        return FieldStruct.unpack_from(self, Offset)
+
+    def SetField(self, FieldStruct, Offset, *args):
+        # check if there's enough space
+        Size = FieldStruct.size
+        if Size > len(self):
+            self.extend([0] * (Size - len(self)))
+        FieldStruct.pack_into(self, Offset, *args)
+
+    def _SetData(self, Data):
+        if len(self) < self._HEADER_SIZE_:
+            self.extend([0] * (self._HEADER_SIZE_ - len(self)))
+        else:
+            del self[self._HEADER_SIZE_:]
+        self.extend(Data)
+
+    def _GetData(self):
+        if len(self) > self._HEADER_SIZE_:
+            return self[self._HEADER_SIZE_:]
+        return None
+
+    Data = property(_GetData, _SetData)
+
+## CompressedImage() class
+#
+#  A class for Compressed Image
+#
+class CompressedImage(Image):
+    # UncompressedLength = 4-byte
+    # CompressionType = 1-byte
+    _HEADER_ = struct.Struct("1I 1B")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _ORIG_SIZE_     = struct.Struct("1I")
+    _CMPRS_TYPE_    = struct.Struct("4x 1B")
+
+    def __init__(m, CompressedData=None, CompressionType=None, UncompressedLength=None):
+        Image.__init__(m)
+        if UncompressedLength is not None:
+            m.UncompressedLength = UncompressedLength
+        if CompressionType is not None:
+            m.CompressionType = CompressionType
+        if CompressedData is not None:
+            m.Data = CompressedData
+
+    def __str__(m):
+        global gIndention
+        S = "algorithm=%s uncompressed=%x" % (m.CompressionType, m.UncompressedLength)
+        for Sec in m.Sections:
+            S += '\n' + str(Sec)
+
+        return S
+
+    def _SetOriginalSize(m, Size):
+        m.SetField(m._ORIG_SIZE_, 0, Size)
+
+    def _GetOriginalSize(m):
+        return m.GetField(m._ORIG_SIZE_)[0]
+
+    def _SetCompressionType(m, Type):
+        m.SetField(m._CMPRS_TYPE_, 0, Type)
+
+    def _GetCompressionType(m):
+        return m.GetField(m._CMPRS_TYPE_)[0]
+
+    def _GetSections(m):
+        try:
+            import EfiCompressor
+            TmpData = EfiCompressor.FrameworkDecompress(
+                                        m[m._HEADER_SIZE_:],
+                                        len(m) - m._HEADER_SIZE_
+                                        )
+            DecData = array('B')
+            DecData.fromstring(TmpData)
+        except:
+            import EfiCompressor
+            TmpData = EfiCompressor.UefiDecompress(
+                                        m[m._HEADER_SIZE_:],
+                                        len(m) - m._HEADER_SIZE_
+                                        )
+            DecData = array('B')
+            DecData.fromstring(TmpData)
+
+        SectionList = []
+        Offset = 0
+        while Offset < len(DecData):
+            Sec = Section()
+            try:
+                Sec.frombuffer(DecData, Offset)
+                Offset += Sec.Size
+                # the section is aligned to 4-byte boundary
+            except:
+                break
+            SectionList.append(Sec)
+        return SectionList
+
+    UncompressedLength = property(_GetOriginalSize, _SetOriginalSize)
+    CompressionType = property(_GetCompressionType, _SetCompressionType)
+    Sections = property(_GetSections)
+
+## Ui() class
+#
+#  A class for Ui
+#
+class Ui(Image):
+    _HEADER_ = struct.Struct("")
+    _HEADER_SIZE_ = 0
+
+    def __init__(m):
+        Image.__init__(m)
+
+    def __str__(m):
+        return m.String
+
+    def _Unpack(m):
+        # keep header in this Image object
+        m.empty()
+        m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
+        return len(m)
+
+    def _GetUiString(m):
+        return codecs.utf_16_decode(m[0:-2].tostring())[0]
+
+    String = property(_GetUiString)
+
+## Depex() class
+#
+#  A class for Depex
+#
+class Depex(Image):
+    _HEADER_ = struct.Struct("")
+    _HEADER_SIZE_ = 0
+
+    _GUID_          = struct.Struct("1I2H8B")
+    _OPCODE_        = struct.Struct("1B")
+
+    _OPCODE_STRING_ = {
+        0x00    :   "BEFORE",
+        0x01    :   "AFTER",
+        0x02    :   "PUSH",
+        0x03    :   "AND",
+        0x04    :   "OR",
+        0x05    :   "NOT",
+        0x06    :   "TRUE",
+        0x07    :   "FALSE",
+        0x08    :   "END",
+        0x09    :   "SOR"
+    }
+
+    _NEXT_ = {
+        -1      :   _OPCODE_,   # first one in depex must be an opcdoe
+        0x00    :   _GUID_,     #"BEFORE",
+        0x01    :   _GUID_,     #"AFTER",
+        0x02    :   _GUID_,     #"PUSH",
+        0x03    :   _OPCODE_,   #"AND",
+        0x04    :   _OPCODE_,   #"OR",
+        0x05    :   _OPCODE_,   #"NOT",
+        0x06    :   _OPCODE_,   #"TRUE",
+        0x07    :   _OPCODE_,   #"FALSE",
+        0x08    :   None,       #"END",
+        0x09    :   _OPCODE_,   #"SOR"
+    }
+
+    def __init__(m):
+        Image.__init__(m)
+        m._ExprList = []
+
+    def __str__(m):
+        global gIndention
+        gIndention += 4
+        Indention = ' ' * gIndention
+        S = '\n'
+        for T in m.Expression:
+            if T in m._OPCODE_STRING_:
+                S += Indention + m._OPCODE_STRING_[T]
+                if T not in [0x00, 0x01, 0x02]:
+                    S += '\n'
+            else:
+                S += ' ' + gGuidStringFormat % T + '\n'
+        gIndention -= 4
+        return S
+
+    def _Unpack(m):
+        # keep header in this Image object
+        m.empty()
+        m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
+        return len(m)
+
+    def _GetExpression(m):
+        if m._ExprList == []:
+            Offset = 0
+            CurrentData = m._OPCODE_
+            while Offset < len(m):
+                Token = CurrentData.unpack_from(m, Offset)
+                Offset += CurrentData.size
+                if len(Token) == 1:
+                    Token = Token[0]
+                    if Token in m._NEXT_:
+                        CurrentData = m._NEXT_[Token]
+                    else:
+                        CurrentData = m._GUID_
+                else:
+                    CurrentData = m._OPCODE_
+                m._ExprList.append(Token)
+                if CurrentData is None:
+                    break
+        return m._ExprList
+
+    Expression = property(_GetExpression)
+
+## FirmwareVolume() class
+#
+#  A class for Firmware Volume
+#
+class FirmwareVolume(Image):
+    # Read FvLength, Attributes, HeaderLength, Checksum
+    _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
+
+    _GUID_      = struct.Struct("16x 1I2H8B")
+    _LENGTH_    = struct.Struct("16x 16x 1Q")
+    _SIG_       = struct.Struct("16x 16x 8x 1I")
+    _ATTR_      = struct.Struct("16x 16x 8x 4x 1I")
+    _HLEN_      = struct.Struct("16x 16x 8x 4x 4x 1H")
+    _CHECKSUM_  = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
+
+    def __init__(self, Name=''):
+        Image.__init__(self)
+        self.Name = Name
+        self.FfsDict = sdict()
+        self.OrderedFfsDict = sdict()
+        self.UnDispatchedFfsDict = sdict()
+        self.ProtocolList = sdict()
+
+    def CheckArchProtocol(self):
+        for Item in EotGlobalData.gArchProtocolGuids:
+            if Item.lower() not in EotGlobalData.gProtocolList:
+
+                return False
+
+        return True
+
+    def ParseDepex(self, Depex, Type):
+        List = None
+        if Type == 'Ppi':
+            List = EotGlobalData.gPpiList
+        if Type == 'Protocol':
+            List = EotGlobalData.gProtocolList
+        DepexStack = []
+        DepexList = []
+        DepexString = ''
+        FileDepex = None
+        CouldBeLoaded = True
+        for Index in range(0, len(Depex.Expression)):
+            Item = Depex.Expression[Index]
+            if Item == 0x00:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
+            elif Item == 0x01:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
+            elif Item == 0x02:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid.lower() in List:
+                    DepexStack.append(True)
+                    DepexList.append(Guid)
+                else:
+                    DepexStack.append(False)
+                    DepexList.append(Guid)
+                continue
+            elif Item == 0x03 or Item == 0x04:
+                DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
+            elif Item == 0x05:
+                DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
+            elif Item == 0x06:
+                DepexStack.append(True)
+                DepexList.append('TRUE')
+                DepexString = DepexString + 'TRUE' + ' '
+            elif Item == 0x07:
+                DepexStack.append(False)
+                DepexList.append('False')
+                DepexString = DepexString + 'FALSE' + ' '
+            elif Item == 0x08:
+                if Index != len(Depex.Expression) - 1:
+                    CouldBeLoaded = False
+                else:
+                    CouldBeLoaded = DepexStack.pop()
+            else:
+                CouldBeLoaded = False
+        if DepexList != []:
+            DepexString = DepexList[0].strip()
+        return (CouldBeLoaded, DepexString, FileDepex)
+
+    def Dispatch(self, Db = None):
+        if Db is None:
+            return False
+        self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
+        # Find PeiCore, DexCore, PeiPriori, DxePriori first
+        FfsSecCoreGuid = None
+        FfsPeiCoreGuid = None
+        FfsDxeCoreGuid = None
+        FfsPeiPrioriGuid = None
+        FfsDxePrioriGuid = None
+        for FfsID in self.UnDispatchedFfsDict:
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x03:
+                FfsSecCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x04:
+                FfsPeiCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x05:
+                FfsDxeCoreGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
+                FfsPeiPrioriGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gAprioriGuid:
+                FfsDxePrioriGuid = FfsID
+                continue
+
+        # Parse SEC_CORE first
+        if FfsSecCoreGuid is not None:
+            self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
+            self.LoadPpi(Db, FfsSecCoreGuid)
+
+        # Parse PEI first
+        if FfsPeiCoreGuid is not None:
+            self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
+            self.LoadPpi(Db, FfsPeiCoreGuid)
+            if FfsPeiPrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
+                if len(FfsPeiPriori.Sections) == 1:
+                    Section = FfsPeiPriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadPpi(Db, GuidString)
+
+        self.DisPatchPei(Db)
+
+        # Parse DXE then
+        if FfsDxeCoreGuid is not None:
+            self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
+            self.LoadProtocol(Db, FfsDxeCoreGuid)
+            if FfsDxePrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
+                if len(FfsDxePriori.Sections) == 1:
+                    Section = FfsDxePriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadProtocol(Db, GuidString)
+
+        self.DisPatchDxe(Db)
+
+    def LoadProtocol(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            SqlCommand = """select Value2 from Inf where BelongsToFile =
+                            (select DISTINCT BelongsToFile from Inf
+                            where Value1 =
+                            (select SourceFileFullPath from Report
+                            where GuidValue like '%s' and ItemMode = 'Callback'))
+                            and Value1 = 'FILE_GUID'""" % Record[0]
+            CallBackSet = Db.TblReport.Exec(SqlCommand)
+            if CallBackSet != []:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+            else:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+
+    def LoadPpi(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
+
+    def DisPatchDxe(self, Db):
+        IsInstalled = False
+        ScheduleList = sdict()
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = False
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x07:
+                # Get Depex
+                IsFoundDepex = False
+                for Section in Ffs.Sections.values():
+                    # Find Depex
+                    if Section.Type == 0x13:
+                        IsFoundDepex = True
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
+                        break
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x13:
+                                IsFoundDepex = True
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x13:
+                                        IsFoundDepex = True
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
+                                        break
+
+                # Not find Depex
+                if not IsFoundDepex:
+                    CouldBeLoaded = self.CheckArchProtocol()
+                    DepexString = ''
+                    FileDepex = None
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    if FileDepex is not None:
+                        ScheduleList.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
+                    else:
+                        ScheduleList[FfsID] = NewFfs
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        for FfsID in ScheduleList:
+            NewFfs = ScheduleList.pop(FfsID)
+            FfsName = 'UnKnown'
+            self.OrderedFfsDict[FfsID] = NewFfs
+            self.LoadProtocol(Db, FfsID)
+
+            SqlCommand = """select Value2 from Inf
+                            where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
+                            and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
+            RecordSet = Db.TblReport.Exec(SqlCommand)
+            if RecordSet != []:
+                FfsName = RecordSet[0][0]
+
+        if IsInstalled:
+            self.DisPatchDxe(Db)
+
+    def DisPatchPei(self, Db):
+        IsInstalled = False
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = True
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x06 or Ffs.Type == 0x08:
+                # Get Depex
+                for Section in Ffs.Sections.values():
+                    if Section.Type == 0x1B:
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
+                        break
+
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x1B:
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x1B:
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
+                                        break
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    self.OrderedFfsDict[FfsID] = NewFfs
+                    self.LoadPpi(Db, FfsID)
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        if IsInstalled:
+            self.DisPatchPei(Db)
+
+
+    def __str__(self):
+        global gIndention
+        gIndention += 4
+        FvInfo = '\n' + ' ' * gIndention
+        FvInfo +=  "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
+        FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
+        gIndention -= 4
+        return FvInfo + FfsInfo
+
+    def _Unpack(self):
+        Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
+        self.empty()
+        self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
+
+        # traverse the FFS
+        EndOfFv = Size
+        FfsStartAddress = self.HeaderSize
+        LastFfsObj = None
+        while FfsStartAddress < EndOfFv:
+            FfsObj = Ffs()
+            FfsObj.frombuffer(self, FfsStartAddress)
+            FfsId = repr(FfsObj)
+            if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
+                or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
+            else:
+                if FfsId in self.FfsDict:
+                    EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
+                                    ExtraData="\t%s @ %s\n\t%s @ %s" \
+                                    % (FfsObj.Guid, FfsObj.Offset,
+                                       self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
+                self.FfsDict[FfsId] = FfsObj
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
+
+            FfsStartAddress += len(FfsObj)
+            #
+            # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
+            # The next FFS must be at the latest next 8-byte aligned address
+            #
+            FfsStartAddress = (FfsStartAddress + 7) & (~7)
+            LastFfsObj = FfsObj
+
+    def _GetAttributes(self):
+        return self.GetField(self._ATTR_, 0)[0]
+
+    def _GetSize(self):
+        return self.GetField(self._LENGTH_, 0)[0]
+
+    def _GetChecksum(self):
+        return self.GetField(self._CHECKSUM_, 0)[0]
+
+    def _GetHeaderLength(self):
+        return self.GetField(self._HLEN_, 0)[0]
+
+    def _GetFileSystemGuid(self):
+        return gGuidStringFormat % self.GetField(self._GUID_, 0)
+
+    Attributes = property(_GetAttributes)
+    Size = property(_GetSize)
+    Checksum = property(_GetChecksum)
+    HeaderSize = property(_GetHeaderLength)
+    FileSystemGuid = property(_GetFileSystemGuid)
+
+## GuidDefinedImage() class
+#
+#  A class for GUID Defined Image
+#
+class GuidDefinedImage(Image):
+    _HEADER_ = struct.Struct("1I2H8B 1H 1H")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _GUID_          = struct.Struct("1I2H8B")
+    _DATA_OFFSET_   = struct.Struct("16x 1H")
+    _ATTR_          = struct.Struct("18x 1H")
+
+    CRC32_GUID          = "FC1BCDB0-7D31-49AA-936A-A4600D9DD083"
+    TIANO_COMPRESS_GUID = 'A31280AD-481E-41B6-95E8-127F4C984779'
+    LZMA_COMPRESS_GUID  = 'EE4E5898-3914-4259-9D6E-DC7BD79403CF'
+
+    def __init__(m, SectionDefinitionGuid=None, DataOffset=None, Attributes=None, Data=None):
+        Image.__init__(m)
+        if SectionDefinitionGuid is not None:
+            m.SectionDefinitionGuid = SectionDefinitionGuid
+        if DataOffset is not None:
+            m.DataOffset = DataOffset
+        if Attributes is not None:
+            m.Attributes = Attributes
+        if Data is not None:
+            m.Data = Data
+
+    def __str__(m):
+        S = "guid=%s" % (gGuidStringFormat % m.SectionDefinitionGuid)
+        for Sec in m.Sections:
+            S += "\n" + str(Sec)
+        return S
+
+    def _Unpack(m):
+        # keep header in this Image object
+        m.empty()
+        m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
+        return len(m)
+
+    def _SetAttribute(m, Attribute):
+        m.SetField(m._ATTR_, 0, Attribute)
+
+    def _GetAttribute(m):
+        return m.GetField(m._ATTR_)[0]
+
+    def _SetGuid(m, Guid):
+        m.SetField(m._GUID_, 0, Guid)
+
+    def _GetGuid(m):
+        return m.GetField(m._GUID_)
+
+    def _SetDataOffset(m, Offset):
+        m.SetField(m._DATA_OFFSET_, 0, Offset)
+
+    def _GetDataOffset(m):
+        return m.GetField(m._DATA_OFFSET_)[0]
+
+    def _GetSections(m):
+        SectionList = []
+        Guid = gGuidStringFormat % m.SectionDefinitionGuid
+        if Guid == m.CRC32_GUID:
+            # skip the CRC32 value, we don't do CRC32 verification here
+            Offset = m.DataOffset - 4
+            while Offset < len(m):
+                Sec = Section()
+                try:
+                    Sec.frombuffer(m, Offset)
+                    Offset += Sec.Size
+                    # the section is aligned to 4-byte boundary
+                    Offset = (Offset + 3) & (~3)
+                except:
+                    break
+                SectionList.append(Sec)
+        elif Guid == m.TIANO_COMPRESS_GUID:
+            try:
+                import EfiCompressor
+                # skip the header
+                Offset = m.DataOffset - 4
+                TmpData = EfiCompressor.FrameworkDecompress(m[Offset:], len(m)-Offset)
+                DecData = array('B')
+                DecData.fromstring(TmpData)
+                Offset = 0
+                while Offset < len(DecData):
+                    Sec = Section()
+                    try:
+                        Sec.frombuffer(DecData, Offset)
+                        Offset += Sec.Size
+                        # the section is aligned to 4-byte boundary
+                        Offset = (Offset + 3) & (~3)
+                    except:
+                        break
+                    SectionList.append(Sec)
+            except:
+                pass
+        elif Guid == m.LZMA_COMPRESS_GUID:
+            try:
+                import LzmaCompressor
+                # skip the header
+                Offset = m.DataOffset - 4
+                TmpData = LzmaCompressor.LzmaDecompress(m[Offset:], len(m)-Offset)
+                DecData = array('B')
+                DecData.fromstring(TmpData)
+                Offset = 0
+                while Offset < len(DecData):
+                    Sec = Section()
+                    try:
+                        Sec.frombuffer(DecData, Offset)
+                        Offset += Sec.Size
+                        # the section is aligned to 4-byte boundary
+                        Offset = (Offset + 3) & (~3)
+                    except:
+                        break
+                    SectionList.append(Sec)
+            except:
+                pass
+
+        return SectionList
+
+    Attributes = property(_GetAttribute, _SetAttribute)
+    SectionDefinitionGuid = property(_GetGuid, _SetGuid)
+    DataOffset = property(_GetDataOffset, _SetDataOffset)
+    Sections = property(_GetSections)
+
+## Section() class
+#
+#  A class for Section
+#
+class Section(Image):
+    _TypeName = {
+        0x00    :   "<unknown>",
+        0x01    :   "COMPRESSION",
+        0x02    :   "GUID_DEFINED",
+        0x10    :   "PE32",
+        0x11    :   "PIC",
+        0x12    :   "TE",
+        0x13    :   "DXE_DEPEX",
+        0x14    :   "VERSION",
+        0x15    :   "USER_INTERFACE",
+        0x16    :   "COMPATIBILITY16",
+        0x17    :   "FIRMWARE_VOLUME_IMAGE",
+        0x18    :   "FREEFORM_SUBTYPE_GUID",
+        0x19    :   "RAW",
+        0x1B    :   "PEI_DEPEX"
+    }
+
+    _SectionSubImages = {
+        0x01    :   CompressedImage,
+        0x02    :   GuidDefinedImage,
+        0x17    :   FirmwareVolume,
+        0x13    :   Depex,
+        0x1B    :   Depex,
+        0x15    :   Ui
+    }
+
+    # Size = 3-byte
+    # Type = 1-byte
+    _HEADER_ = struct.Struct("3B 1B")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    # SubTypeGuid
+    # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
+
+    _SIZE_          = struct.Struct("3B")
+    _TYPE_          = struct.Struct("3x 1B")
+
+    def __init__(m, Type=None, Size=None):
+        Image.__init__(m)
+        m._Alignment = 1
+        if Type is not None:
+            m.Type = Type
+        if Size is not None:
+            m.Size = Size
+
+    def __str__(m):
+        global gIndention
+        gIndention += 4
+        SectionInfo = ' ' * gIndention
+        if m.Type in m._TypeName:
+            SectionInfo += "[SECTION:%s] offset=%x size=%x" % (m._TypeName[m.Type], m._OFF_, m.Size)
+        else:
+            SectionInfo += "[SECTION:%x<unknown>] offset=%x size=%x " % (m.Type, m._OFF_, m.Size)
+        for Offset in m._SubImages:
+            SectionInfo += ", " + str(m._SubImages[Offset])
+        gIndention -= 4
+        return SectionInfo
+
+    def _Unpack(m):
+        m.empty()
+        Type, = m._TYPE_.unpack_from(m._BUF_, m._OFF_)
+        Size1, Size2, Size3 = m._SIZE_.unpack_from(m._BUF_, m._OFF_)
+        Size = Size1 + (Size2 << 8) + (Size3 << 16)
+
+        if Type not in m._SectionSubImages:
+            # no need to extract sub-image, keep all in this Image object
+            m.extend(m._BUF_[m._OFF_ : m._OFF_ + Size])
+        else:
+            # keep header in this Image object
+            m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._HEADER_SIZE_])
+            #
+            # use new Image object to represent payload, which may be another kind
+            # of image such as PE32
+            #
+            PayloadOffset = m._HEADER_SIZE_
+            PayloadLen = m.Size - m._HEADER_SIZE_
+            Payload = m._SectionSubImages[m.Type]()
+            Payload.frombuffer(m._BUF_, m._OFF_ + m._HEADER_SIZE_, PayloadLen)
+            m._SubImages[PayloadOffset] = Payload
+
+        return Size
+
+    def _SetSize(m, Size):
+        Size1 = Size & 0xFF
+        Size2 = (Size & 0xFF00) >> 8
+        Size3 = (Size & 0xFF0000) >> 16
+        m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
+
+    def _GetSize(m):
+        Size1, Size2, Size3 = m.GetField(m._SIZE_)
+        return Size1 + (Size2 << 8) + (Size3 << 16)
+
+    def _SetType(m, Type):
+        m.SetField(m._TYPE_, 0, Type)
+
+    def _GetType(m):
+        return m.GetField(m._TYPE_)[0]
+
+    def _GetAlignment(m):
+        return m._Alignment
+
+    def _SetAlignment(m, Alignment):
+        m._Alignment = Alignment
+        AlignmentMask = Alignment - 1
+        # section alignment is actually for payload, so we need to add header size
+        PayloadOffset = m._OFF_ + m._HEADER_SIZE_
+        if (PayloadOffset & (~AlignmentMask)) == 0:
+            return
+        NewOffset = (PayloadOffset + AlignmentMask) & (~AlignmentMask)
+        while (NewOffset - PayloadOffset) < m._HEADER_SIZE_:
+            NewOffset += m._Alignment
+
+    def tofile(m, f):
+        m.Size = len(m)
+        Image.tofile(m, f)
+        for Offset in m._SubImages:
+            m._SubImages[Offset].tofile(f)
+
+    Type = property(_GetType, _SetType)
+    Size = property(_GetSize, _SetSize)
+    Alignment = property(_GetAlignment, _SetAlignment)
+
+## Ffs() class
+#
+#  A class for Ffs Section
+#
+class Ffs(Image):
+    _FfsFormat = "24B%(payload_size)sB"
+    # skip IntegrityCheck
+    _HEADER_ = struct.Struct("1I2H8B 2x 1B 1B 3B 1B")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _NAME_      = struct.Struct("1I2H8B")
+    _INT_CHECK_ = struct.Struct("16x 1H")
+    _TYPE_      = struct.Struct("18x 1B")
+    _ATTR_      = struct.Struct("19x 1B")
+    _SIZE_      = struct.Struct("20x 3B")
+    _STATE_     = struct.Struct("23x 1B")
+
+    VTF_GUID = "1BA0062E-C779-4582-8566-336AE8F78F09"
+
+    FFS_ATTRIB_FIXED              = 0x04
+    FFS_ATTRIB_DATA_ALIGNMENT     = 0x38
+    FFS_ATTRIB_CHECKSUM           = 0x40
+
+    _TypeName = {
+        0x00    :   "<unknown>",
+        0x01    :   "RAW",
+        0x02    :   "FREEFORM",
+        0x03    :   "SECURITY_CORE",
+        0x04    :   "PEI_CORE",
+        0x05    :   "DXE_CORE",
+        0x06    :   "PEIM",
+        0x07    :   "DRIVER",
+        0x08    :   "COMBINED_PEIM_DRIVER",
+        0x09    :   "APPLICATION",
+        0x0A    :   "SMM",
+        0x0B    :   "FIRMWARE_VOLUME_IMAGE",
+        0x0C    :   "COMBINED_SMM_DXE",
+        0x0D    :   "SMM_CORE",
+        0x0E    :   "MM_STANDALONE",
+        0x0F    :   "MM_CORE_STANDALONE",
+        0xc0    :   "OEM_MIN",
+        0xdf    :   "OEM_MAX",
+        0xe0    :   "DEBUG_MIN",
+        0xef    :   "DEBUG_MAX",
+        0xf0    :   "FFS_MIN",
+        0xff    :   "FFS_MAX",
+        0xf0    :   "FFS_PAD",
+    }
+
+    def __init__(self):
+        Image.__init__(self)
+        self.FreeSpace = 0
+
+        self.Sections = sdict()
+        self.Depex = ''
+
+        self.__ID__ = None
+
+    def __str__(self):
+        global gIndention
+        gIndention += 4
+        Indention = ' ' * gIndention
+        FfsInfo = Indention
+        FfsInfo +=  "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
+                    (Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment)
+        SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections])
+        gIndention -= 4
+        return FfsInfo + SectionInfo + "\n"
+
+    def __len__(self):
+        return self.Size
+
+    def __repr__(self):
+        return self.__ID__
+
+    def _Unpack(self):
+        Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_)
+        Size = Size1 + (Size2 << 8) + (Size3 << 16)
+        self.empty()
+        self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size])
+
+        # Pad FFS may use the same GUID. We need to avoid it.
+        if self.Type == 0xf0:
+            self.__ID__ = str(uuid.uuid1()).upper()
+        else:
+            self.__ID__ = self.Guid
+
+        # Traverse the SECTION. RAW and PAD do not have sections
+        if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF:
+            EndOfFfs = Size
+            SectionStartAddress = self._HEADER_SIZE_
+            while SectionStartAddress < EndOfFfs:
+                SectionObj = Section()
+                SectionObj.frombuffer(self, SectionStartAddress)
+                #f = open(repr(SectionObj), 'wb')
+                #SectionObj.Size = 0
+                #SectionObj.tofile(f)
+                #f.close()
+                self.Sections[SectionStartAddress] = SectionObj
+                SectionStartAddress += len(SectionObj)
+                SectionStartAddress = (SectionStartAddress + 3) & (~3)
+
+    def Pack(self):
+        pass
+
+    def SetFreeSpace(self, Size):
+        self.FreeSpace = Size
+
+    def _GetGuid(self):
+        return gGuidStringFormat % self.Name
+
+    def _SetName(self, Value):
+        # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
+        self.SetField(self._NAME_, 0, Value)
+
+    def _GetName(self):
+        # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
+        return self.GetField(self._NAME_)
+
+    def _SetSize(m, Size):
+        Size1 = Size & 0xFF
+        Size2 = (Size & 0xFF00) >> 8
+        Size3 = (Size & 0xFF0000) >> 16
+        m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
+
+    def _GetSize(m):
+        Size1, Size2, Size3 = m.GetField(m._SIZE_)
+        return Size1 + (Size2 << 8) + (Size3 << 16)
+
+    def _SetType(m, Type):
+        m.SetField(m._TYPE_, 0, Type)
+
+    def _GetType(m):
+        return m.GetField(m._TYPE_)[0]
+
+    def _SetAttributes(self, Value):
+        self.SetField(m._ATTR_, 0, Value)
+
+    def _GetAttributes(self):
+        return self.GetField(self._ATTR_)[0]
+
+    def _GetFixed(self):
+        if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0:
+            return True
+        return False
+
+    def _GetCheckSum(self):
+        if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0:
+            return True
+        return False
+
+    def _GetAlignment(self):
+        return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3
+
+    def _SetState(self, Value):
+        self.SetField(m._STATE_, 0, Value)
+
+    def _GetState(self):
+        return self.GetField(m._STATE_)[0]
+
+    Name = property(_GetName, _SetName)
+    Guid = property(_GetGuid)
+    Type = property(_GetType, _SetType)
+    Size = property(_GetSize, _SetSize)
+    Attributes = property(_GetAttributes, _SetAttributes)
+    Fixed = property(_GetFixed)
+    Checksum = property(_GetCheckSum)
+    Alignment = property(_GetAlignment)
+    State = property(_GetState, _SetState)
+
+## FirmwareVolume() class
+#
+#  A class for Firmware Volume
+#
+class FirmwareVolume(Image):
+    # Read FvLength, Attributes, HeaderLength, Checksum
+    _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
+    _HEADER_SIZE_ = _HEADER_.size
+
+    _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
+
+    _GUID_      = struct.Struct("16x 1I2H8B")
+    _LENGTH_    = struct.Struct("16x 16x 1Q")
+    _SIG_       = struct.Struct("16x 16x 8x 1I")
+    _ATTR_      = struct.Struct("16x 16x 8x 4x 1I")
+    _HLEN_      = struct.Struct("16x 16x 8x 4x 4x 1H")
+    _CHECKSUM_  = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
+
+    def __init__(self, Name=''):
+        Image.__init__(self)
+        self.Name = Name
+        self.FfsDict = sdict()
+        self.OrderedFfsDict = sdict()
+        self.UnDispatchedFfsDict = sdict()
+        self.ProtocolList = sdict()
+
+    def CheckArchProtocol(self):
+        for Item in EotGlobalData.gArchProtocolGuids:
+            if Item.lower() not in EotGlobalData.gProtocolList:
+
+                return False
+
+        return True
+
+    def ParseDepex(self, Depex, Type):
+        List = None
+        if Type == 'Ppi':
+            List = EotGlobalData.gPpiList
+        if Type == 'Protocol':
+            List = EotGlobalData.gProtocolList
+        DepexStack = []
+        DepexList = []
+        DepexString = ''
+        FileDepex = None
+        CouldBeLoaded = True
+        for Index in range(0, len(Depex.Expression)):
+            Item = Depex.Expression[Index]
+            if Item == 0x00:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
+            elif Item == 0x01:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
+                    return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
+            elif Item == 0x02:
+                Index = Index + 1
+                Guid = gGuidStringFormat % Depex.Expression[Index]
+                if Guid.lower() in List:
+                    DepexStack.append(True)
+                    DepexList.append(Guid)
+                else:
+                    DepexStack.append(False)
+                    DepexList.append(Guid)
+                continue
+            elif Item == 0x03 or Item == 0x04:
+                DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
+            elif Item == 0x05:
+                DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
+                DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
+            elif Item == 0x06:
+                DepexStack.append(True)
+                DepexList.append('TRUE')
+                DepexString = DepexString + 'TRUE' + ' '
+            elif Item == 0x07:
+                DepexStack.append(False)
+                DepexList.append('False')
+                DepexString = DepexString + 'FALSE' + ' '
+            elif Item == 0x08:
+                if Index != len(Depex.Expression) - 1:
+                    CouldBeLoaded = False
+                else:
+                    CouldBeLoaded = DepexStack.pop()
+            else:
+                CouldBeLoaded = False
+        if DepexList != []:
+            DepexString = DepexList[0].strip()
+        return (CouldBeLoaded, DepexString, FileDepex)
+
+    def Dispatch(self, Db = None):
+        if Db is None:
+            return False
+        self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
+        # Find PeiCore, DexCore, PeiPriori, DxePriori first
+        FfsSecCoreGuid = None
+        FfsPeiCoreGuid = None
+        FfsDxeCoreGuid = None
+        FfsPeiPrioriGuid = None
+        FfsDxePrioriGuid = None
+        for FfsID in self.UnDispatchedFfsDict:
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x03:
+                FfsSecCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x04:
+                FfsPeiCoreGuid = FfsID
+                continue
+            if Ffs.Type == 0x05:
+                FfsDxeCoreGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
+                FfsPeiPrioriGuid = FfsID
+                continue
+            if Ffs.Guid.lower() == gAprioriGuid:
+                FfsDxePrioriGuid = FfsID
+                continue
+
+        # Parse SEC_CORE first
+        if FfsSecCoreGuid is not None:
+            self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
+            self.LoadPpi(Db, FfsSecCoreGuid)
+
+        # Parse PEI first
+        if FfsPeiCoreGuid is not None:
+            self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
+            self.LoadPpi(Db, FfsPeiCoreGuid)
+            if FfsPeiPrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
+                if len(FfsPeiPriori.Sections) == 1:
+                    Section = FfsPeiPriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadPpi(Db, GuidString)
+
+        self.DisPatchPei(Db)
+
+        # Parse DXE then
+        if FfsDxeCoreGuid is not None:
+            self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
+            self.LoadProtocol(Db, FfsDxeCoreGuid)
+            if FfsDxePrioriGuid is not None:
+                # Load PEIM described in priori file
+                FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
+                if len(FfsDxePriori.Sections) == 1:
+                    Section = FfsDxePriori.Sections.popitem()[1]
+                    if Section.Type == 0x19:
+                        GuidStruct = struct.Struct('1I2H8B')
+                        Start = 4
+                        while len(Section) > Start:
+                            Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
+                            GuidString = gGuidStringFormat % Guid
+                            Start = Start + 16
+                            if GuidString in self.UnDispatchedFfsDict:
+                                self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
+                                self.LoadProtocol(Db, GuidString)
+
+        self.DisPatchDxe(Db)
+
+    def LoadProtocol(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            SqlCommand = """select Value2 from Inf where BelongsToFile =
+                            (select DISTINCT BelongsToFile from Inf
+                            where Value1 =
+                            (select SourceFileFullPath from Report
+                            where GuidValue like '%s' and ItemMode = 'Callback'))
+                            and Value1 = 'FILE_GUID'""" % Record[0]
+            CallBackSet = Db.TblReport.Exec(SqlCommand)
+            if CallBackSet != []:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+            else:
+                EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
+
+    def LoadPpi(self, Db, ModuleGuid):
+        SqlCommand = """select GuidValue from Report
+                        where SourceFileFullPath in
+                        (select Value1 from Inf where BelongsToFile =
+                        (select BelongsToFile from Inf
+                        where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
+                        and Model = %s)
+                        and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
+                        % (ModuleGuid, 5001, 3007)
+        RecordSet = Db.TblReport.Exec(SqlCommand)
+        for Record in RecordSet:
+            EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
+
+    def DisPatchDxe(self, Db):
+        IsInstalled = False
+        ScheduleList = sdict()
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = False
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x07:
+                # Get Depex
+                IsFoundDepex = False
+                for Section in Ffs.Sections.values():
+                    # Find Depex
+                    if Section.Type == 0x13:
+                        IsFoundDepex = True
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
+                        break
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x13:
+                                IsFoundDepex = True
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x13:
+                                        IsFoundDepex = True
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
+                                        break
+
+                # Not find Depex
+                if not IsFoundDepex:
+                    CouldBeLoaded = self.CheckArchProtocol()
+                    DepexString = ''
+                    FileDepex = None
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    if FileDepex is not None:
+                        ScheduleList.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
+                    else:
+                        ScheduleList[FfsID] = NewFfs
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        for FfsID in ScheduleList:
+            NewFfs = ScheduleList.pop(FfsID)
+            FfsName = 'UnKnown'
+            self.OrderedFfsDict[FfsID] = NewFfs
+            self.LoadProtocol(Db, FfsID)
+
+            SqlCommand = """select Value2 from Inf
+                            where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
+                            and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
+            RecordSet = Db.TblReport.Exec(SqlCommand)
+            if RecordSet != []:
+                FfsName = RecordSet[0][0]
+
+        if IsInstalled:
+            self.DisPatchDxe(Db)
+
+    def DisPatchPei(self, Db):
+        IsInstalled = False
+        for FfsID in self.UnDispatchedFfsDict:
+            CouldBeLoaded = True
+            DepexString = ''
+            FileDepex = None
+            Ffs = self.UnDispatchedFfsDict[FfsID]
+            if Ffs.Type == 0x06 or Ffs.Type == 0x08:
+                # Get Depex
+                for Section in Ffs.Sections.values():
+                    if Section.Type == 0x1B:
+                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
+                        break
+
+                    if Section.Type == 0x01:
+                        CompressSections = Section._SubImages[4]
+                        for CompressSection in CompressSections.Sections:
+                            if CompressSection.Type == 0x1B:
+                                CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
+                                break
+                            if CompressSection.Type == 0x02:
+                                NewSections = CompressSection._SubImages[4]
+                                for NewSection in NewSections.Sections:
+                                    if NewSection.Type == 0x1B:
+                                        CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
+                                        break
+
+                # Append New Ffs
+                if CouldBeLoaded:
+                    IsInstalled = True
+                    NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
+                    NewFfs.Depex = DepexString
+                    self.OrderedFfsDict[FfsID] = NewFfs
+                    self.LoadPpi(Db, FfsID)
+                else:
+                    self.UnDispatchedFfsDict[FfsID].Depex = DepexString
+
+        if IsInstalled:
+            self.DisPatchPei(Db)
+
+
+    def __str__(self):
+        global gIndention
+        gIndention += 4
+        FvInfo = '\n' + ' ' * gIndention
+        FvInfo +=  "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
+        FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
+        gIndention -= 4
+        return FvInfo + FfsInfo
+
+    def _Unpack(self):
+        Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
+        self.empty()
+        self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
+
+        # traverse the FFS
+        EndOfFv = Size
+        FfsStartAddress = self.HeaderSize
+        LastFfsObj = None
+        while FfsStartAddress < EndOfFv:
+            FfsObj = Ffs()
+            FfsObj.frombuffer(self, FfsStartAddress)
+            FfsId = repr(FfsObj)
+            if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
+                or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
+            else:
+                if FfsId in self.FfsDict:
+                    EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
+                                    ExtraData="\t%s @ %s\n\t%s @ %s" \
+                                    % (FfsObj.Guid, FfsObj.Offset,
+                                       self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
+                self.FfsDict[FfsId] = FfsObj
+                if LastFfsObj is not None:
+                    LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
+
+            FfsStartAddress += len(FfsObj)
+            #
+            # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
+            # The next FFS must be at the latest next 8-byte aligned address
+            #
+            FfsStartAddress = (FfsStartAddress + 7) & (~7)
+            LastFfsObj = FfsObj
+
+    def _GetAttributes(self):
+        return self.GetField(self._ATTR_, 0)[0]
+
+    def _GetSize(self):
+        return self.GetField(self._LENGTH_, 0)[0]
+
+    def _GetChecksum(self):
+        return self.GetField(self._CHECKSUM_, 0)[0]
+
+    def _GetHeaderLength(self):
+        return self.GetField(self._HLEN_, 0)[0]
+
+    def _GetFileSystemGuid(self):
+        return gGuidStringFormat % self.GetField(self._GUID_, 0)
+
+    Attributes = property(_GetAttributes)
+    Size = property(_GetSize)
+    Checksum = property(_GetChecksum)
+    HeaderSize = property(_GetHeaderLength)
+    FileSystemGuid = property(_GetFileSystemGuid)
 
 ## MultipleFv() class
 #
@@ -390,6 +1830,8 @@ class Eot(object):
         SqlCommand = """select DISTINCT GuidValue, ItemType from Report where ModuleID = -2 and ItemMode = 'Produced'"""
         RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
         for Record in RecordSet:
+            if Record[1] == 'Ppi':
+                EotGlobalData.gPpiList[Record[0].lower()] = -2
             if Record[1] == 'Protocol':
                 EotGlobalData.gProtocolList[Record[0].lower()] = -2
 
diff --git a/BaseTools/Source/Python/Eot/EotGlobalData.py b/BaseTools/Source/Python/Eot/EotGlobalData.py
index a9f51189c1eb..cb6a940ab8f9 100644
--- a/BaseTools/Source/Python/Eot/EotGlobalData.py
+++ b/BaseTools/Source/Python/Eot/EotGlobalData.py
@@ -65,6 +65,9 @@ gGuidDict = dict()
 
 # Dict for PROTOCOL
 gProtocolList = {}
+# Dict for PPI
+gPpiList = {}
+
 
 # Dict for consumed PPI function calling
 gConsumedPpiLibrary = OrderedDict()
@@ -92,3 +95,17 @@ gConsumedProtocolLibrary['EfiHandleProtocol'] = 1
 # Dict for callback PROTOCOL function callling
 gCallbackProtocolLibrary = OrderedDict()
 gCallbackProtocolLibrary['EfiRegisterProtocolCallback'] = 2
+
+gArchProtocolGuids = {'665e3ff6-46cc-11d4-9a38-0090273fc14d',
+                      '26baccb1-6f42-11d4-bce7-0080c73c8881',
+                      '26baccb2-6f42-11d4-bce7-0080c73c8881',
+                      '1da97072-bddc-4b30-99f1-72a0b56fff2a',
+                      '27cfac87-46cc-11d4-9a38-0090273fc14d',
+                      '27cfac88-46cc-11d4-9a38-0090273fc14d',
+                      'b7dfb4e1-052f-449f-87be-9818fc91b733',
+                      'a46423e3-4617-49f1-b9ff-d1bfa9115839',
+                      'd2b2b828-0826-48a7-b3df-983c006024f0',
+                      '26baccb3-6f42-11d4-bce7-0080c73c8881',
+                      '1e5668e2-8481-11d4-bcf1-0080c73c8881',
+                      '6441f818-6362-4e44-b570-7dba31dd2453',
+                      '665e3ff5-46cc-11d4-9a38-0090273fc14d'}
-- 
2.16.2.windows.1



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-05-28  1:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1527171329.git.jaben.carsey@intel.com>
2018-05-24 14:17 ` [PATCH v1 1/1] BaseTools: Add missing content to EOT tool Jaben Carsey
2018-05-28  1:16   ` Zhu, Yonghong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox