audk/BaseTools/Source/Python/FMMT/core/FMMTOperation.py
Ashraf Ali S 6d2143f685 BaseTools: Fix NoneType parent reference in FMMT operations
This patch addresses an issue in the FMMT operations where the parent
reference is not checked for NoneType. This oversight can lead to an
AttributeError: 'NoneType' object has no attribute 'Name' when
attempting to access the parent reference. The fix involves adding a
check for NoneType before accessing the parent reference to ensure that
the operations handle such cases gracefully.

The affected functions include:
- AddNewFfs
- ReplaceFfs
- ExtractFfs

These functions now include proper checks to prevent the AttributeError.

Signed-off-by: Ashraf Ali S <ashraf.ali.s@intel.com>
2025-01-27 16:26:18 +00:00

242 lines
11 KiB
Python

## @file
# This file is used to define the functions to operate bios binary file.
#
# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
from core.FMMTParser import *
from core.FvHandler import *
from utils.FvLayoutPrint import *
from utils.FmmtLogger import FmmtLogger as logger
global Fv_count
Fv_count = 0
# The ROOT_TYPE can be 'ROOT_TREE', 'ROOT_FV_TREE', 'ROOT_FFS_TREE', 'ROOT_SECTION_TREE'
def ViewFile(inputfile: str, ROOT_TYPE: str, layoutfile: str=None, outputfile: str=None) -> None:
if not os.path.exists(inputfile):
logger.error("Invalid inputfile, can not open {}.".format(inputfile))
raise Exception("Process Failed: Invalid inputfile!")
# 1. Data Prepare
with open(inputfile, "rb") as f:
whole_data = f.read()
FmmtParser = FMMTParser(inputfile, ROOT_TYPE)
# 2. DataTree Create
logger.debug('Parsing inputfile data......')
FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
logger.debug('Done!')
# 3. Log Output
InfoDict = FmmtParser.WholeFvTree.ExportTree()
logger.debug('BinaryTree created, start parsing BinaryTree data......')
FmmtParser.WholeFvTree.parserTree(InfoDict, FmmtParser.BinaryInfo)
logger.debug('Done!')
GetFormatter("").LogPrint(FmmtParser.BinaryInfo)
if layoutfile:
if os.path.splitext(layoutfile)[1]:
layoutfilename = layoutfile
layoutfileformat = os.path.splitext(layoutfile)[1][1:].lower()
else:
layoutfilename = "Layout_{}{}".format(os.path.basename(inputfile),".{}".format(layoutfile.lower()))
layoutfileformat = layoutfile.lower()
GetFormatter(layoutfileformat).dump(InfoDict, FmmtParser.BinaryInfo, layoutfilename)
# 4. Data Encapsulation
if outputfile:
logger.debug('Start encapsulating data......')
FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
with open(outputfile, "wb") as f:
f.write(FmmtParser.FinalData)
logger.debug('Encapsulated data is saved in {}.'.format(outputfile))
def DeleteFfs(inputfile: str, TargetFfs_name: str, outputfile: str, Fv_name: str=None) -> None:
if not os.path.exists(inputfile):
logger.error("Invalid inputfile, can not open {}.".format(inputfile))
raise Exception("Process Failed: Invalid inputfile!")
# 1. Data Prepare
with open(inputfile, "rb") as f:
whole_data = f.read()
FmmtParser = FMMTParser(inputfile, ROOT_TREE)
# 2. DataTree Create
logger.debug('Parsing inputfile data......')
FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
logger.debug('Done!')
# 3. Data Modify
FmmtParser.WholeFvTree.FindNode(TargetFfs_name, FmmtParser.WholeFvTree.Findlist)
# Choose the Specfic DeleteFfs with Fv info
if Fv_name:
FindNum = len(FmmtParser.WholeFvTree.Findlist)
for index in range(FindNum-1, -1, -1):
parent = FmmtParser.WholeFvTree.Findlist[index].Parent
if parent is None or parent.Data is None:
continue
if parent.key != Fv_name and parent.Data.Name != Fv_name:
FmmtParser.WholeFvTree.Findlist.remove(FmmtParser.WholeFvTree.Findlist[index])
Status = False
if FmmtParser.WholeFvTree.Findlist != []:
for Delete_Ffs in FmmtParser.WholeFvTree.Findlist:
FfsMod = FvHandler(None, Delete_Ffs)
Status = FfsMod.DeleteFfs()
else:
logger.error('Target Ffs not found!!!')
# 4. Data Encapsulation
if Status:
logger.debug('Start encapsulating data......')
FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
with open(outputfile, "wb") as f:
f.write(FmmtParser.FinalData)
logger.debug('Encapsulated data is saved in {}.'.format(outputfile))
def AddNewFfs(inputfile: str, Fv_name: str, newffsfile: str, outputfile: str) -> None:
if not os.path.exists(inputfile):
logger.error("Invalid inputfile, can not open {}.".format(inputfile))
raise Exception("Process Failed: Invalid inputfile!")
if not os.path.exists(newffsfile):
logger.error("Invalid ffsfile, can not open {}.".format(newffsfile))
raise Exception("Process Failed: Invalid ffs file!")
# 1. Data Prepare
with open(inputfile, "rb") as f:
whole_data = f.read()
FmmtParser = FMMTParser(inputfile, ROOT_TREE)
# 2. DataTree Create
logger.debug('Parsing inputfile data......')
FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
logger.debug('Done!')
# Get Target Fv and Target Ffs_Pad
FmmtParser.WholeFvTree.FindNode(Fv_name, FmmtParser.WholeFvTree.Findlist)
# Create new ffs Tree
with open(newffsfile, "rb") as f:
new_ffs_data = f.read()
NewFmmtParser = FMMTParser(newffsfile, ROOT_FFS_TREE)
Status = False
# 3. Data Modify
if FmmtParser.WholeFvTree.Findlist:
for TargetFv in FmmtParser.WholeFvTree.Findlist:
TargetFfsPad = TargetFv.Child[-1]
logger.debug('Parsing newffsfile data......')
if TargetFfsPad.type == FFS_FREE_SPACE:
NewFmmtParser.ParserFromRoot(NewFmmtParser.WholeFvTree, new_ffs_data, TargetFfsPad.Data.HOffset)
else:
NewFmmtParser.ParserFromRoot(NewFmmtParser.WholeFvTree, new_ffs_data, TargetFfsPad.Data.HOffset+TargetFfsPad.Data.Size)
logger.debug('Done!')
FfsMod = FvHandler(NewFmmtParser.WholeFvTree.Child[0], TargetFfsPad)
Status = FfsMod.AddFfs()
else:
logger.error('Target Fv not found!!!')
# 4. Data Encapsulation
if Status:
logger.debug('Start encapsulating data......')
FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
with open(outputfile, "wb") as f:
f.write(FmmtParser.FinalData)
logger.debug('Encapsulated data is saved in {}.'.format(outputfile))
def ReplaceFfs(inputfile: str, Ffs_name: str, newffsfile: str, outputfile: str, Fv_name: str=None) -> None:
if not os.path.exists(inputfile):
logger.error("Invalid inputfile, can not open {}.".format(inputfile))
raise Exception("Process Failed: Invalid inputfile!")
# 1. Data Prepare
with open(inputfile, "rb") as f:
whole_data = f.read()
FmmtParser = FMMTParser(inputfile, ROOT_TREE)
# 2. DataTree Create
logger.debug('Parsing inputfile data......')
FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
logger.debug('Done!')
with open(newffsfile, "rb") as f:
new_ffs_data = f.read()
newFmmtParser = FMMTParser(newffsfile, FV_TREE)
logger.debug('Parsing newffsfile data......')
newFmmtParser.ParserFromRoot(newFmmtParser.WholeFvTree, new_ffs_data)
logger.debug('Done!')
Status = False
# 3. Data Modify
new_ffs = newFmmtParser.WholeFvTree.Child[0]
new_ffs.Data.PadData = GetPadSize(new_ffs.Data.Size, FFS_COMMON_ALIGNMENT) * b'\xff'
FmmtParser.WholeFvTree.FindNode(Ffs_name, FmmtParser.WholeFvTree.Findlist)
if Fv_name:
FindNum = len(FmmtParser.WholeFvTree.Findlist)
for index in range(FindNum-1, -1, -1):
parent = FmmtParser.WholeFvTree.Findlist[index].Parent
if parent is None or parent.Data is None:
continue
if parent.key != Fv_name and parent.Data.Name != Fv_name:
FmmtParser.WholeFvTree.Findlist.remove(FmmtParser.WholeFvTree.Findlist[index])
if FmmtParser.WholeFvTree.Findlist != []:
for TargetFfs in FmmtParser.WholeFvTree.Findlist:
FfsMod = FvHandler(newFmmtParser.WholeFvTree.Child[0], TargetFfs)
Status = FfsMod.ReplaceFfs()
else:
logger.error('Target Ffs not found!!!')
# 4. Data Encapsulation
if Status:
logger.debug('Start encapsulating data......')
FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
with open(outputfile, "wb") as f:
f.write(FmmtParser.FinalData)
logger.debug('Encapsulated data is saved in {}.'.format(outputfile))
def ExtractFfs(inputfile: str, Ffs_name: str, outputfile: str, Fv_name: str=None) -> None:
if not os.path.exists(inputfile):
logger.error("Invalid inputfile, can not open {}.".format(inputfile))
raise Exception("Process Failed: Invalid inputfile!")
# 1. Data Prepare
with open(inputfile, "rb") as f:
whole_data = f.read()
FmmtParser = FMMTParser(inputfile, ROOT_TREE)
# 2. DataTree Create
logger.debug('Parsing inputfile data......')
FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
logger.debug('Done!')
FmmtParser.WholeFvTree.FindNode(Ffs_name, FmmtParser.WholeFvTree.Findlist)
if Fv_name:
FindNum = len(FmmtParser.WholeFvTree.Findlist)
for index in range(FindNum-1, -1, -1):
parent = FmmtParser.WholeFvTree.Findlist[index].Parent
if parent is None or parent.Data is None:
continue
if parent.key != Fv_name and parent.Data.Name != Fv_name:
FmmtParser.WholeFvTree.Findlist.remove(FmmtParser.WholeFvTree.Findlist[index])
if FmmtParser.WholeFvTree.Findlist != []:
TargetNode = FmmtParser.WholeFvTree.Findlist[0]
if TargetNode.type == FV_TREE or TargetNode.type == SEC_FV_TREE or TargetNode.type == DATA_FV_TREE:
FinalData = struct2stream(TargetNode.Data.Header) + TargetNode.Data.Data
with open(outputfile, "wb") as f:
f.write(FinalData)
logger.debug('Extract fv data is saved in {}.'.format(outputfile))
else:
TargetFv = TargetNode.Parent
if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
TargetNode.Data.Header.State = c_uint8(
~TargetNode.Data.Header.State)
FinalData = struct2stream(TargetNode.Data.Header) + TargetNode.Data.Data
with open(outputfile, "wb") as f:
f.write(FinalData)
logger.debug('Extract ffs data is saved in {}.'.format(outputfile))
else:
logger.error('Target Ffs/Fv not found!!!')
def ShrinkFv(inputfile: str, outputfile: str) -> None:
if not os.path.exists(inputfile):
logger.error("Invalid inputfile, can not open {}.".format(inputfile))
raise Exception("Process Failed: Invalid inputfile!")
# 1. Data Prepare
with open(inputfile, "rb") as f:
whole_data = f.read()
FmmtParser = FMMTParser(inputfile, ROOT_TREE)
# 2. DataTree Create
logger.debug('Parsing inputfile data......')
FmmtParser.ParserFromRoot(FmmtParser.WholeFvTree, whole_data)
logger.debug('Done!')
TargetFv = FmmtParser.WholeFvTree.Child[0]
if TargetFv:
FvMod = FvHandler(TargetFv)
Status = FvMod.ShrinkFv()
else:
logger.error('Target Fv not found!!!')
# 4. Data Encapsulation
if Status:
logger.debug('Start encapsulating data......')
FmmtParser.Encapsulation(FmmtParser.WholeFvTree, False)
with open(outputfile, "wb") as f:
f.write(FmmtParser.FinalData)
logger.debug('Encapsulated data is saved in {}.'.format(outputfile))