| ## @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)) |