public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [Patch V1 3/3] BaseTools: FMMT support ELF UPLD parser
@ 2023-04-18  9:55 Yuwei Chen
  2023-06-05  9:19 ` Bob Feng
  0 siblings, 1 reply; 3+ messages in thread
From: Yuwei Chen @ 2023-04-18  9:55 UTC (permalink / raw)
  To: devel; +Cc: Rebecca Cran, Bob Feng, Liming Gao

FMMT add new function to support the .elf file parsing.
Using '-v' option, the UPLD info will be printed out.

'''
- UNIVERSAL_PAYLOAD_INFO
  - 4 bytes align (BOOLEAN)
    - Identifier
    - SpecRevision
    - Attribute
    - Revision
    - Capability
    - ProducerId
    - ImageId
UPLD Buffer
'''

Cc: Rebecca Cran <rebecca@bsdio.com>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Signed-off-by: Yuwei Chen <yuwei.chen@intel.com>
---
 BaseTools/Source/Python/FMMT/FMMT.py                       |   2 ++
 BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py  |  36 +++++++++++++++++++++++++++++++++++-
 BaseTools/Source/Python/FMMT/core/BiosTree.py              |  48 ++++++++++++++++++++++++++++++++++++++++++++++--
 BaseTools/Source/Python/FMMT/core/BiosTreeNode.py          |  56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 BaseTools/Source/Python/FMMT/core/FMMTParser.py            |   2 +-
 BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 383 insertions(+), 5 deletions(-)

diff --git a/BaseTools/Source/Python/FMMT/FMMT.py b/BaseTools/Source/Python/FMMT/FMMT.py
index bf580b3843..26fc4c5792 100644
--- a/BaseTools/Source/Python/FMMT/FMMT.py
+++ b/BaseTools/Source/Python/FMMT/FMMT.py
@@ -84,6 +84,8 @@ class FMMT():
             ROOT_TYPE = ROOT_FFS_TREE
         elif filetype == '.sec':
             ROOT_TYPE = ROOT_SECTION_TREE
+        elif filetype == '.elf':
+            ROOT_TYPE = ROOT_ELF_TREE
         else:
             ROOT_TYPE = ROOT_TREE
         ViewFile(inputfile, ROOT_TYPE, layoutfilename, outputfile)
diff --git a/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py b/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
index 2d4e6d9276..de174f26ab 100644
--- a/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
+++ b/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
@@ -15,10 +15,13 @@ from core.GuidTools import GUIDTools
 from utils.FmmtLogger import FmmtLogger as logger
 
 ROOT_TREE = 'ROOT'
+ROOT_ELF_TREE = 'ROOT_ELF_TREE'
 ROOT_FV_TREE = 'ROOT_FV_TREE'
 ROOT_FFS_TREE = 'ROOT_FFS_TREE'
 ROOT_SECTION_TREE = 'ROOT_SECTION_TREE'
 
+ELF_TREE = 'ELF'
+ELF_SECTION_TREE = 'ELF_SECTION_TREE'
 FV_TREE = 'FV'
 DATA_FV_TREE = 'DATA_FV'
 FFS_TREE = 'FFS'
@@ -49,6 +52,12 @@ class BinaryProduct():
     def ParserData():
         pass
 
+class ElfFactory(BinaryFactory):
+    type = [ROOT_ELF_TREE, ELF_TREE]
+
+    def Create_Product():
+        return ElfProduct()
+
 class SectionFactory(BinaryFactory):
     type = [SECTION_TREE]
 
@@ -354,6 +363,30 @@ class FdProduct(BinaryProduct):
                 tmp_index += 1
         return Fd_Struct
 
+class ElfSectionProduct(BinaryProduct):
+    ## Decompress the compressed section.
+    def ParserData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        pass
+    def ParserSectionData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        pass
+    def ParserProgramData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        pass
+
+class ElfProduct(BinaryProduct):
+
+    def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        Elf_Info = ElfNode(Whole_Data)
+        if Elf_Info.Header.ELF_PHOff != 0:
+            Elf_Info.GetProgramList(Whole_Data[Elf_Info.Header.ELF_PHOff:])
+        if Elf_Info.Header.ELF_SHOff != 0:
+            Elf_Info.GetSectionList(Whole_Data[Elf_Info.Header.ELF_SHOff:])
+            Elf_Info.FindUPLDSection(Whole_Data)
+        Elf_Tree = BIOSTREE(Elf_Info.Name)
+        Elf_Tree.type = ELF_TREE
+        Elf_Info.Data = Whole_Data[Elf_Info.HeaderLength:]
+        Elf_Tree.Data = Elf_Info
+        ParTree.insertChild(Elf_Tree)
+
 class ParserEntry():
     FactoryTable:dict = {
         SECTION_TREE: SectionFactory,
@@ -364,6 +397,7 @@ class ParserEntry():
         SEC_FV_TREE: FvFactory,
         ROOT_FV_TREE: FdFactory,
         ROOT_TREE: FdFactory,
+        ROOT_ELF_TREE: ElfFactory,
     }
 
     def GetTargetFactory(self, Tree_type: str) -> BinaryFactory:
@@ -377,4 +411,4 @@ class ParserEntry():
     def DataParser(self, Tree, Data: bytes, Offset: int) -> None:
         TargetFactory = self.GetTargetFactory(Tree.type)
         if TargetFactory:
-            self.Generate_Product(TargetFactory, Tree, Data, Offset)
\ No newline at end of file
+            self.Generate_Product(TargetFactory, Tree, Data, Offset)
diff --git a/BaseTools/Source/Python/FMMT/core/BiosTree.py b/BaseTools/Source/Python/FMMT/core/BiosTree.py
index 137f49748b..c5a7b017f4 100644
--- a/BaseTools/Source/Python/FMMT/core/BiosTree.py
+++ b/BaseTools/Source/Python/FMMT/core/BiosTree.py
@@ -12,6 +12,7 @@ ROOT_TREE = 'ROOT'
 ROOT_FV_TREE = 'ROOT_FV_TREE'
 ROOT_FFS_TREE = 'ROOT_FFS_TREE'
 ROOT_SECTION_TREE = 'ROOT_SECTION_TREE'
+ROOT_ELF_TREE = 'ROOT_ELF_TREE'
 
 FV_TREE = 'FV'
 DATA_FV_TREE = 'DATA_FV'
@@ -21,11 +22,13 @@ FFS_FREE_SPACE = 'FFS_FREE_SPACE'
 SECTION_TREE = 'SECTION'
 SEC_FV_TREE = 'SEC_FV_IMAGE'
 BINARY_DATA = 'BINARY'
+ELF_TREE = 'ELF'
 
 RootType = [ROOT_TREE, ROOT_FV_TREE, ROOT_FFS_TREE, ROOT_SECTION_TREE]
 FvType = [FV_TREE, SEC_FV_TREE]
 FfsType = FFS_TREE
 SecType = SECTION_TREE
+ElfType = [ROOT_ELF_TREE, ELF_TREE]
 
 class BIOSTREE:
     def __init__(self, NodeName: str) -> None:
@@ -118,6 +121,31 @@ class BIOSTREE:
             Info.append("Image File: {}".format(Key))
             Info.append("FilesNum: {}".format(TargetDict.get(Key).get('FilesNum')))
             Info.append("\n")
+        elif TargetDict[Key]["Type"] == ROOT_ELF_TREE:
+            Info.append("ELF File: {}\n".format(Key))
+        elif TargetDict[Key]["Type"] == ELF_TREE:
+            ProducerId = ""
+            ImageId = ""
+            if TargetDict.get(Key).get('IfExist'):
+                Identifier = TargetDict.get(Key).get('Identifier')
+                for item in TargetDict.get(Key).get('ProducerId'):
+                    ProducerId += chr(item)
+                for item in TargetDict.get(Key).get('ImageId'):
+                    ImageId += chr(item)
+                Info.append("- UNIVERSAL_PAYLOAD_INFO")
+                Info.append("  - 4 bytes align: {}".format(TargetDict.get(Key).get('Upld_Info_Align')))
+                Info.append("    - Identifier: {}  # 0x48444c50--PLDH / 0x444c5055--UPLD".format(hex(Identifier)))
+                Info.append("    - SpecRevision: {}".format(hex(TargetDict.get(Key).get('SpecRevision'))))
+                Info.append("    - Attribute: {}".format(hex(TargetDict.get(Key).get('Attribute'))))
+                Info.append("    - Revision: {}".format(hex(TargetDict.get(Key).get('Revision'))))
+                Info.append("    - Capability: {}".format(hex(TargetDict.get(Key).get('Capability'))))
+                Info.append("    - ProducerId: {}".format(ProducerId))
+                Info.append("    - ImageId: {}".format(ImageId))
+                Info.append("\n")
+                Info.append("- UPLD buffer")
+                Info.append("  Buffer: {}".format(TargetDict.get(Key).get('Upld_Buffer')))
+            else:
+                print("Do not find the Upld Info section!!!\n")
         elif TargetDict[Key]["Type"] in FvType:
             space += 2
             if TargetDict[Key]["Type"] == SEC_FV_TREE:
@@ -146,13 +174,29 @@ class BIOSTREE:
         if TreeInfo is None:
             TreeInfo =collections.OrderedDict()
 
-        if self.type == ROOT_TREE or self.type == ROOT_FV_TREE or self.type == ROOT_FFS_TREE or self.type == ROOT_SECTION_TREE:
+        if self.type == ROOT_TREE or self.type == ROOT_FV_TREE or self.type == ROOT_FFS_TREE or self.type == ROOT_SECTION_TREE or self.type == ROOT_ELF_TREE:
             key = str(self.key)
             TreeInfo[self.key] = collections.OrderedDict()
             TreeInfo[self.key]["Name"] = key
             TreeInfo[self.key]["Type"] = self.type
             TreeInfo[self.key]["FilesNum"] = len(self.Child)
-        elif self.type == FV_TREE or  self.type == SEC_FV_TREE:
+        elif self.type == ELF_TREE:
+            key = str(self.Data.Name)
+            TreeInfo[key] = collections.OrderedDict()
+            TreeInfo[key]["Name"] = key
+            TreeInfo[key]["Type"] = self.type
+            TreeInfo[key]["IfExist"] = self.Data.UpldInfo
+            if self.Data.UpldInfo:
+                TreeInfo[key]["Identifier"] = self.Data.UpldInfo.Identifier
+                TreeInfo[key]["SpecRevision"] = self.Data.UpldInfo.SpecRevision
+                TreeInfo[key]["Attribute"] = self.Data.UpldInfo.Attribute
+                TreeInfo[key]["Revision"] = self.Data.UpldInfo.Revision
+                TreeInfo[key]["Capability"] = self.Data.UpldInfo.Capability
+                TreeInfo[key]["ProducerId"] = self.Data.UpldInfo.ProducerId
+                TreeInfo[key]["ImageId"] = self.Data.UpldInfo.ImageId
+                TreeInfo[key]["Upld_Info_Align"] = self.Data.Upld_Info_Align
+                TreeInfo[key]["Upld_Buffer"] = self.Data.UpldBuffer
+        elif self.type == FV_TREE or self.type == SEC_FV_TREE:
             key = str(self.Data.FvId)
             TreeInfo[key] = collections.OrderedDict()
             TreeInfo[key]["Name"] = key
diff --git a/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py b/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
index 20447766c8..5ca4c20dc6 100644
--- a/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
+++ b/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
@@ -4,6 +4,7 @@
 # Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
+from FirmwareStorageFormat.UPLHeader import *
 from FirmwareStorageFormat.FvHeader import *
 from FirmwareStorageFormat.FfsFileHeader import *
 from FirmwareStorageFormat.SectionHeader import *
@@ -37,6 +38,59 @@ class BinaryNode:
         self.HOffset = 0
         self.Data = b''
 
+class ElfNode:
+    def __init__(self, buffer: bytes) -> None:
+        self.Header = ELF_HEADER32.from_buffer_copy(buffer)
+        if self.Header.ELF_Identification[0:4] != b'\x7fELF':
+            logger.error('Invalid Elf Header! Elf Identification {} is not ".ELF".'.format(self.Header.ELF_Identification))
+            raise Exception("Process Failed: Invalid ELF Header Identification!")
+        self.Class = self.Header.ELF_Identification[4]
+        if self.Class == 0x02:
+            self.Header = ELF_HEADER64.from_buffer_copy(buffer)
+        elif self.Class != 0x01:
+            logger.error('Invalid Elf Class! Elf Class {} is not 0x01 or 0x02.'.format(self.Class))
+            raise Exception("Process Failed: Invalid ELF Class!")
+
+        self.ProList = []
+        self.SecList = []
+        self.UpldInfoSection = None
+        self.UpldInfo = None
+        self.UpldBuffer = b''
+        self.Name = "ELF"
+        self.HeaderLength = len(struct2stream(self.Header))
+        self.HOffset = 0
+        self.DOffset = 0
+        self.ROffset = 0
+        self.Data = b''
+        self.PadData = b''
+        self.Upld_Info_Align = False
+
+    def GetProgramList(self, buffer: bytes) -> None:
+        for i in range(self.Header.ELF_PHNum):
+            if self.Class == 0x01:
+                ElfProgramHeader = ELF_PROGRAM_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
+            elif self.Class == 0x02:
+                ElfProgramHeader = ELF_PROGRAM_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
+            self.ProList.append(ElfProgramHeader)
+
+    def GetSectionList(self, buffer: bytes) -> None:
+        for i in range(self.Header.ELF_SHNum):
+            if self.Class == 0x01:
+                ElfSectionHeader = ELF_SECTION_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
+            elif self.Class == 0x02:
+                ElfSectionHeader = ELF_SECTION_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
+            self.SecList.append(ElfSectionHeader)
+
+    def FindUPLDSection(self, buffer: bytes) -> None:
+        for item in self.SecList:
+            if buffer[item.SH_Offset:item.SH_Offset+4] == b'PLDH' or buffer[item.SH_Offset:item.SH_Offset+4] == b'UPLD':
+                self.UpldInfoSection = item
+                self.UpldInfo = UNIVERSAL_PAYLOAD_INFO.from_buffer_copy(buffer[item.SH_Offset:item.SH_Offset+item.SH_Size])
+                self.UpldBuffer = struct2stream(self.UpldInfo)
+                if (self.UpldInfoSection.SH_Offset) % 4 == 0:
+                # if (self.UpldInfoSection.SH_Offset - self.Header.ELF_Entry) % 4 == 0:
+                    self.Upld_Info_Align = True
+
 class FvNode:
     def __init__(self, name, buffer: bytes) -> None:
         self.Header = EFI_FIRMWARE_VOLUME_HEADER.from_buffer_copy(buffer)
@@ -191,4 +245,4 @@ class FreeSpaceNode:
         self.HOffset = 0
         self.DOffset = 0
         self.ROffset = 0
-        self.PadData = b''
\ No newline at end of file
+        self.PadData = b''
diff --git a/BaseTools/Source/Python/FMMT/core/FMMTParser.py b/BaseTools/Source/Python/FMMT/core/FMMTParser.py
index e76ac51185..25a2bde799 100644
--- a/BaseTools/Source/Python/FMMT/core/FMMTParser.py
+++ b/BaseTools/Source/Python/FMMT/core/FMMTParser.py
@@ -20,7 +20,7 @@ class FMMTParser:
 
     ## Parser the nodes in WholeTree.
     def ParserFromRoot(self, WholeFvTree=None, whole_data: bytes=b'', Reloffset: int=0) -> None:
-        if WholeFvTree.type == ROOT_TREE or WholeFvTree.type == ROOT_FV_TREE:
+        if WholeFvTree.type == ROOT_TREE or WholeFvTree.type == ROOT_FV_TREE or WholeFvTree.type == ROOT_ELF_TREE:
             ParserEntry().DataParser(self.WholeFvTree, whole_data, Reloffset)
         else:
             ParserEntry().DataParser(WholeFvTree, whole_data, Reloffset)
diff --git a/BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py b/BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py
new file mode 100644
index 0000000000..c57852e741
--- /dev/null
+++ b/BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py
@@ -0,0 +1,244 @@
+## @file
+# This file is used to define the UPL Header C Struct.
+#
+# Copyright (c) 2023-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+from struct import *
+from ctypes import *
+from FirmwareStorageFormat.Common import *
+
+EFI_COMMON_SECTION_HEADER_LEN = 4
+EFI_COMMON_SECTION_HEADER2_LEN = 8
+
+# ELF header.
+class ELF_HEADER32(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Identification',       ARRAY(c_char, 16)),   # /* File identification. */
+        ('ELF_Type',                 c_uint16),            # Elf32_Half   /* File type. */
+        ('ELF_Machine',              c_uint16),            # Elf32_Half   /* Machine architecture. */
+        ('ELF_Version',              c_uint32),            # Elf32_Word   /* ELF format version. */
+        ('ELF_Entry',                c_uint32),            # Elf32_Addr   /* Entry point. */
+        ('ELF_PHOff',                c_uint32),            # Elf32_Off    /* Program header file offset. */
+        ('ELF_SHOff',                c_uint32),            # Elf32_Off    /* Section header file offset. */
+        ('ELF_Flags',                c_uint32),            # Elf32_Word   /* Architecture-specific flags. */
+        ('ELF_EFSize',               c_uint16),            # Elf32_Half   /* Size of ELF header in bytes. */
+        ('ELF_PHEntSize',            c_uint16),            # Elf32_Half   /* Size of program header entry. */
+        ('ELF_PHNum',                c_uint16),            # Elf32_Half   /* Number of program header entries. */
+        ('ELF_SHEntSize',            c_uint16),            # Elf32_Half   /* Size of section header entry. */
+        ('ELF_SHNum',                c_uint16),            # Elf32_Half   /* Number of section header entries. */
+        ('ELF_SNStr',                c_uint16),            # Elf32_Half   /* Section name strings section. */
+    ]
+
+class ELF_HEADER64(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Identification',       ARRAY(c_char, 16)),   # /* File identification. */
+        ('ELF_Type',                 c_uint16),            # Elf64_Half   /* File type. */
+        ('ELF_Machine',              c_uint16),            # Elf64_Half   /* Machine architecture. */
+        ('ELF_Version',              c_uint32),            # Elf64_Word   /* ELF format version. */
+        ('ELF_Entry',                c_uint64),            # Elf64_Addr   /* Entry point. */
+        ('ELF_PHOff',                c_uint64),            # Elf64_Off    /* Program header file offset. */
+        ('ELF_SHOff',                c_uint64),            # Elf64_Off    /* Section header file offset. */
+        ('ELF_Flags',                c_uint32),            # Elf64_Word   /* Architecture-specific flags. */
+        ('ELF_EFSize',               c_uint16),            # Elf64_Half   /* Size of ELF header in bytes. */
+        ('ELF_PHEntSize',            c_uint16),            # Elf64_Half   /* Size of program header entry. */
+        ('ELF_PHNum',                c_uint16),            # Elf64_Half   /* Number of program header entries. */
+        ('ELF_SHEntSize',            c_uint16),            # Elf64_Half   /* Size of section header entry. */
+        ('ELF_SHNum',                c_uint16),            # Elf64_Half   /* Number of section header entries. */
+        ('ELF_SNStr',                c_uint16),            # Elf64_Half   /* Section name strings section. */
+    ]
+
+# Section header.
+class ELF_SECTION_HEADER32(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('SH_Name',                  c_uint32),            # Elf32_Word   /* Section name (index into the section header string table). */
+        ('SH_Type',                  c_uint32),            # Elf32_Word   /* Section type. */
+        ('SH_Flags',                 c_uint32),            # Elf32_Word   /* Section flags. */
+        ('SH_ADDR',                  c_uint32),            # Elf32_Addr   /* Address in memory image. */
+        ('SH_Offset',                c_uint32),            # Elf32_Off    /* Offset in file. */
+        ('SH_Size',                  c_uint32),            # Elf32_Word   /* Size in bytes. */
+        ('SH_Link',                  c_uint32),            # Elf32_Word   /* Index of a related section. */
+        ('SH_Info',                  c_uint32),            # Elf32_Word   /* Depends on section type. */
+        ('SH_AddrAlign',             c_uint32),            # Elf32_Word   /* Alignment in bytes. */
+        ('SH_EntSize',               c_uint32),            # Elf32_Word   /* Size of each entry in section. */
+    ]
+
+class ELF_SECTION_HEADER64(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('SH_Name',                  c_uint32),            # Elf32_Word   /* Section name (index into the section header string table). */
+        ('SH_Type',                  c_uint32),            # Elf32_Word   /* Section type. */
+        ('SH_Flags',                 c_uint64),            # Elf32_XWord   /* Section flags. */
+        ('SH_ADDR',                  c_uint64),            # Elf32_Addr   /* Address in memory image. */
+        ('SH_Offset',                c_uint64),            # Elf32_Off    /* Offset in file. */
+        ('SH_Size',                  c_uint64),            # Elf32_XWord   /* Size in bytes. */
+        ('SH_Link',                  c_uint32),            # Elf32_Word   /* Index of a related section. */
+        ('SH_Info',                  c_uint32),            # Elf32_Word   /* Depends on section type. */
+        ('SH_AddrAlign',             c_uint64),            # Elf32_XWord   /* Alignment in bytes. */
+        ('SH_EntSize',               c_uint64),            # Elf32_XWord   /* Size of each entry in section. */
+    ]
+
+# Program header.
+class ELF_PROGRAM_HEADER32(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('PH_Type',                  c_uint32),            # Elf32_Word   /* Entry type. */
+        ('PH_Offset',                c_uint32),            # Elf32_Off    /* File offset of contents. */
+        ('PH_VirAddr',               c_uint32),            # Elf32_Addr   /* Virtual address in memory image. */
+        ('PH_PhyAddr',               c_uint32),            # Elf32_Addr   /* Physical address (not used). */
+        ('PH_FileSize',              c_uint32),            # Elf32_Word   /* Size of contents in file. */
+        ('PH_MemorySize',            c_uint32),            # Elf32_Word   /* Size of contents in memory. */
+        ('PH_Flags',                 c_uint32),            # Elf32_Word   /* Access permission flags. */
+        ('PH_Align',                 c_uint32),            # Elf32_Word   /* Alignment in memory and file. */
+    ]
+
+class ELF_PROGRAM_HEADER64(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('PH_Type',                  c_uint32),            # Elf32_Word   /* Entry type. */
+        ('PH_Flags',                 c_uint32),            # Elf32_Word   /* Access permission flags. */
+        ('PH_Offset',                c_uint64),            # Elf32_Off    /* File offset of contents. */
+        ('PH_VirAddr',               c_uint64),            # Elf32_Addr   /* Virtual address in memory image. */
+        ('PH_PhyAddr',               c_uint64),            # Elf32_Addr   /* Physical address (not used). */
+        ('PH_FileSize',              c_uint64),            # Elf32_XWord   /* Size of contents in file. */
+        ('PH_MemorySize',            c_uint64),            # Elf32_XWord   /* Size of contents in memory. */
+        ('PH_Align',                 c_uint64),            # Elf32_XWord   /* Alignment in memory and file. */
+    ]
+
+# Dynamic union.
+class ELF_DYNAMIC_UNION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Dynamic_Val',          c_uint32),            # Elf32_Word   /* Integer value. */
+        ('ELF_Dynamic_Ptr',          c_uint32),            # Elf32_Addr   /* Address value. */
+    ]
+
+
+# Dynamic structure. The ".dynamic" section contains an array of them.
+class ELF_DYNAMIC_STRUCTURE(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Dynamic_Tag',          c_int32),             # Elf32_Sword   /* Entry type. */
+        ('ELF_Dynamic_Union',        ELF_DYNAMIC_UNION),   # Elf32_Off     /* Section type. */
+    ]
+
+## Relocation entries.
+
+# /* Relocations that don't need an addend field. */
+class ELF_RELOCATION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_ReOffset',             c_uint32),            # Elf32_Addr   /* Location to be relocated. */
+        ('ELF_ReInfo',               c_uint32),            # Elf32_Word   /* Relocation type and symbol index. */
+    ]
+
+# /* Relocations that need an addend field. */
+class ELF_RELOCATION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_ReOffset',             c_uint32),            # Elf32_Addr   /* Location to be relocated. */
+        ('ELF_ReInfo',               c_uint32),            # Elf32_Word   /* Relocation type and symbol index. */
+        ('ELF_ReAddend',             c_int32),             # Elf32_SWord  /* Addend. */
+    ]
+
+# Move Entry
+class ELF_MOVE(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_MValue',               c_uint64),            # Elf32_Lword  /* symbol value */
+        ('ELF_MInfo',                c_uint32),            # Elf32_Word   /* size + index */
+        ('ELF_MPOffset',             c_int32),             # Elf32_Word   /* symbol offset */
+        ('ELF_MRepeat',              c_uint16),            # Elf32_Half   /* repeat count */
+        ('ELF_MStride',              c_uint16),            # Elf32_Half   /* stride info */
+    ]
+
+## Hardware/Software capabilities entry
+class ELF_CAPA_UNION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Capa_Val',             c_uint32),            # Elf32_Word   /* Integer value. */
+        ('ELF_Capa_Ptr',             c_uint32),            # Elf32_Addr   /* Address value. */
+    ]
+
+class ELF_CAPABILITY(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Capa_Tag',             c_uint32),            # Elf32_Word   /* how to interpret value */
+        ('ELF_Capa_Union',           ELF_CAPA_UNION),      # ELF_CAPA_UNION
+    ]
+
+# Symbol table entries.
+class ELF_SYMBOL(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_ST_Name',              c_uint32),            # Elf32_Word   /* String table index of name. */
+        ('ELF_ST_Value',             c_uint32),            # Elf32_Addr   /* Symbol value. */
+        ('ELF_ST_Size',              c_uint32),            # Elf32_Word   /* Size of associated object. */
+        ('ELF_ST_Info',              c_char),              # /* Type and binding information. */
+        ('ELF_ST_Other',             c_char),              # /* Reserved (not used). */
+        ('ELF_ST_Shndx',             c_uint16),            # Elf32_Half   /* Section index of symbol. */
+    ]
+
+# Structures used by Sun & GNU symbol versioning.
+class ELF_VERDEF(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VD_Version',           c_uint16),            # Elf32_Half
+        ('ELF_VD_Flags',             c_uint16),            # Elf32_Half
+        ('ELF_VD_Ndx',               c_uint16),            # Elf32_Half
+        ('ELF_VD_Cnt',               c_uint16),            # Elf32_Half
+        ('ELF_VD_Hash',              c_uint32),            # Elf32_Word
+        ('ELF_VD_Aux',               c_uint32),            # Elf32_Word
+        ('ELF_VD_Next',              c_uint32),            # Elf32_Word
+    ]
+
+class ELF_VERDAUX(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VDA_Name',             c_uint32),            # Elf32_Word
+        ('ELF_VDA_Next',             c_uint32),            # Elf32_Word
+    ]
+
+class ELF_VERNEED(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VN_Version',           c_uint16),            # Elf32_Half
+        ('ELF_VN_Cnt',               c_uint16),            # Elf32_Half
+        ('ELF_VN_File',              c_uint32),            # Elf32_Word
+        ('ELF_VN_Aux',               c_uint32),            # Elf32_Word
+        ('ELF_VN_Next',              c_uint32),            # Elf32_Word
+    ]
+
+class ELF_VERNAUX(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VNA_Hash',             c_uint32),            # Elf32_Word
+        ('ELF_VNA_Flags',            c_uint16),            # Elf32_Half
+        ('ELF_VNA_Other',            c_uint16),            # Elf32_Half
+        ('ELF_VNA_Name',             c_uint32),            # Elf32_Word
+        ('ELF_VNA_Next',             c_uint32),            # Elf32_Word
+    ]
+
+class ELF_SYMINFO(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_SI_BoundTo',           c_uint16),            # Elf32_Half   /* direct bindings - symbol bound to */
+        ('ELF_SI_Flags',             c_uint16),            # Elf32_Half   /* per symbol flags */
+    ]
+
+class UNIVERSAL_PAYLOAD_INFO(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('Identifier',               c_uint32),            # ‘PLDH’ Identifier for the unverial payload info. 0x504c4448
+        ('HeaderLength',             c_uint32),            # Length of the structure in bytes.
+        ('SpecRevision',             c_uint16),            # Indicates compliance with a revision of this specification in the BCD format. 7 : 0 - Minor Version / 15 : 8 - Major Version For revision v0.75 the value will be 0x0075.
+        ('Reserved',                 c_uint16),            # Reserved for future use.
+        ('Revision',                 c_uint32),            # Revision of the Payload binary. Major.Minor .Revision.Build . The ImageRevision can be decoded as follows: 7 : 0  - Build Number / 15 :8  - Revision / 23 :16 - Minor Version / 31 :24 - Major Version
+        ('Attribute',                c_uint32),            # Length of the structure in bytes.
+        ('Capability',               c_uint32),            # Length of the structure in bytes.
+        ('ProducerId',               ARRAY(c_uint8, 16)),  # Length of the structure in bytes.
+        ('ImageId',                  ARRAY(c_uint8, 16)),  # Length of the structure in bytes.
+    ]
-- 
2.39.1.windows.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread
* [Patch V1 3/3] BaseTools: FMMT support ELF UPLD parser
@ 2023-04-18  9:53 Yuwei Chen
  0 siblings, 0 replies; 3+ messages in thread
From: Yuwei Chen @ 2023-04-18  9:53 UTC (permalink / raw)
  To: devel; +Cc: Rebecca Cran, Bob Feng, Liming Gao

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 28590 bytes --]

FMMT add new function to support the .elf file parsing.
Using '-v' option, the UPLD info will be printed out.

'''
- UNIVERSAL_PAYLOAD_INFO
  - 4 bytes align (BOOLEAN)
    - Identifier
    - SpecRevision
    - Attribute
    - Revision
    - Capability
    - ProducerId
    - ImageId
UPLD Buffer
'''

Cc: Rebecca Cran <rebecca@bsdio.com>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Signed-off-by: Yuwei Chen <yuwei.chen@intel.com>
---
 BaseTools/Source/Python/FMMT/FMMT.py                       |   2 ++
 BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py  |  36 +++++++++++++++++++++++++++++++++++-
 BaseTools/Source/Python/FMMT/core/BiosTree.py              |  48 ++++++++++++++++++++++++++++++++++++++++++++++--
 BaseTools/Source/Python/FMMT/core/BiosTreeNode.py          |  56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 BaseTools/Source/Python/FMMT/core/FMMTParser.py            |   2 +-
 BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 383 insertions(+), 5 deletions(-)

diff --git a/BaseTools/Source/Python/FMMT/FMMT.py b/BaseTools/Source/Python/FMMT/FMMT.py
index bf580b3843..26fc4c5792 100644
--- a/BaseTools/Source/Python/FMMT/FMMT.py
+++ b/BaseTools/Source/Python/FMMT/FMMT.py
@@ -84,6 +84,8 @@ class FMMT():
             ROOT_TYPE = ROOT_FFS_TREE
         elif filetype == '.sec':
             ROOT_TYPE = ROOT_SECTION_TREE
+        elif filetype == '.elf':
+            ROOT_TYPE = ROOT_ELF_TREE
         else:
             ROOT_TYPE = ROOT_TREE
         ViewFile(inputfile, ROOT_TYPE, layoutfilename, outputfile)
diff --git a/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py b/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
index 2d4e6d9276..de174f26ab 100644
--- a/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
+++ b/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
@@ -15,10 +15,13 @@ from core.GuidTools import GUIDTools
 from utils.FmmtLogger import FmmtLogger as logger
 
 ROOT_TREE = 'ROOT'
+ROOT_ELF_TREE = 'ROOT_ELF_TREE'
 ROOT_FV_TREE = 'ROOT_FV_TREE'
 ROOT_FFS_TREE = 'ROOT_FFS_TREE'
 ROOT_SECTION_TREE = 'ROOT_SECTION_TREE'
 
+ELF_TREE = 'ELF'
+ELF_SECTION_TREE = 'ELF_SECTION_TREE'
 FV_TREE = 'FV'
 DATA_FV_TREE = 'DATA_FV'
 FFS_TREE = 'FFS'
@@ -49,6 +52,12 @@ class BinaryProduct():
     def ParserData():
         pass
 
+class ElfFactory(BinaryFactory):
+    type = [ROOT_ELF_TREE, ELF_TREE]
+
+    def Create_Product():
+        return ElfProduct()
+
 class SectionFactory(BinaryFactory):
     type = [SECTION_TREE]
 
@@ -354,6 +363,30 @@ class FdProduct(BinaryProduct):
                 tmp_index += 1
         return Fd_Struct
 
+class ElfSectionProduct(BinaryProduct):
+    ## Decompress the compressed section.
+    def ParserData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        pass
+    def ParserSectionData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        pass
+    def ParserProgramData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        pass
+
+class ElfProduct(BinaryProduct):
+
+    def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+        Elf_Info = ElfNode(Whole_Data)
+        if Elf_Info.Header.ELF_PHOff != 0:
+            Elf_Info.GetProgramList(Whole_Data[Elf_Info.Header.ELF_PHOff:])
+        if Elf_Info.Header.ELF_SHOff != 0:
+            Elf_Info.GetSectionList(Whole_Data[Elf_Info.Header.ELF_SHOff:])
+            Elf_Info.FindUPLDSection(Whole_Data)
+        Elf_Tree = BIOSTREE(Elf_Info.Name)
+        Elf_Tree.type = ELF_TREE
+        Elf_Info.Data = Whole_Data[Elf_Info.HeaderLength:]
+        Elf_Tree.Data = Elf_Info
+        ParTree.insertChild(Elf_Tree)
+
 class ParserEntry():
     FactoryTable:dict = {
         SECTION_TREE: SectionFactory,
@@ -364,6 +397,7 @@ class ParserEntry():
         SEC_FV_TREE: FvFactory,
         ROOT_FV_TREE: FdFactory,
         ROOT_TREE: FdFactory,
+        ROOT_ELF_TREE: ElfFactory,
     }
 
     def GetTargetFactory(self, Tree_type: str) -> BinaryFactory:
@@ -377,4 +411,4 @@ class ParserEntry():
     def DataParser(self, Tree, Data: bytes, Offset: int) -> None:
         TargetFactory = self.GetTargetFactory(Tree.type)
         if TargetFactory:
-            self.Generate_Product(TargetFactory, Tree, Data, Offset)
\ No newline at end of file
+            self.Generate_Product(TargetFactory, Tree, Data, Offset)
diff --git a/BaseTools/Source/Python/FMMT/core/BiosTree.py b/BaseTools/Source/Python/FMMT/core/BiosTree.py
index 137f49748b..c5a7b017f4 100644
--- a/BaseTools/Source/Python/FMMT/core/BiosTree.py
+++ b/BaseTools/Source/Python/FMMT/core/BiosTree.py
@@ -12,6 +12,7 @@ ROOT_TREE = 'ROOT'
 ROOT_FV_TREE = 'ROOT_FV_TREE'
 ROOT_FFS_TREE = 'ROOT_FFS_TREE'
 ROOT_SECTION_TREE = 'ROOT_SECTION_TREE'
+ROOT_ELF_TREE = 'ROOT_ELF_TREE'
 
 FV_TREE = 'FV'
 DATA_FV_TREE = 'DATA_FV'
@@ -21,11 +22,13 @@ FFS_FREE_SPACE = 'FFS_FREE_SPACE'
 SECTION_TREE = 'SECTION'
 SEC_FV_TREE = 'SEC_FV_IMAGE'
 BINARY_DATA = 'BINARY'
+ELF_TREE = 'ELF'
 
 RootType = [ROOT_TREE, ROOT_FV_TREE, ROOT_FFS_TREE, ROOT_SECTION_TREE]
 FvType = [FV_TREE, SEC_FV_TREE]
 FfsType = FFS_TREE
 SecType = SECTION_TREE
+ElfType = [ROOT_ELF_TREE, ELF_TREE]
 
 class BIOSTREE:
     def __init__(self, NodeName: str) -> None:
@@ -118,6 +121,31 @@ class BIOSTREE:
             Info.append("Image File: {}".format(Key))
             Info.append("FilesNum: {}".format(TargetDict.get(Key).get('FilesNum')))
             Info.append("\n")
+        elif TargetDict[Key]["Type"] == ROOT_ELF_TREE:
+            Info.append("ELF File: {}\n".format(Key))
+        elif TargetDict[Key]["Type"] == ELF_TREE:
+            ProducerId = ""
+            ImageId = ""
+            if TargetDict.get(Key).get('IfExist'):
+                Identifier = TargetDict.get(Key).get('Identifier')
+                for item in TargetDict.get(Key).get('ProducerId'):
+                    ProducerId += chr(item)
+                for item in TargetDict.get(Key).get('ImageId'):
+                    ImageId += chr(item)
+                Info.append("- UNIVERSAL_PAYLOAD_INFO")
+                Info.append("  - 4 bytes align: {}".format(TargetDict.get(Key).get('Upld_Info_Align')))
+                Info.append("    - Identifier: {}  # 0x48444c50--PLDH / 0x444c5055--UPLD".format(hex(Identifier)))
+                Info.append("    - SpecRevision: {}".format(hex(TargetDict.get(Key).get('SpecRevision'))))
+                Info.append("    - Attribute: {}".format(hex(TargetDict.get(Key).get('Attribute'))))
+                Info.append("    - Revision: {}".format(hex(TargetDict.get(Key).get('Revision'))))
+                Info.append("    - Capability: {}".format(hex(TargetDict.get(Key).get('Capability'))))
+                Info.append("    - ProducerId: {}".format(ProducerId))
+                Info.append("    - ImageId: {}".format(ImageId))
+                Info.append("\n")
+                Info.append("- UPLD buffer")
+                Info.append("  Buffer: {}".format(TargetDict.get(Key).get('Upld_Buffer')))
+            else:
+                print("Do not find the Upld Info section!!!\n")
         elif TargetDict[Key]["Type"] in FvType:
             space += 2
             if TargetDict[Key]["Type"] == SEC_FV_TREE:
@@ -146,13 +174,29 @@ class BIOSTREE:
         if TreeInfo is None:
             TreeInfo =collections.OrderedDict()
 
-        if self.type == ROOT_TREE or self.type == ROOT_FV_TREE or self.type == ROOT_FFS_TREE or self.type == ROOT_SECTION_TREE:
+        if self.type == ROOT_TREE or self.type == ROOT_FV_TREE or self.type == ROOT_FFS_TREE or self.type == ROOT_SECTION_TREE or self.type == ROOT_ELF_TREE:
             key = str(self.key)
             TreeInfo[self.key] = collections.OrderedDict()
             TreeInfo[self.key]["Name"] = key
             TreeInfo[self.key]["Type"] = self.type
             TreeInfo[self.key]["FilesNum"] = len(self.Child)
-        elif self.type == FV_TREE or  self.type == SEC_FV_TREE:
+        elif self.type == ELF_TREE:
+            key = str(self.Data.Name)
+            TreeInfo[key] = collections.OrderedDict()
+            TreeInfo[key]["Name"] = key
+            TreeInfo[key]["Type"] = self.type
+            TreeInfo[key]["IfExist"] = self.Data.UpldInfo
+            if self.Data.UpldInfo:
+                TreeInfo[key]["Identifier"] = self.Data.UpldInfo.Identifier
+                TreeInfo[key]["SpecRevision"] = self.Data.UpldInfo.SpecRevision
+                TreeInfo[key]["Attribute"] = self.Data.UpldInfo.Attribute
+                TreeInfo[key]["Revision"] = self.Data.UpldInfo.Revision
+                TreeInfo[key]["Capability"] = self.Data.UpldInfo.Capability
+                TreeInfo[key]["ProducerId"] = self.Data.UpldInfo.ProducerId
+                TreeInfo[key]["ImageId"] = self.Data.UpldInfo.ImageId
+                TreeInfo[key]["Upld_Info_Align"] = self.Data.Upld_Info_Align
+                TreeInfo[key]["Upld_Buffer"] = self.Data.UpldBuffer
+        elif self.type == FV_TREE or self.type == SEC_FV_TREE:
             key = str(self.Data.FvId)
             TreeInfo[key] = collections.OrderedDict()
             TreeInfo[key]["Name"] = key
diff --git a/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py b/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
index 20447766c8..5ca4c20dc6 100644
--- a/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
+++ b/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
@@ -4,6 +4,7 @@
 # Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
+from FirmwareStorageFormat.UPLHeader import *
 from FirmwareStorageFormat.FvHeader import *
 from FirmwareStorageFormat.FfsFileHeader import *
 from FirmwareStorageFormat.SectionHeader import *
@@ -37,6 +38,59 @@ class BinaryNode:
         self.HOffset = 0
         self.Data = b''
 
+class ElfNode:
+    def __init__(self, buffer: bytes) -> None:
+        self.Header = ELF_HEADER32.from_buffer_copy(buffer)
+        if self.Header.ELF_Identification[0:4] != b'\x7fELF':
+            logger.error('Invalid Elf Header! Elf Identification {} is not ".ELF".'.format(self.Header.ELF_Identification))
+            raise Exception("Process Failed: Invalid ELF Header Identification!")
+        self.Class = self.Header.ELF_Identification[4]
+        if self.Class == 0x02:
+            self.Header = ELF_HEADER64.from_buffer_copy(buffer)
+        elif self.Class != 0x01:
+            logger.error('Invalid Elf Class! Elf Class {} is not 0x01 or 0x02.'.format(self.Class))
+            raise Exception("Process Failed: Invalid ELF Class!")
+
+        self.ProList = []
+        self.SecList = []
+        self.UpldInfoSection = None
+        self.UpldInfo = None
+        self.UpldBuffer = b''
+        self.Name = "ELF"
+        self.HeaderLength = len(struct2stream(self.Header))
+        self.HOffset = 0
+        self.DOffset = 0
+        self.ROffset = 0
+        self.Data = b''
+        self.PadData = b''
+        self.Upld_Info_Align = False
+
+    def GetProgramList(self, buffer: bytes) -> None:
+        for i in range(self.Header.ELF_PHNum):
+            if self.Class == 0x01:
+                ElfProgramHeader = ELF_PROGRAM_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
+            elif self.Class == 0x02:
+                ElfProgramHeader = ELF_PROGRAM_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
+            self.ProList.append(ElfProgramHeader)
+
+    def GetSectionList(self, buffer: bytes) -> None:
+        for i in range(self.Header.ELF_SHNum):
+            if self.Class == 0x01:
+                ElfSectionHeader = ELF_SECTION_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
+            elif self.Class == 0x02:
+                ElfSectionHeader = ELF_SECTION_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
+            self.SecList.append(ElfSectionHeader)
+
+    def FindUPLDSection(self, buffer: bytes) -> None:
+        for item in self.SecList:
+            if buffer[item.SH_Offset:item.SH_Offset+4] == b'PLDH' or buffer[item.SH_Offset:item.SH_Offset+4] == b'UPLD':
+                self.UpldInfoSection = item
+                self.UpldInfo = UNIVERSAL_PAYLOAD_INFO.from_buffer_copy(buffer[item.SH_Offset:item.SH_Offset+item.SH_Size])
+                self.UpldBuffer = struct2stream(self.UpldInfo)
+                if (self.UpldInfoSection.SH_Offset) % 4 == 0:
+                # if (self.UpldInfoSection.SH_Offset - self.Header.ELF_Entry) % 4 == 0:
+                    self.Upld_Info_Align = True
+
 class FvNode:
     def __init__(self, name, buffer: bytes) -> None:
         self.Header = EFI_FIRMWARE_VOLUME_HEADER.from_buffer_copy(buffer)
@@ -191,4 +245,4 @@ class FreeSpaceNode:
         self.HOffset = 0
         self.DOffset = 0
         self.ROffset = 0
-        self.PadData = b''
\ No newline at end of file
+        self.PadData = b''
diff --git a/BaseTools/Source/Python/FMMT/core/FMMTParser.py b/BaseTools/Source/Python/FMMT/core/FMMTParser.py
index e76ac51185..25a2bde799 100644
--- a/BaseTools/Source/Python/FMMT/core/FMMTParser.py
+++ b/BaseTools/Source/Python/FMMT/core/FMMTParser.py
@@ -20,7 +20,7 @@ class FMMTParser:
 
     ## Parser the nodes in WholeTree.
     def ParserFromRoot(self, WholeFvTree=None, whole_data: bytes=b'', Reloffset: int=0) -> None:
-        if WholeFvTree.type == ROOT_TREE or WholeFvTree.type == ROOT_FV_TREE:
+        if WholeFvTree.type == ROOT_TREE or WholeFvTree.type == ROOT_FV_TREE or WholeFvTree.type == ROOT_ELF_TREE:
             ParserEntry().DataParser(self.WholeFvTree, whole_data, Reloffset)
         else:
             ParserEntry().DataParser(WholeFvTree, whole_data, Reloffset)
diff --git a/BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py b/BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py
new file mode 100644
index 0000000000..c57852e741
--- /dev/null
+++ b/BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py
@@ -0,0 +1,244 @@
+## @file
+# This file is used to define the UPL Header C Struct.
+#
+# Copyright (c) 2023-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+from struct import *
+from ctypes import *
+from FirmwareStorageFormat.Common import *
+
+EFI_COMMON_SECTION_HEADER_LEN = 4
+EFI_COMMON_SECTION_HEADER2_LEN = 8
+
+# ELF header.
+class ELF_HEADER32(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Identification',       ARRAY(c_char, 16)),   # /* File identification. */
+        ('ELF_Type',                 c_uint16),            # Elf32_Half   /* File type. */
+        ('ELF_Machine',              c_uint16),            # Elf32_Half   /* Machine architecture. */
+        ('ELF_Version',              c_uint32),            # Elf32_Word   /* ELF format version. */
+        ('ELF_Entry',                c_uint32),            # Elf32_Addr   /* Entry point. */
+        ('ELF_PHOff',                c_uint32),            # Elf32_Off    /* Program header file offset. */
+        ('ELF_SHOff',                c_uint32),            # Elf32_Off    /* Section header file offset. */
+        ('ELF_Flags',                c_uint32),            # Elf32_Word   /* Architecture-specific flags. */
+        ('ELF_EFSize',               c_uint16),            # Elf32_Half   /* Size of ELF header in bytes. */
+        ('ELF_PHEntSize',            c_uint16),            # Elf32_Half   /* Size of program header entry. */
+        ('ELF_PHNum',                c_uint16),            # Elf32_Half   /* Number of program header entries. */
+        ('ELF_SHEntSize',            c_uint16),            # Elf32_Half   /* Size of section header entry. */
+        ('ELF_SHNum',                c_uint16),            # Elf32_Half   /* Number of section header entries. */
+        ('ELF_SNStr',                c_uint16),            # Elf32_Half   /* Section name strings section. */
+    ]
+
+class ELF_HEADER64(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Identification',       ARRAY(c_char, 16)),   # /* File identification. */
+        ('ELF_Type',                 c_uint16),            # Elf64_Half   /* File type. */
+        ('ELF_Machine',              c_uint16),            # Elf64_Half   /* Machine architecture. */
+        ('ELF_Version',              c_uint32),            # Elf64_Word   /* ELF format version. */
+        ('ELF_Entry',                c_uint64),            # Elf64_Addr   /* Entry point. */
+        ('ELF_PHOff',                c_uint64),            # Elf64_Off    /* Program header file offset. */
+        ('ELF_SHOff',                c_uint64),            # Elf64_Off    /* Section header file offset. */
+        ('ELF_Flags',                c_uint32),            # Elf64_Word   /* Architecture-specific flags. */
+        ('ELF_EFSize',               c_uint16),            # Elf64_Half   /* Size of ELF header in bytes. */
+        ('ELF_PHEntSize',            c_uint16),            # Elf64_Half   /* Size of program header entry. */
+        ('ELF_PHNum',                c_uint16),            # Elf64_Half   /* Number of program header entries. */
+        ('ELF_SHEntSize',            c_uint16),            # Elf64_Half   /* Size of section header entry. */
+        ('ELF_SHNum',                c_uint16),            # Elf64_Half   /* Number of section header entries. */
+        ('ELF_SNStr',                c_uint16),            # Elf64_Half   /* Section name strings section. */
+    ]
+
+# Section header.
+class ELF_SECTION_HEADER32(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('SH_Name',                  c_uint32),            # Elf32_Word   /* Section name (index into the section header string table). */
+        ('SH_Type',                  c_uint32),            # Elf32_Word   /* Section type. */
+        ('SH_Flags',                 c_uint32),            # Elf32_Word   /* Section flags. */
+        ('SH_ADDR',                  c_uint32),            # Elf32_Addr   /* Address in memory image. */
+        ('SH_Offset',                c_uint32),            # Elf32_Off    /* Offset in file. */
+        ('SH_Size',                  c_uint32),            # Elf32_Word   /* Size in bytes. */
+        ('SH_Link',                  c_uint32),            # Elf32_Word   /* Index of a related section. */
+        ('SH_Info',                  c_uint32),            # Elf32_Word   /* Depends on section type. */
+        ('SH_AddrAlign',             c_uint32),            # Elf32_Word   /* Alignment in bytes. */
+        ('SH_EntSize',               c_uint32),            # Elf32_Word   /* Size of each entry in section. */
+    ]
+
+class ELF_SECTION_HEADER64(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('SH_Name',                  c_uint32),            # Elf32_Word   /* Section name (index into the section header string table). */
+        ('SH_Type',                  c_uint32),            # Elf32_Word   /* Section type. */
+        ('SH_Flags',                 c_uint64),            # Elf32_XWord   /* Section flags. */
+        ('SH_ADDR',                  c_uint64),            # Elf32_Addr   /* Address in memory image. */
+        ('SH_Offset',                c_uint64),            # Elf32_Off    /* Offset in file. */
+        ('SH_Size',                  c_uint64),            # Elf32_XWord   /* Size in bytes. */
+        ('SH_Link',                  c_uint32),            # Elf32_Word   /* Index of a related section. */
+        ('SH_Info',                  c_uint32),            # Elf32_Word   /* Depends on section type. */
+        ('SH_AddrAlign',             c_uint64),            # Elf32_XWord   /* Alignment in bytes. */
+        ('SH_EntSize',               c_uint64),            # Elf32_XWord   /* Size of each entry in section. */
+    ]
+
+# Program header.
+class ELF_PROGRAM_HEADER32(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('PH_Type',                  c_uint32),            # Elf32_Word   /* Entry type. */
+        ('PH_Offset',                c_uint32),            # Elf32_Off    /* File offset of contents. */
+        ('PH_VirAddr',               c_uint32),            # Elf32_Addr   /* Virtual address in memory image. */
+        ('PH_PhyAddr',               c_uint32),            # Elf32_Addr   /* Physical address (not used). */
+        ('PH_FileSize',              c_uint32),            # Elf32_Word   /* Size of contents in file. */
+        ('PH_MemorySize',            c_uint32),            # Elf32_Word   /* Size of contents in memory. */
+        ('PH_Flags',                 c_uint32),            # Elf32_Word   /* Access permission flags. */
+        ('PH_Align',                 c_uint32),            # Elf32_Word   /* Alignment in memory and file. */
+    ]
+
+class ELF_PROGRAM_HEADER64(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('PH_Type',                  c_uint32),            # Elf32_Word   /* Entry type. */
+        ('PH_Flags',                 c_uint32),            # Elf32_Word   /* Access permission flags. */
+        ('PH_Offset',                c_uint64),            # Elf32_Off    /* File offset of contents. */
+        ('PH_VirAddr',               c_uint64),            # Elf32_Addr   /* Virtual address in memory image. */
+        ('PH_PhyAddr',               c_uint64),            # Elf32_Addr   /* Physical address (not used). */
+        ('PH_FileSize',              c_uint64),            # Elf32_XWord   /* Size of contents in file. */
+        ('PH_MemorySize',            c_uint64),            # Elf32_XWord   /* Size of contents in memory. */
+        ('PH_Align',                 c_uint64),            # Elf32_XWord   /* Alignment in memory and file. */
+    ]
+
+# Dynamic union.
+class ELF_DYNAMIC_UNION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Dynamic_Val',          c_uint32),            # Elf32_Word   /* Integer value. */
+        ('ELF_Dynamic_Ptr',          c_uint32),            # Elf32_Addr   /* Address value. */
+    ]
+
+
+# Dynamic structure. The ".dynamic" section contains an array of them.
+class ELF_DYNAMIC_STRUCTURE(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Dynamic_Tag',          c_int32),             # Elf32_Sword   /* Entry type. */
+        ('ELF_Dynamic_Union',        ELF_DYNAMIC_UNION),   # Elf32_Off     /* Section type. */
+    ]
+
+## Relocation entries.
+
+# /* Relocations that don't need an addend field. */
+class ELF_RELOCATION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_ReOffset',             c_uint32),            # Elf32_Addr   /* Location to be relocated. */
+        ('ELF_ReInfo',               c_uint32),            # Elf32_Word   /* Relocation type and symbol index. */
+    ]
+
+# /* Relocations that need an addend field. */
+class ELF_RELOCATION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_ReOffset',             c_uint32),            # Elf32_Addr   /* Location to be relocated. */
+        ('ELF_ReInfo',               c_uint32),            # Elf32_Word   /* Relocation type and symbol index. */
+        ('ELF_ReAddend',             c_int32),             # Elf32_SWord  /* Addend. */
+    ]
+
+# Move Entry
+class ELF_MOVE(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_MValue',               c_uint64),            # Elf32_Lword  /* symbol value */
+        ('ELF_MInfo',                c_uint32),            # Elf32_Word   /* size + index */
+        ('ELF_MPOffset',             c_int32),             # Elf32_Word   /* symbol offset */
+        ('ELF_MRepeat',              c_uint16),            # Elf32_Half   /* repeat count */
+        ('ELF_MStride',              c_uint16),            # Elf32_Half   /* stride info */
+    ]
+
+## Hardware/Software capabilities entry
+class ELF_CAPA_UNION(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Capa_Val',             c_uint32),            # Elf32_Word   /* Integer value. */
+        ('ELF_Capa_Ptr',             c_uint32),            # Elf32_Addr   /* Address value. */
+    ]
+
+class ELF_CAPABILITY(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_Capa_Tag',             c_uint32),            # Elf32_Word   /* how to interpret value */
+        ('ELF_Capa_Union',           ELF_CAPA_UNION),      # ELF_CAPA_UNION
+    ]
+
+# Symbol table entries.
+class ELF_SYMBOL(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_ST_Name',              c_uint32),            # Elf32_Word   /* String table index of name. */
+        ('ELF_ST_Value',             c_uint32),            # Elf32_Addr   /* Symbol value. */
+        ('ELF_ST_Size',              c_uint32),            # Elf32_Word   /* Size of associated object. */
+        ('ELF_ST_Info',              c_char),              # /* Type and binding information. */
+        ('ELF_ST_Other',             c_char),              # /* Reserved (not used). */
+        ('ELF_ST_Shndx',             c_uint16),            # Elf32_Half   /* Section index of symbol. */
+    ]
+
+# Structures used by Sun & GNU symbol versioning.
+class ELF_VERDEF(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VD_Version',           c_uint16),            # Elf32_Half
+        ('ELF_VD_Flags',             c_uint16),            # Elf32_Half
+        ('ELF_VD_Ndx',               c_uint16),            # Elf32_Half
+        ('ELF_VD_Cnt',               c_uint16),            # Elf32_Half
+        ('ELF_VD_Hash',              c_uint32),            # Elf32_Word
+        ('ELF_VD_Aux',               c_uint32),            # Elf32_Word
+        ('ELF_VD_Next',              c_uint32),            # Elf32_Word
+    ]
+
+class ELF_VERDAUX(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VDA_Name',             c_uint32),            # Elf32_Word
+        ('ELF_VDA_Next',             c_uint32),            # Elf32_Word
+    ]
+
+class ELF_VERNEED(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VN_Version',           c_uint16),            # Elf32_Half
+        ('ELF_VN_Cnt',               c_uint16),            # Elf32_Half
+        ('ELF_VN_File',              c_uint32),            # Elf32_Word
+        ('ELF_VN_Aux',               c_uint32),            # Elf32_Word
+        ('ELF_VN_Next',              c_uint32),            # Elf32_Word
+    ]
+
+class ELF_VERNAUX(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_VNA_Hash',             c_uint32),            # Elf32_Word
+        ('ELF_VNA_Flags',            c_uint16),            # Elf32_Half
+        ('ELF_VNA_Other',            c_uint16),            # Elf32_Half
+        ('ELF_VNA_Name',             c_uint32),            # Elf32_Word
+        ('ELF_VNA_Next',             c_uint32),            # Elf32_Word
+    ]
+
+class ELF_SYMINFO(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('ELF_SI_BoundTo',           c_uint16),            # Elf32_Half   /* direct bindings - symbol bound to */
+        ('ELF_SI_Flags',             c_uint16),            # Elf32_Half   /* per symbol flags */
+    ]
+
+class UNIVERSAL_PAYLOAD_INFO(Structure):
+    _pack_ = 1
+    _fields_ = [
+        ('Identifier',               c_uint32),            # ‘PLDH’ Identifier for the unverial payload info. 0x504c4448
+        ('HeaderLength',             c_uint32),            # Length of the structure in bytes.
+        ('SpecRevision',             c_uint16),            # Indicates compliance with a revision of this specification in the BCD format. 7 : 0 - Minor Version / 15 : 8 - Major Version For revision v0.75 the value will be 0x0075.
+        ('Reserved',                 c_uint16),            # Reserved for future use.
+        ('Revision',                 c_uint32),            # Revision of the Payload binary. Major.Minor .Revision.Build . The ImageRevision can be decoded as follows: 7 : 0  - Build Number / 15 :8  - Revision / 23 :16 - Minor Version / 31 :24 - Major Version
+        ('Attribute',                c_uint32),            # Length of the structure in bytes.
+        ('Capability',               c_uint32),            # Length of the structure in bytes.
+        ('ProducerId',               ARRAY(c_uint8, 16)),  # Length of the structure in bytes.
+        ('ImageId',                  ARRAY(c_uint8, 16)),  # Length of the structure in bytes.
+    ]
-- 
2.39.1.windows.1


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

end of thread, other threads:[~2023-06-05  9:19 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-18  9:55 [Patch V1 3/3] BaseTools: FMMT support ELF UPLD parser Yuwei Chen
2023-06-05  9:19 ` Bob Feng
  -- strict thread matches above, loose matches on Subject: below --
2023-04-18  9:53 Yuwei Chen

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