## @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' 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' RootType = [ROOT_TREE, ROOT_FV_TREE, ROOT_FFS_TREE, ROOT_SECTION_TREE] FvType = [FV_TREE, SEC_FV_TREE] FfsType = FFS_TREE SecType = SECTION_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: 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"] 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: 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: 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