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 <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> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn> Reviewed-by: Bob Feng <bob.c.feng@intel.com>
This commit is contained in:
@ -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)
|
||||
|
@ -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)
|
||||
self.Generate_Product(TargetFactory, Tree, Data, Offset)
|
||||
|
@ -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
|
||||
|
@ -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''
|
||||
self.PadData = b''
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user