From 59f0d350a9f39fdb1d26295457eaf14306703afb Mon Sep 17 00:00:00 2001 From: Yuwei Chen Date: Thu, 29 Jun 2023 11:35:01 +0800 Subject: [PATCH] BaseTools: FMMT support ELF UPLD parser 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 Cc: Bob Feng Cc: Liming Gao Signed-off-by: Yuwei Chen Reviewed-by: Liming Gao Reviewed-by: Bob Feng --- BaseTools/Source/Python/FMMT/FMMT.py | 2 + .../Python/FMMT/core/BinaryFactoryProduct.py | 36 ++- BaseTools/Source/Python/FMMT/core/BiosTree.py | 48 +++- .../Source/Python/FMMT/core/BiosTreeNode.py | 56 +++- .../Source/Python/FMMT/core/FMMTParser.py | 2 +- .../Python/FirmwareStorageFormat/UPLHeader.py | 244 ++++++++++++++++++ 6 files changed, 383 insertions(+), 5 deletions(-) create mode 100644 BaseTools/Source/Python/FirmwareStorageFormat/UPLHeader.py 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.
# 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..fd4da939f9 --- /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.
+# 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. + ]