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>
		
	
		
			
				
	
	
		
			243 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
## @file
 | 
						|
# This file is used to define the Bios layout tree structure and related operations.
 | 
						|
#
 | 
						|
# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
 | 
						|
# SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
##
 | 
						|
import collections
 | 
						|
from FirmwareStorageFormat.Common import *
 | 
						|
from utils.FmmtLogger import FmmtLogger as logger
 | 
						|
 | 
						|
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'
 | 
						|
FFS_TREE = 'FFS'
 | 
						|
FFS_PAD = 'FFS_PAD'
 | 
						|
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:
 | 
						|
        self.key = NodeName
 | 
						|
        self.type = None
 | 
						|
        self.Data = None
 | 
						|
        self.Child = []
 | 
						|
        self.Findlist = []
 | 
						|
        self.Parent = None
 | 
						|
        self.NextRel = None
 | 
						|
        self.LastRel = None
 | 
						|
 | 
						|
    def HasChild(self) -> bool:
 | 
						|
        if self.Child == []:
 | 
						|
            return False
 | 
						|
        else:
 | 
						|
            return True
 | 
						|
 | 
						|
    def isFinalChild(self) -> bool:
 | 
						|
        ParTree = self.Parent
 | 
						|
        if ParTree:
 | 
						|
            if ParTree.Child[-1] == self:
 | 
						|
                return True
 | 
						|
        return False
 | 
						|
 | 
						|
    # FvTree.insertChild()
 | 
						|
    def insertChild(self, newNode, pos: int=None) -> None:
 | 
						|
        if len(self.Child) == 0:
 | 
						|
            self.Child.append(newNode)
 | 
						|
        else:
 | 
						|
            if not pos or pos == len(self.Child):
 | 
						|
                LastTree = self.Child[-1]
 | 
						|
                self.Child.append(newNode)
 | 
						|
                LastTree.NextRel = newNode
 | 
						|
                newNode.LastRel = LastTree
 | 
						|
            else:
 | 
						|
                newNode.NextRel = self.Child[pos-1].NextRel
 | 
						|
                newNode.LastRel = self.Child[pos].LastRel
 | 
						|
                self.Child[pos-1].NextRel = newNode
 | 
						|
                self.Child[pos].LastRel = newNode
 | 
						|
                self.Child.insert(pos, newNode)
 | 
						|
        newNode.Parent = self
 | 
						|
 | 
						|
    # lastNode.insertRel(newNode)
 | 
						|
    def insertRel(self, newNode) -> None:
 | 
						|
        if self.Parent:
 | 
						|
            parentTree = self.Parent
 | 
						|
            new_index = parentTree.Child.index(self) + 1
 | 
						|
            parentTree.Child.insert(new_index, newNode)
 | 
						|
        self.NextRel = newNode
 | 
						|
        newNode.LastRel = self
 | 
						|
 | 
						|
    def deleteNode(self, deletekey: str) -> None:
 | 
						|
        FindStatus, DeleteTree = self.FindNode(deletekey)
 | 
						|
        if FindStatus:
 | 
						|
            parentTree = DeleteTree.Parent
 | 
						|
            lastTree = DeleteTree.LastRel
 | 
						|
            nextTree = DeleteTree.NextRel
 | 
						|
            if parentTree:
 | 
						|
                index = parentTree.Child.index(DeleteTree)
 | 
						|
                del parentTree.Child[index]
 | 
						|
            if lastTree and nextTree:
 | 
						|
                lastTree.NextRel = nextTree
 | 
						|
                nextTree.LastRel = lastTree
 | 
						|
            elif lastTree:
 | 
						|
                lastTree.NextRel = None
 | 
						|
            elif nextTree:
 | 
						|
                nextTree.LastRel = None
 | 
						|
            return DeleteTree
 | 
						|
        else:
 | 
						|
            logger.error('Could not find the target tree')
 | 
						|
            return None
 | 
						|
 | 
						|
    def FindNode(self, key: str, Findlist: list) -> None:
 | 
						|
        if self.key == key or (self.Data and self.Data.Name == key) or (self.type == FFS_TREE and self.Data.UiName == key):
 | 
						|
            Findlist.append(self)
 | 
						|
        for item in self.Child:
 | 
						|
            item.FindNode(key, Findlist)
 | 
						|
 | 
						|
    def GetTreePath(self):
 | 
						|
        BiosTreePath = [self]
 | 
						|
        while self.Parent:
 | 
						|
            BiosTreePath.insert(0, self.Parent)
 | 
						|
            self = self.Parent
 | 
						|
        return BiosTreePath
 | 
						|
 | 
						|
    def parserTree(self, TargetDict: dict=None, Info: list=None, space: int=0, ParFvId="") -> None:
 | 
						|
        Key = list(TargetDict.keys())[0]
 | 
						|
        if TargetDict[Key]["Type"] in RootType:
 | 
						|
            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:
 | 
						|
                Info.append("{}Child FV named {} of {}".format(space*" ", Key, ParFvId))
 | 
						|
                space += 2
 | 
						|
            else:
 | 
						|
                Info.append("FvId: {}".format(Key))
 | 
						|
                ParFvId = Key
 | 
						|
            Info.append("{}FvNameGuid: {}".format(space*" ", TargetDict.get(Key).get('FvNameGuid')))
 | 
						|
            Info.append("{}Attributes: {}".format(space*" ", TargetDict.get(Key).get('Attributes')))
 | 
						|
            Info.append("{}Total Volume Size: {}".format(space*" ", TargetDict.get(Key).get('Size')))
 | 
						|
            Info.append("{}Free Volume Size: {}".format(space*" ", TargetDict.get(Key).get('FreeSize')))
 | 
						|
            Info.append("{}Volume Offset: {}".format(space*" ", TargetDict.get(Key).get('Offset')))
 | 
						|
            Info.append("{}FilesNum: {}".format(space*" ", TargetDict.get(Key).get('FilesNum')))
 | 
						|
        elif TargetDict[Key]["Type"] in FfsType:
 | 
						|
            space += 2
 | 
						|
            if TargetDict.get(Key).get('UiName') != "b''":
 | 
						|
                Info.append("{}File: {} / {}".format(space*" ", Key, TargetDict.get(Key).get('UiName')))
 | 
						|
            else:
 | 
						|
                Info.append("{}File: {}".format(space*" ", Key))
 | 
						|
        if "Files" in list(TargetDict[Key].keys()):
 | 
						|
            for item in TargetDict[Key]["Files"]:
 | 
						|
                self.parserTree(item, Info, space, ParFvId)
 | 
						|
 | 
						|
    def ExportTree(self,TreeInfo: dict=None) -> dict:
 | 
						|
        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 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 == 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
 | 
						|
            if self.Data.FvId != self.Data.Name:
 | 
						|
                TreeInfo[key]["FvNameGuid"] = str(self.Data.Name)
 | 
						|
            TreeInfo[key]["Type"] = self.type
 | 
						|
            TreeInfo[key]["Attributes"] = hex(self.Data.Header.Attributes)
 | 
						|
            TreeInfo[key]["Size"] = hex(self.Data.Header.FvLength)
 | 
						|
            TreeInfo[key]["FreeSize"] = hex(self.Data.Free_Space)
 | 
						|
            TreeInfo[key]["Offset"] = hex(self.Data.HOffset)
 | 
						|
            TreeInfo[key]["FilesNum"] = len(self.Child)
 | 
						|
        elif self.type == FFS_TREE:
 | 
						|
            key = str(self.Data.Name)
 | 
						|
            TreeInfo[key] = collections.OrderedDict()
 | 
						|
            TreeInfo[key]["Name"] = key
 | 
						|
            TreeInfo[key]["UiName"] = '{}'.format(self.Data.UiName)
 | 
						|
            TreeInfo[key]["Version"] = '{}'.format(self.Data.Version)
 | 
						|
            TreeInfo[key]["Type"] = self.type
 | 
						|
            TreeInfo[key]["Size"] = hex(self.Data.Size)
 | 
						|
            TreeInfo[key]["Offset"] = hex(self.Data.HOffset)
 | 
						|
            TreeInfo[key]["FilesNum"] = len(self.Child)
 | 
						|
        elif self.type == SECTION_TREE and self.Data.Type == 0x02:
 | 
						|
            key = str(self.Data.Name)
 | 
						|
            TreeInfo[key] = collections.OrderedDict()
 | 
						|
            TreeInfo[key]["Name"] = key
 | 
						|
            TreeInfo[key]["Type"] = self.type
 | 
						|
            TreeInfo[key]["Size"] = hex(len(self.Data.OriData) + self.Data.HeaderLength)
 | 
						|
            TreeInfo[key]["DecompressedSize"] = hex(self.Data.Size)
 | 
						|
            TreeInfo[key]["Offset"] = hex(self.Data.HOffset)
 | 
						|
            TreeInfo[key]["FilesNum"] = len(self.Child)
 | 
						|
        elif self is not None:
 | 
						|
            key = str(self.Data.Name)
 | 
						|
            TreeInfo[key] = collections.OrderedDict()
 | 
						|
            TreeInfo[key]["Name"] = key
 | 
						|
            TreeInfo[key]["Type"] = self.type
 | 
						|
            TreeInfo[key]["Size"] = hex(self.Data.Size)
 | 
						|
            TreeInfo[key]["Offset"] = hex(self.Data.HOffset)
 | 
						|
            TreeInfo[key]["FilesNum"] = len(self.Child)
 | 
						|
 | 
						|
        for item in self.Child:
 | 
						|
            TreeInfo[key].setdefault('Files',[]).append( item.ExportTree())
 | 
						|
 | 
						|
        return TreeInfo
 |