mirror of https://github.com/acidanthera/audk.git
198 lines
8.2 KiB
Python
198 lines
8.2 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'
|
|
|
|
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
|