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