## @file # This file is used to define the Bios layout tree structure and related operations. # # Copyright (c) 2021-, Intel Corporation. All rights reserved.
# 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