summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/FMMT
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /BaseTools/Source/Python/FMMT
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'BaseTools/Source/Python/FMMT')
-rw-r--r--BaseTools/Source/Python/FMMT/FMMT.py326
-rw-r--r--BaseTools/Source/Python/FMMT/FmmtConf.ini22
-rw-r--r--BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py828
-rw-r--r--BaseTools/Source/Python/FMMT/core/BiosTree.py484
-rw-r--r--BaseTools/Source/Python/FMMT/core/BiosTreeNode.py496
-rw-r--r--BaseTools/Source/Python/FMMT/core/FMMTOperation.py464
-rw-r--r--BaseTools/Source/Python/FMMT/core/FMMTParser.py174
-rw-r--r--BaseTools/Source/Python/FMMT/core/FvHandler.py1366
-rw-r--r--BaseTools/Source/Python/FMMT/core/GuidTools.py358
-rw-r--r--BaseTools/Source/Python/FMMT/utils/FmmtLogger.py62
10 files changed, 2290 insertions, 2290 deletions
diff --git a/BaseTools/Source/Python/FMMT/FMMT.py b/BaseTools/Source/Python/FMMT/FMMT.py
index 7505b6c88a..1b1923c2a3 100644
--- a/BaseTools/Source/Python/FMMT/FMMT.py
+++ b/BaseTools/Source/Python/FMMT/FMMT.py
@@ -1,163 +1,163 @@
-# @file
-# Firmware Module Management Tool.
-#
-# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-# Import Modules
-#
-import argparse
-from core.FMMTOperation import *
-
-parser = argparse.ArgumentParser(description='''
-View the Binary Structure of FD/FV/Ffs/Section, and Delete/Extract/Add/Replace a Ffs from/into a FV.
-''')
-parser.add_argument("--version", action="version", version='%(prog)s Version 1.0',
- help="Print debug information.")
-parser.add_argument("-v", "--View", dest="View", nargs='+',
- help="View each FV and the named files within each FV: '-v inputfile outputfile, inputfiletype(.Fd/.Fv/.ffs/.sec)'")
-parser.add_argument("-d", "--Delete", dest="Delete", nargs='+',
- help="Delete a Ffs from FV: '-d inputfile TargetFvName(Optional) TargetFfsName outputfile\
- If not given TargetFvName, all the existed target Ffs will be deleted'")
-parser.add_argument("-e", "--Extract", dest="Extract", nargs='+',
- help="Extract a Ffs Info: '-e inputfile TargetFvName(Optional) TargetFfsName outputfile\
- If not given TargetFvName, the first found target Ffs will be extracted.\
- If only given TargetFvName, not given TargetFfsName, the TargetFv will be extracted to output file'")
-parser.add_argument("-a", "--Add", dest="Add", nargs='+',
- help="Add a Ffs into a FV:'-a inputfile TargetFvName newffsfile outputfile'")
-parser.add_argument("-r", "--Replace", dest="Replace", nargs='+',
- help="Replace a Ffs in a FV: '-r inputfile TargetFvName(Optional) TargetFfsName newffsfile outputfile\
- If not given TargetFvName, all the existed target Ffs will be replaced with new Ffs file)'")
-parser.add_argument("-l", "--LayoutFileName", dest="LayoutFileName", nargs='+',
- help="The output file which saves Binary layout: '-l xxx.txt'/'-l xxx.json'\
- If only provide file format as 'txt', \
- the file will be generated with default name (Layout_'InputFileName'.txt). \
- Currently supports two formats: json, txt. More formats will be added in the future")
-parser.add_argument("-c", "--ConfigFilePath", dest="ConfigFilePath", nargs='+',
- help="Provide the target FmmtConf.ini file path: '-c C:\\Code\\FmmtConf.ini' \
- FmmtConf file saves the target guidtool used in compress/uncompress process.\
- If do not provide, FMMT tool will search the inputfile folder for FmmtConf.ini firstly, if not found,\
- the FmmtConf.ini saved in FMMT tool's folder will be used as default.")
-parser.add_argument("-s", "--ShrinkFv", dest="ShrinkFv", nargs='+',
- help="Shrink the Fv file: '-s InputFvfile OutputFvfile")
-
-def print_banner():
- print("")
-
-class FMMT():
- def __init__(self) -> None:
- self.firmware_packet = {}
-
- def SetConfigFilePath(self, configfilepath:str) -> str:
- os.environ['FmmtConfPath'] = os.path.abspath(configfilepath)
-
- def SetDestPath(self, inputfile:str) -> str:
- os.environ['FmmtConfPath'] = ''
- self.dest_path = os.path.dirname(os.path.abspath(inputfile))
- old_env = os.environ['PATH']
- os.environ['PATH'] = self.dest_path + os.pathsep + old_env
-
- def CheckFfsName(self, FfsName:str) -> str:
- try:
- return uuid.UUID(FfsName)
- except:
- return FfsName
-
- def GetFvName(self, FvName:str) -> str:
- try:
- return uuid.UUID(FvName)
- except:
- return FvName
-
- def View(self, inputfile: str, layoutfilename: str=None, outputfile: str=None) -> None:
- # ViewFile(inputfile, ROOT_TYPE, logfile, outputfile)
- self.SetDestPath(inputfile)
- filetype = os.path.splitext(inputfile)[1].lower()
- if filetype == '.fd':
- ROOT_TYPE = ROOT_TREE
- elif filetype == '.fv':
- ROOT_TYPE = ROOT_FV_TREE
- elif filetype == '.ffs':
- ROOT_TYPE = ROOT_FFS_TREE
- elif filetype == '.sec':
- ROOT_TYPE = ROOT_SECTION_TREE
- elif filetype == '.elf':
- ROOT_TYPE = ROOT_ELF_TREE
- else:
- ROOT_TYPE = ROOT_TREE
- ViewFile(inputfile, ROOT_TYPE, layoutfilename, outputfile)
-
- def Delete(self, inputfile: str, TargetFfs_name: str, outputfile: str, Fv_name: str=None) -> None:
- self.SetDestPath(inputfile)
- if Fv_name:
- DeleteFfs(inputfile, self.CheckFfsName(TargetFfs_name), outputfile, self.GetFvName(Fv_name))
- else:
- DeleteFfs(inputfile, self.CheckFfsName(TargetFfs_name), outputfile)
-
- def Extract(self, inputfile: str, Ffs_name: str, outputfile: str, Fv_name: str=None) -> None:
- self.SetDestPath(inputfile)
- if Fv_name:
- ExtractFfs(inputfile, self.CheckFfsName(Ffs_name), outputfile, self.GetFvName(Fv_name))
- else:
- ExtractFfs(inputfile, self.CheckFfsName(Ffs_name), outputfile)
-
- def Add(self, inputfile: str, Fv_name: str, newffsfile: str, outputfile: str) -> None:
- self.SetDestPath(inputfile)
- AddNewFfs(inputfile, self.CheckFfsName(Fv_name), newffsfile, outputfile)
-
- def Replace(self,inputfile: str, Ffs_name: str, newffsfile: str, outputfile: str, Fv_name: str=None) -> None:
- self.SetDestPath(inputfile)
- if Fv_name:
- ReplaceFfs(inputfile, self.CheckFfsName(Ffs_name), newffsfile, outputfile, self.GetFvName(Fv_name))
- else:
- ReplaceFfs(inputfile, self.CheckFfsName(Ffs_name), newffsfile, outputfile)
-
- def Shrink(self,inputfile: str, outputfile: str) -> None:
- self.SetDestPath(inputfile)
- ShrinkFv(inputfile, outputfile)
-
-def main():
- args=parser.parse_args()
- status=0
-
- try:
- fmmt=FMMT()
- if args.ConfigFilePath:
- fmmt.SetConfigFilePath(args.ConfigFilePath[0])
- if args.View:
- if args.LayoutFileName:
- fmmt.View(args.View[0], args.LayoutFileName[0])
- else:
- fmmt.View(args.View[0])
- elif args.Delete:
- if len(args.Delete) == 4:
- fmmt.Delete(args.Delete[0],args.Delete[2],args.Delete[3],args.Delete[1])
- else:
- fmmt.Delete(args.Delete[0],args.Delete[1],args.Delete[2])
- elif args.Extract:
- if len(args.Extract) == 4:
- fmmt.Extract(args.Extract[0],args.Extract[2],args.Extract[3], args.Extract[1])
- else:
- fmmt.Extract(args.Extract[0],args.Extract[1],args.Extract[2])
- elif args.Add:
- fmmt.Add(args.Add[0],args.Add[1],args.Add[2],args.Add[3])
- elif args.Replace:
- if len(args.Replace) == 5:
- fmmt.Replace(args.Replace[0],args.Replace[2],args.Replace[3],args.Replace[4],args.Replace[1])
- else:
- fmmt.Replace(args.Replace[0],args.Replace[1],args.Replace[2],args.Replace[3])
- elif args.ShrinkFv:
- fmmt.Shrink(args.ShrinkFv[0], args.ShrinkFv[1])
- else:
- parser.print_help()
- except Exception as e:
- print(e)
-
- return status
-
-
-if __name__ == "__main__":
- exit(main())
+# @file
+# Firmware Module Management Tool.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# Import Modules
+#
+import argparse
+from core.FMMTOperation import *
+
+parser = argparse.ArgumentParser(description='''
+View the Binary Structure of FD/FV/Ffs/Section, and Delete/Extract/Add/Replace a Ffs from/into a FV.
+''')
+parser.add_argument("--version", action="version", version='%(prog)s Version 1.0',
+ help="Print debug information.")
+parser.add_argument("-v", "--View", dest="View", nargs='+',
+ help="View each FV and the named files within each FV: '-v inputfile outputfile, inputfiletype(.Fd/.Fv/.ffs/.sec)'")
+parser.add_argument("-d", "--Delete", dest="Delete", nargs='+',
+ help="Delete a Ffs from FV: '-d inputfile TargetFvName(Optional) TargetFfsName outputfile\
+ If not given TargetFvName, all the existed target Ffs will be deleted'")
+parser.add_argument("-e", "--Extract", dest="Extract", nargs='+',
+ help="Extract a Ffs Info: '-e inputfile TargetFvName(Optional) TargetFfsName outputfile\
+ If not given TargetFvName, the first found target Ffs will be extracted.\
+ If only given TargetFvName, not given TargetFfsName, the TargetFv will be extracted to output file'")
+parser.add_argument("-a", "--Add", dest="Add", nargs='+',
+ help="Add a Ffs into a FV:'-a inputfile TargetFvName newffsfile outputfile'")
+parser.add_argument("-r", "--Replace", dest="Replace", nargs='+',
+ help="Replace a Ffs in a FV: '-r inputfile TargetFvName(Optional) TargetFfsName newffsfile outputfile\
+ If not given TargetFvName, all the existed target Ffs will be replaced with new Ffs file)'")
+parser.add_argument("-l", "--LayoutFileName", dest="LayoutFileName", nargs='+',
+ help="The output file which saves Binary layout: '-l xxx.txt'/'-l xxx.json'\
+ If only provide file format as 'txt', \
+ the file will be generated with default name (Layout_'InputFileName'.txt). \
+ Currently supports two formats: json, txt. More formats will be added in the future")
+parser.add_argument("-c", "--ConfigFilePath", dest="ConfigFilePath", nargs='+',
+ help="Provide the target FmmtConf.ini file path: '-c C:\\Code\\FmmtConf.ini' \
+ FmmtConf file saves the target guidtool used in compress/uncompress process.\
+ If do not provide, FMMT tool will search the inputfile folder for FmmtConf.ini firstly, if not found,\
+ the FmmtConf.ini saved in FMMT tool's folder will be used as default.")
+parser.add_argument("-s", "--ShrinkFv", dest="ShrinkFv", nargs='+',
+ help="Shrink the Fv file: '-s InputFvfile OutputFvfile")
+
+def print_banner():
+ print("")
+
+class FMMT():
+ def __init__(self) -> None:
+ self.firmware_packet = {}
+
+ def SetConfigFilePath(self, configfilepath:str) -> str:
+ os.environ['FmmtConfPath'] = os.path.abspath(configfilepath)
+
+ def SetDestPath(self, inputfile:str) -> str:
+ os.environ['FmmtConfPath'] = ''
+ self.dest_path = os.path.dirname(os.path.abspath(inputfile))
+ old_env = os.environ['PATH']
+ os.environ['PATH'] = self.dest_path + os.pathsep + old_env
+
+ def CheckFfsName(self, FfsName:str) -> str:
+ try:
+ return uuid.UUID(FfsName)
+ except:
+ return FfsName
+
+ def GetFvName(self, FvName:str) -> str:
+ try:
+ return uuid.UUID(FvName)
+ except:
+ return FvName
+
+ def View(self, inputfile: str, layoutfilename: str=None, outputfile: str=None) -> None:
+ # ViewFile(inputfile, ROOT_TYPE, logfile, outputfile)
+ self.SetDestPath(inputfile)
+ filetype = os.path.splitext(inputfile)[1].lower()
+ if filetype == '.fd':
+ ROOT_TYPE = ROOT_TREE
+ elif filetype == '.fv':
+ ROOT_TYPE = ROOT_FV_TREE
+ elif filetype == '.ffs':
+ ROOT_TYPE = ROOT_FFS_TREE
+ elif filetype == '.sec':
+ ROOT_TYPE = ROOT_SECTION_TREE
+ elif filetype == '.elf':
+ ROOT_TYPE = ROOT_ELF_TREE
+ else:
+ ROOT_TYPE = ROOT_TREE
+ ViewFile(inputfile, ROOT_TYPE, layoutfilename, outputfile)
+
+ def Delete(self, inputfile: str, TargetFfs_name: str, outputfile: str, Fv_name: str=None) -> None:
+ self.SetDestPath(inputfile)
+ if Fv_name:
+ DeleteFfs(inputfile, self.CheckFfsName(TargetFfs_name), outputfile, self.GetFvName(Fv_name))
+ else:
+ DeleteFfs(inputfile, self.CheckFfsName(TargetFfs_name), outputfile)
+
+ def Extract(self, inputfile: str, Ffs_name: str, outputfile: str, Fv_name: str=None) -> None:
+ self.SetDestPath(inputfile)
+ if Fv_name:
+ ExtractFfs(inputfile, self.CheckFfsName(Ffs_name), outputfile, self.GetFvName(Fv_name))
+ else:
+ ExtractFfs(inputfile, self.CheckFfsName(Ffs_name), outputfile)
+
+ def Add(self, inputfile: str, Fv_name: str, newffsfile: str, outputfile: str) -> None:
+ self.SetDestPath(inputfile)
+ AddNewFfs(inputfile, self.CheckFfsName(Fv_name), newffsfile, outputfile)
+
+ def Replace(self,inputfile: str, Ffs_name: str, newffsfile: str, outputfile: str, Fv_name: str=None) -> None:
+ self.SetDestPath(inputfile)
+ if Fv_name:
+ ReplaceFfs(inputfile, self.CheckFfsName(Ffs_name), newffsfile, outputfile, self.GetFvName(Fv_name))
+ else:
+ ReplaceFfs(inputfile, self.CheckFfsName(Ffs_name), newffsfile, outputfile)
+
+ def Shrink(self,inputfile: str, outputfile: str) -> None:
+ self.SetDestPath(inputfile)
+ ShrinkFv(inputfile, outputfile)
+
+def main():
+ args=parser.parse_args()
+ status=0
+
+ try:
+ fmmt=FMMT()
+ if args.ConfigFilePath:
+ fmmt.SetConfigFilePath(args.ConfigFilePath[0])
+ if args.View:
+ if args.LayoutFileName:
+ fmmt.View(args.View[0], args.LayoutFileName[0])
+ else:
+ fmmt.View(args.View[0])
+ elif args.Delete:
+ if len(args.Delete) == 4:
+ fmmt.Delete(args.Delete[0],args.Delete[2],args.Delete[3],args.Delete[1])
+ else:
+ fmmt.Delete(args.Delete[0],args.Delete[1],args.Delete[2])
+ elif args.Extract:
+ if len(args.Extract) == 4:
+ fmmt.Extract(args.Extract[0],args.Extract[2],args.Extract[3], args.Extract[1])
+ else:
+ fmmt.Extract(args.Extract[0],args.Extract[1],args.Extract[2])
+ elif args.Add:
+ fmmt.Add(args.Add[0],args.Add[1],args.Add[2],args.Add[3])
+ elif args.Replace:
+ if len(args.Replace) == 5:
+ fmmt.Replace(args.Replace[0],args.Replace[2],args.Replace[3],args.Replace[4],args.Replace[1])
+ else:
+ fmmt.Replace(args.Replace[0],args.Replace[1],args.Replace[2],args.Replace[3])
+ elif args.ShrinkFv:
+ fmmt.Shrink(args.ShrinkFv[0], args.ShrinkFv[1])
+ else:
+ parser.print_help()
+ except Exception as e:
+ print(e)
+
+ return status
+
+
+if __name__ == "__main__":
+ exit(main())
diff --git a/BaseTools/Source/Python/FMMT/FmmtConf.ini b/BaseTools/Source/Python/FMMT/FmmtConf.ini
index aa2444f11b..338e075ce5 100644
--- a/BaseTools/Source/Python/FMMT/FmmtConf.ini
+++ b/BaseTools/Source/Python/FMMT/FmmtConf.ini
@@ -1,11 +1,11 @@
-## @file
-# This file is used to define the FMMT dependent external tool guid.
-#
-# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-a31280ad-481e-41b6-95e8-127f4c984779 TIANO TianoCompress
-ee4e5898-3914-4259-9d6e-dc7bd79403cf LZMA LzmaCompress
-fc1bcdb0-7d31-49aa-936a-a4600d9dd083 CRC32 GenCrc32
-d42ae6bd-1352-4bfb-909a-ca72a6eae889 LZMAF86 LzmaF86Compress
-3d532050-5cda-4fd0-879e-0f7f630d5afb BROTLI BrotliCompress
+## @file
+# This file is used to define the FMMT dependent external tool guid.
+#
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+a31280ad-481e-41b6-95e8-127f4c984779 TIANO TianoCompress
+ee4e5898-3914-4259-9d6e-dc7bd79403cf LZMA LzmaCompress
+fc1bcdb0-7d31-49aa-936a-a4600d9dd083 CRC32 GenCrc32
+d42ae6bd-1352-4bfb-909a-ca72a6eae889 LZMAF86 LzmaF86Compress
+3d532050-5cda-4fd0-879e-0f7f630d5afb BROTLI BrotliCompress
diff --git a/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py b/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
index de174f26ab..9eca6c1950 100644
--- a/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
+++ b/BaseTools/Source/Python/FMMT/core/BinaryFactoryProduct.py
@@ -1,414 +1,414 @@
-## @file
-# This file is used to implement of the various bianry parser.
-#
-# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-from re import T
-import copy
-import os
-import sys
-from FirmwareStorageFormat.Common import *
-from core.BiosTreeNode import *
-from core.BiosTree import *
-from core.GuidTools import GUIDTools
-from utils.FmmtLogger import FmmtLogger as logger
-
-ROOT_TREE = 'ROOT'
-ROOT_ELF_TREE = 'ROOT_ELF_TREE'
-ROOT_FV_TREE = 'ROOT_FV_TREE'
-ROOT_FFS_TREE = 'ROOT_FFS_TREE'
-ROOT_SECTION_TREE = 'ROOT_SECTION_TREE'
-
-ELF_TREE = 'ELF'
-ELF_SECTION_TREE = 'ELF_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'
-Fv_count = 0
-
-## Abstract factory
-class BinaryFactory():
- type:list = []
-
- def Create_Product():
- pass
-
-class BinaryProduct():
- ## Use GuidTool to decompress data.
- def DeCompressData(self, GuidTool, Section_Data: bytes, FileName) -> bytes:
- guidtool = GUIDTools().__getitem__(struct2stream(GuidTool))
- if not guidtool.ifexist:
- logger.error("GuidTool {} is not found when decompressing {} file.\n".format(guidtool.command, FileName))
- raise Exception("Process Failed: GuidTool not found!")
- DecompressedData = guidtool.unpack(Section_Data)
- return DecompressedData
-
- def ParserData():
- pass
-
-class ElfFactory(BinaryFactory):
- type = [ROOT_ELF_TREE, ELF_TREE]
-
- def Create_Product():
- return ElfProduct()
-
-class SectionFactory(BinaryFactory):
- type = [SECTION_TREE]
-
- def Create_Product():
- return SectionProduct()
-
-class FfsFactory(BinaryFactory):
- type = [ROOT_SECTION_TREE, FFS_TREE]
-
- def Create_Product():
- return FfsProduct()
-
-class FvFactory(BinaryFactory):
- type = [ROOT_FFS_TREE, FV_TREE, SEC_FV_TREE]
-
- def Create_Product():
- return FvProduct()
-
-class FdFactory(BinaryFactory):
- type = [ROOT_FV_TREE, ROOT_TREE]
-
- def Create_Product():
- return FdProduct()
-
-class SectionProduct(BinaryProduct):
- ## Decompress the compressed section.
- def ParserData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- if Section_Tree.Data.Type == 0x01:
- Section_Tree.Data.OriData = Section_Tree.Data.Data
- self.ParserSection(Section_Tree, b'')
- # Guided Define Section
- elif Section_Tree.Data.Type == 0x02:
- Section_Tree.Data.OriData = Section_Tree.Data.Data
- DeCompressGuidTool = Section_Tree.Data.ExtHeader.SectionDefinitionGuid
- Section_Tree.Data.Data = self.DeCompressData(DeCompressGuidTool, Section_Tree.Data.Data, Section_Tree.Parent.Data.Name)
- Section_Tree.Data.Size = len(Section_Tree.Data.Data) + Section_Tree.Data.HeaderLength
- self.ParserSection(Section_Tree, b'')
- elif Section_Tree.Data.Type == 0x03:
- Section_Tree.Data.OriData = Section_Tree.Data.Data
- self.ParserSection(Section_Tree, b'')
- # SEC_FV Section
- elif Section_Tree.Data.Type == 0x17:
- global Fv_count
- Sec_Fv_Info = FvNode(Fv_count, Section_Tree.Data.Data)
- Sec_Fv_Tree = BIOSTREE('FV'+ str(Fv_count))
- Sec_Fv_Tree.type = SEC_FV_TREE
- Sec_Fv_Tree.Data = Sec_Fv_Info
- Sec_Fv_Tree.Data.HOffset = Section_Tree.Data.DOffset
- Sec_Fv_Tree.Data.DOffset = Sec_Fv_Tree.Data.HOffset + Sec_Fv_Tree.Data.Header.HeaderLength
- Sec_Fv_Tree.Data.Data = Section_Tree.Data.Data[Sec_Fv_Tree.Data.Header.HeaderLength:]
- Section_Tree.insertChild(Sec_Fv_Tree)
- Fv_count += 1
-
- def ParserSection(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- Rel_Offset = 0
- Section_Offset = 0
- # Get the Data from parent tree, if do not have the tree then get it from the whole_data.
- if ParTree.Data != None:
- Data_Size = len(ParTree.Data.Data)
- Section_Offset = ParTree.Data.DOffset
- Whole_Data = ParTree.Data.Data
- else:
- Data_Size = len(Whole_Data)
- # Parser all the data to collect all the Section recorded in its Parent Section.
- while Rel_Offset < Data_Size:
- # Create a SectionNode and set it as the SectionTree's Data
- Section_Info = SectionNode(Whole_Data[Rel_Offset:])
- Section_Tree = BIOSTREE(Section_Info.Name)
- Section_Tree.type = SECTION_TREE
- Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.HeaderLength: Rel_Offset+Section_Info.Size]
- Section_Info.DOffset = Section_Offset + Section_Info.HeaderLength + Rel_Whole_Offset
- Section_Info.HOffset = Section_Offset + Rel_Whole_Offset
- Section_Info.ROffset = Rel_Offset
- if Section_Info.Header.Type == 0:
- break
- # The final Section in parent Section does not need to add padding, else must be 4-bytes align with parent Section start offset
- Pad_Size = 0
- if (Rel_Offset+Section_Info.HeaderLength+len(Section_Info.Data) != Data_Size):
- Pad_Size = GetPadSize(Section_Info.Size, SECTION_COMMON_ALIGNMENT)
- Section_Info.PadData = Pad_Size * b'\x00'
- if Section_Info.Header.Type == 0x02:
- Section_Info.DOffset = Section_Offset + Section_Info.ExtHeader.DataOffset + Rel_Whole_Offset
- Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.ExtHeader.DataOffset: Rel_Offset+Section_Info.Size]
- if Section_Info.Header.Type == 0x14:
- ParTree.Data.Version = Section_Info.ExtHeader.GetVersionString()
- if Section_Info.Header.Type == 0x15:
- ParTree.Data.UiName = Section_Info.ExtHeader.GetUiString()
- if Section_Info.Header.Type == 0x19:
- if Section_Info.Data.replace(b'\x00', b'') == b'':
- Section_Info.IsPadSection = True
- Section_Offset += Section_Info.Size + Pad_Size
- Rel_Offset += Section_Info.Size + Pad_Size
- Section_Tree.Data = Section_Info
- ParTree.insertChild(Section_Tree)
-
-class FfsProduct(BinaryProduct):
- # ParserFFs / GetSection
- def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- Rel_Offset = 0
- Section_Offset = 0
- # Get the Data from parent tree, if do not have the tree then get it from the whole_data.
- if ParTree.Data != None:
- Data_Size = len(ParTree.Data.Data)
- Section_Offset = ParTree.Data.DOffset
- Whole_Data = ParTree.Data.Data
- else:
- Data_Size = len(Whole_Data)
- # Parser all the data to collect all the Section recorded in Ffs.
- while Rel_Offset < Data_Size:
- # Create a SectionNode and set it as the SectionTree's Data
- Section_Info = SectionNode(Whole_Data[Rel_Offset:])
- Section_Tree = BIOSTREE(Section_Info.Name)
- Section_Tree.type = SECTION_TREE
- Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.HeaderLength: Rel_Offset+Section_Info.Size]
- Section_Info.DOffset = Section_Offset + Section_Info.HeaderLength + Rel_Whole_Offset
- Section_Info.HOffset = Section_Offset + Rel_Whole_Offset
- Section_Info.ROffset = Rel_Offset
- if Section_Info.Header.Type == 0:
- break
- # The final Section in Ffs does not need to add padding, else must be 4-bytes align with Ffs start offset
- Pad_Size = 0
- if (Rel_Offset+Section_Info.HeaderLength+len(Section_Info.Data) != Data_Size):
- Pad_Size = GetPadSize(Section_Info.Size, SECTION_COMMON_ALIGNMENT)
- Section_Info.PadData = Pad_Size * b'\x00'
- if Section_Info.Header.Type == 0x02:
- Section_Info.DOffset = Section_Offset + Section_Info.ExtHeader.DataOffset + Rel_Whole_Offset
- Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.ExtHeader.DataOffset: Rel_Offset+Section_Info.Size]
- # If Section is Version or UI type, it saves the version and UI info of its parent Ffs.
- if Section_Info.Header.Type == 0x14:
- ParTree.Data.Version = Section_Info.ExtHeader.GetVersionString()
- if Section_Info.Header.Type == 0x15:
- ParTree.Data.UiName = Section_Info.ExtHeader.GetUiString()
- if Section_Info.Header.Type == 0x19:
- if Section_Info.Data.replace(b'\x00', b'') == b'':
- Section_Info.IsPadSection = True
- Section_Offset += Section_Info.Size + Pad_Size
- Rel_Offset += Section_Info.Size + Pad_Size
- Section_Tree.Data = Section_Info
- ParTree.insertChild(Section_Tree)
-
-class FvProduct(BinaryProduct):
- ## ParserFv / GetFfs
- def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- Ffs_Offset = 0
- Rel_Offset = 0
- # Get the Data from parent tree, if do not have the tree then get it from the whole_data.
- if ParTree.Data != None:
- Data_Size = len(ParTree.Data.Data)
- Ffs_Offset = ParTree.Data.DOffset
- Whole_Data = ParTree.Data.Data
- else:
- Data_Size = len(Whole_Data)
- # Parser all the data to collect all the Ffs recorded in Fv.
- while Rel_Offset < Data_Size:
- # Create a FfsNode and set it as the FFsTree's Data
- if Data_Size - Rel_Offset < 24:
- Ffs_Tree = BIOSTREE('Free_Space')
- Ffs_Tree.type = FFS_FREE_SPACE
- Ffs_Tree.Data = FreeSpaceNode(Whole_Data[Rel_Offset:])
- Ffs_Tree.Data.HOffset = Ffs_Offset + Rel_Whole_Offset
- Ffs_Tree.Data.DOffset = Ffs_Tree.Data.HOffset
- ParTree.Data.Free_Space = Data_Size - Rel_Offset
- ParTree.insertChild(Ffs_Tree)
- Rel_Offset = Data_Size
- else:
- Ffs_Info = FfsNode(Whole_Data[Rel_Offset:])
- Ffs_Tree = BIOSTREE(Ffs_Info.Name)
- Ffs_Info.HOffset = Ffs_Offset + Rel_Whole_Offset
- Ffs_Info.DOffset = Ffs_Offset + Ffs_Info.Header.HeaderLength + Rel_Whole_Offset
- Ffs_Info.ROffset = Rel_Offset
- if Ffs_Info.Name == PADVECTOR:
- Ffs_Tree.type = FFS_PAD
- Ffs_Info.Data = Whole_Data[Rel_Offset+Ffs_Info.Header.HeaderLength: Rel_Offset+Ffs_Info.Size]
- Ffs_Info.Size = len(Ffs_Info.Data) + Ffs_Info.Header.HeaderLength
- # if current Ffs is the final ffs of Fv and full of b'\xff', define it with Free_Space
- if struct2stream(Ffs_Info.Header).replace(b'\xff', b'') == b'':
- Ffs_Tree.type = FFS_FREE_SPACE
- Ffs_Info.Data = Whole_Data[Rel_Offset:]
- Ffs_Info.Size = len(Ffs_Info.Data)
- ParTree.Data.Free_Space = Ffs_Info.Size
- else:
- Ffs_Tree.type = FFS_TREE
- Ffs_Info.Data = Whole_Data[Rel_Offset+Ffs_Info.Header.HeaderLength: Rel_Offset+Ffs_Info.Size]
- # The final Ffs in Fv does not need to add padding, else must be 8-bytes align with Fv start offset
- Pad_Size = 0
- if Ffs_Tree.type != FFS_FREE_SPACE and (Rel_Offset+Ffs_Info.Header.HeaderLength+len(Ffs_Info.Data) != Data_Size):
- Pad_Size = GetPadSize(Ffs_Info.Size, FFS_COMMON_ALIGNMENT)
- Ffs_Info.PadData = Pad_Size * b'\xff'
- Ffs_Offset += Ffs_Info.Size + Pad_Size
- Rel_Offset += Ffs_Info.Size + Pad_Size
- Ffs_Tree.Data = Ffs_Info
- ParTree.insertChild(Ffs_Tree)
-
-class FdProduct(BinaryProduct):
- type = [ROOT_FV_TREE, ROOT_TREE]
-
- ## Create DataTree with first level /fv Info, then parser each Fv.
- def ParserData(self, WholeFvTree, whole_data: bytes=b'', offset: int=0) -> None:
- # Get all Fv image in Fd with offset and length
- Fd_Struct = self.GetFvFromFd(whole_data)
- data_size = len(whole_data)
- Binary_count = 0
- global Fv_count
- # If the first Fv image is the Binary Fv, add it into the tree.
- if Fd_Struct[0][1] != 0:
- Binary_node = BIOSTREE('BINARY'+ str(Binary_count))
- Binary_node.type = BINARY_DATA
- Binary_node.Data = BinaryNode(str(Binary_count))
- Binary_node.Data.Data = whole_data[:Fd_Struct[0][1]]
- Binary_node.Data.Size = len(Binary_node.Data.Data)
- Binary_node.Data.HOffset = 0 + offset
- WholeFvTree.insertChild(Binary_node)
- Binary_count += 1
- # Add the first collected Fv image into the tree.
- Cur_node = BIOSTREE(Fd_Struct[0][0]+ str(Fv_count))
- Cur_node.type = Fd_Struct[0][0]
- Cur_node.Data = FvNode(Fv_count, whole_data[Fd_Struct[0][1]:Fd_Struct[0][1]+Fd_Struct[0][2][0]])
- Cur_node.Data.HOffset = Fd_Struct[0][1] + offset
- Cur_node.Data.DOffset = Cur_node.Data.HOffset+Cur_node.Data.Header.HeaderLength
- Cur_node.Data.Data = whole_data[Fd_Struct[0][1]+Cur_node.Data.Header.HeaderLength:Fd_Struct[0][1]+Cur_node.Data.Size]
- WholeFvTree.insertChild(Cur_node)
- Fv_count += 1
- Fv_num = len(Fd_Struct)
- # Add all the collected Fv image and the Binary Fv image between them into the tree.
- for i in range(Fv_num-1):
- if Fd_Struct[i][1]+Fd_Struct[i][2][0] != Fd_Struct[i+1][1]:
- Binary_node = BIOSTREE('BINARY'+ str(Binary_count))
- Binary_node.type = BINARY_DATA
- Binary_node.Data = BinaryNode(str(Binary_count))
- Binary_node.Data.Data = whole_data[Fd_Struct[i][1]+Fd_Struct[i][2][0]:Fd_Struct[i+1][1]]
- Binary_node.Data.Size = len(Binary_node.Data.Data)
- Binary_node.Data.HOffset = Fd_Struct[i][1]+Fd_Struct[i][2][0] + offset
- WholeFvTree.insertChild(Binary_node)
- Binary_count += 1
- Cur_node = BIOSTREE(Fd_Struct[i+1][0]+ str(Fv_count))
- Cur_node.type = Fd_Struct[i+1][0]
- Cur_node.Data = FvNode(Fv_count, whole_data[Fd_Struct[i+1][1]:Fd_Struct[i+1][1]+Fd_Struct[i+1][2][0]])
- Cur_node.Data.HOffset = Fd_Struct[i+1][1] + offset
- Cur_node.Data.DOffset = Cur_node.Data.HOffset+Cur_node.Data.Header.HeaderLength
- Cur_node.Data.Data = whole_data[Fd_Struct[i+1][1]+Cur_node.Data.Header.HeaderLength:Fd_Struct[i+1][1]+Cur_node.Data.Size]
- WholeFvTree.insertChild(Cur_node)
- Fv_count += 1
- # If the final Fv image is the Binary Fv, add it into the tree
- if Fd_Struct[-1][1] + Fd_Struct[-1][2][0] != data_size:
- Binary_node = BIOSTREE('BINARY'+ str(Binary_count))
- Binary_node.type = BINARY_DATA
- Binary_node.Data = BinaryNode(str(Binary_count))
- Binary_node.Data.Data = whole_data[Fd_Struct[-1][1]+Fd_Struct[-1][2][0]:]
- Binary_node.Data.Size = len(Binary_node.Data.Data)
- Binary_node.Data.HOffset = Fd_Struct[-1][1]+Fd_Struct[-1][2][0] + offset
- WholeFvTree.insertChild(Binary_node)
- Binary_count += 1
-
- ## Get the first level Fv from Fd file.
- def GetFvFromFd(self, whole_data: bytes=b'') -> list:
- Fd_Struct = []
- data_size = len(whole_data)
- cur_index = 0
- # Get all the EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE FV image offset and length.
- while cur_index < data_size:
- if EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE in whole_data[cur_index:]:
- target_index = whole_data[cur_index:].index(EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE) + cur_index
- if whole_data[target_index+24:target_index+28] == FVH_SIGNATURE:
- Fd_Struct.append([FV_TREE, target_index - 16, unpack("Q", whole_data[target_index+16:target_index+24])])
- cur_index = Fd_Struct[-1][1] + Fd_Struct[-1][2][0]
- else:
- cur_index = target_index + 16
- else:
- cur_index = data_size
- cur_index = 0
- # Get all the EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE FV image offset and length.
- while cur_index < data_size:
- if EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE in whole_data[cur_index:]:
- target_index = whole_data[cur_index:].index(EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE) + cur_index
- if whole_data[target_index+24:target_index+28] == FVH_SIGNATURE:
- Fd_Struct.append([FV_TREE, target_index - 16, unpack("Q", whole_data[target_index+16:target_index+24])])
- cur_index = Fd_Struct[-1][1] + Fd_Struct[-1][2][0]
- else:
- cur_index = target_index + 16
- else:
- cur_index = data_size
- cur_index = 0
- # Get all the EFI_SYSTEM_NVDATA_FV_GUID_BYTE FV image offset and length.
- while cur_index < data_size:
- if EFI_SYSTEM_NVDATA_FV_GUID_BYTE in whole_data[cur_index:]:
- target_index = whole_data[cur_index:].index(EFI_SYSTEM_NVDATA_FV_GUID_BYTE) + cur_index
- if whole_data[target_index+24:target_index+28] == FVH_SIGNATURE:
- Fd_Struct.append([DATA_FV_TREE, target_index - 16, unpack("Q", whole_data[target_index+16:target_index+24])])
- cur_index = Fd_Struct[-1][1] + Fd_Struct[-1][2][0]
- else:
- cur_index = target_index + 16
- else:
- cur_index = data_size
- # Sort all the collect Fv image with offset.
- Fd_Struct.sort(key=lambda x:x[1])
- tmp_struct = copy.deepcopy(Fd_Struct)
- tmp_index = 0
- Fv_num = len(Fd_Struct)
- # Remove the Fv image included in another Fv image.
- for i in range(1,Fv_num):
- if tmp_struct[i][1]+tmp_struct[i][2][0] < tmp_struct[i-1][1]+tmp_struct[i-1][2][0]:
- Fd_Struct.remove(Fd_Struct[i-tmp_index])
- tmp_index += 1
- return Fd_Struct
-
-class ElfSectionProduct(BinaryProduct):
- ## Decompress the compressed section.
- def ParserData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- pass
- def ParserSectionData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- pass
- def ParserProgramData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- pass
-
-class ElfProduct(BinaryProduct):
-
- def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
- Elf_Info = ElfNode(Whole_Data)
- if Elf_Info.Header.ELF_PHOff != 0:
- Elf_Info.GetProgramList(Whole_Data[Elf_Info.Header.ELF_PHOff:])
- if Elf_Info.Header.ELF_SHOff != 0:
- Elf_Info.GetSectionList(Whole_Data[Elf_Info.Header.ELF_SHOff:])
- Elf_Info.FindUPLDSection(Whole_Data)
- Elf_Tree = BIOSTREE(Elf_Info.Name)
- Elf_Tree.type = ELF_TREE
- Elf_Info.Data = Whole_Data[Elf_Info.HeaderLength:]
- Elf_Tree.Data = Elf_Info
- ParTree.insertChild(Elf_Tree)
-
-class ParserEntry():
- FactoryTable:dict = {
- SECTION_TREE: SectionFactory,
- ROOT_SECTION_TREE: FfsFactory,
- FFS_TREE: FfsFactory,
- ROOT_FFS_TREE: FvFactory,
- FV_TREE: FvFactory,
- SEC_FV_TREE: FvFactory,
- ROOT_FV_TREE: FdFactory,
- ROOT_TREE: FdFactory,
- ROOT_ELF_TREE: ElfFactory,
- }
-
- def GetTargetFactory(self, Tree_type: str) -> BinaryFactory:
- if Tree_type in self.FactoryTable:
- return self.FactoryTable[Tree_type]
-
- def Generate_Product(self, TargetFactory: BinaryFactory, Tree, Data: bytes, Offset: int) -> None:
- New_Product = TargetFactory.Create_Product()
- New_Product.ParserData(Tree, Data, Offset)
-
- def DataParser(self, Tree, Data: bytes, Offset: int) -> None:
- TargetFactory = self.GetTargetFactory(Tree.type)
- if TargetFactory:
- self.Generate_Product(TargetFactory, Tree, Data, Offset)
+## @file
+# This file is used to implement of the various bianry parser.
+#
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+from re import T
+import copy
+import os
+import sys
+from FirmwareStorageFormat.Common import *
+from core.BiosTreeNode import *
+from core.BiosTree import *
+from core.GuidTools import GUIDTools
+from utils.FmmtLogger import FmmtLogger as logger
+
+ROOT_TREE = 'ROOT'
+ROOT_ELF_TREE = 'ROOT_ELF_TREE'
+ROOT_FV_TREE = 'ROOT_FV_TREE'
+ROOT_FFS_TREE = 'ROOT_FFS_TREE'
+ROOT_SECTION_TREE = 'ROOT_SECTION_TREE'
+
+ELF_TREE = 'ELF'
+ELF_SECTION_TREE = 'ELF_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'
+Fv_count = 0
+
+## Abstract factory
+class BinaryFactory():
+ type:list = []
+
+ def Create_Product():
+ pass
+
+class BinaryProduct():
+ ## Use GuidTool to decompress data.
+ def DeCompressData(self, GuidTool, Section_Data: bytes, FileName) -> bytes:
+ guidtool = GUIDTools().__getitem__(struct2stream(GuidTool))
+ if not guidtool.ifexist:
+ logger.error("GuidTool {} is not found when decompressing {} file.\n".format(guidtool.command, FileName))
+ raise Exception("Process Failed: GuidTool not found!")
+ DecompressedData = guidtool.unpack(Section_Data)
+ return DecompressedData
+
+ def ParserData():
+ pass
+
+class ElfFactory(BinaryFactory):
+ type = [ROOT_ELF_TREE, ELF_TREE]
+
+ def Create_Product():
+ return ElfProduct()
+
+class SectionFactory(BinaryFactory):
+ type = [SECTION_TREE]
+
+ def Create_Product():
+ return SectionProduct()
+
+class FfsFactory(BinaryFactory):
+ type = [ROOT_SECTION_TREE, FFS_TREE]
+
+ def Create_Product():
+ return FfsProduct()
+
+class FvFactory(BinaryFactory):
+ type = [ROOT_FFS_TREE, FV_TREE, SEC_FV_TREE]
+
+ def Create_Product():
+ return FvProduct()
+
+class FdFactory(BinaryFactory):
+ type = [ROOT_FV_TREE, ROOT_TREE]
+
+ def Create_Product():
+ return FdProduct()
+
+class SectionProduct(BinaryProduct):
+ ## Decompress the compressed section.
+ def ParserData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ if Section_Tree.Data.Type == 0x01:
+ Section_Tree.Data.OriData = Section_Tree.Data.Data
+ self.ParserSection(Section_Tree, b'')
+ # Guided Define Section
+ elif Section_Tree.Data.Type == 0x02:
+ Section_Tree.Data.OriData = Section_Tree.Data.Data
+ DeCompressGuidTool = Section_Tree.Data.ExtHeader.SectionDefinitionGuid
+ Section_Tree.Data.Data = self.DeCompressData(DeCompressGuidTool, Section_Tree.Data.Data, Section_Tree.Parent.Data.Name)
+ Section_Tree.Data.Size = len(Section_Tree.Data.Data) + Section_Tree.Data.HeaderLength
+ self.ParserSection(Section_Tree, b'')
+ elif Section_Tree.Data.Type == 0x03:
+ Section_Tree.Data.OriData = Section_Tree.Data.Data
+ self.ParserSection(Section_Tree, b'')
+ # SEC_FV Section
+ elif Section_Tree.Data.Type == 0x17:
+ global Fv_count
+ Sec_Fv_Info = FvNode(Fv_count, Section_Tree.Data.Data)
+ Sec_Fv_Tree = BIOSTREE('FV'+ str(Fv_count))
+ Sec_Fv_Tree.type = SEC_FV_TREE
+ Sec_Fv_Tree.Data = Sec_Fv_Info
+ Sec_Fv_Tree.Data.HOffset = Section_Tree.Data.DOffset
+ Sec_Fv_Tree.Data.DOffset = Sec_Fv_Tree.Data.HOffset + Sec_Fv_Tree.Data.Header.HeaderLength
+ Sec_Fv_Tree.Data.Data = Section_Tree.Data.Data[Sec_Fv_Tree.Data.Header.HeaderLength:]
+ Section_Tree.insertChild(Sec_Fv_Tree)
+ Fv_count += 1
+
+ def ParserSection(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ Rel_Offset = 0
+ Section_Offset = 0
+ # Get the Data from parent tree, if do not have the tree then get it from the whole_data.
+ if ParTree.Data != None:
+ Data_Size = len(ParTree.Data.Data)
+ Section_Offset = ParTree.Data.DOffset
+ Whole_Data = ParTree.Data.Data
+ else:
+ Data_Size = len(Whole_Data)
+ # Parser all the data to collect all the Section recorded in its Parent Section.
+ while Rel_Offset < Data_Size:
+ # Create a SectionNode and set it as the SectionTree's Data
+ Section_Info = SectionNode(Whole_Data[Rel_Offset:])
+ Section_Tree = BIOSTREE(Section_Info.Name)
+ Section_Tree.type = SECTION_TREE
+ Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.HeaderLength: Rel_Offset+Section_Info.Size]
+ Section_Info.DOffset = Section_Offset + Section_Info.HeaderLength + Rel_Whole_Offset
+ Section_Info.HOffset = Section_Offset + Rel_Whole_Offset
+ Section_Info.ROffset = Rel_Offset
+ if Section_Info.Header.Type == 0:
+ break
+ # The final Section in parent Section does not need to add padding, else must be 4-bytes align with parent Section start offset
+ Pad_Size = 0
+ if (Rel_Offset+Section_Info.HeaderLength+len(Section_Info.Data) != Data_Size):
+ Pad_Size = GetPadSize(Section_Info.Size, SECTION_COMMON_ALIGNMENT)
+ Section_Info.PadData = Pad_Size * b'\x00'
+ if Section_Info.Header.Type == 0x02:
+ Section_Info.DOffset = Section_Offset + Section_Info.ExtHeader.DataOffset + Rel_Whole_Offset
+ Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.ExtHeader.DataOffset: Rel_Offset+Section_Info.Size]
+ if Section_Info.Header.Type == 0x14:
+ ParTree.Data.Version = Section_Info.ExtHeader.GetVersionString()
+ if Section_Info.Header.Type == 0x15:
+ ParTree.Data.UiName = Section_Info.ExtHeader.GetUiString()
+ if Section_Info.Header.Type == 0x19:
+ if Section_Info.Data.replace(b'\x00', b'') == b'':
+ Section_Info.IsPadSection = True
+ Section_Offset += Section_Info.Size + Pad_Size
+ Rel_Offset += Section_Info.Size + Pad_Size
+ Section_Tree.Data = Section_Info
+ ParTree.insertChild(Section_Tree)
+
+class FfsProduct(BinaryProduct):
+ # ParserFFs / GetSection
+ def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ Rel_Offset = 0
+ Section_Offset = 0
+ # Get the Data from parent tree, if do not have the tree then get it from the whole_data.
+ if ParTree.Data != None:
+ Data_Size = len(ParTree.Data.Data)
+ Section_Offset = ParTree.Data.DOffset
+ Whole_Data = ParTree.Data.Data
+ else:
+ Data_Size = len(Whole_Data)
+ # Parser all the data to collect all the Section recorded in Ffs.
+ while Rel_Offset < Data_Size:
+ # Create a SectionNode and set it as the SectionTree's Data
+ Section_Info = SectionNode(Whole_Data[Rel_Offset:])
+ Section_Tree = BIOSTREE(Section_Info.Name)
+ Section_Tree.type = SECTION_TREE
+ Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.HeaderLength: Rel_Offset+Section_Info.Size]
+ Section_Info.DOffset = Section_Offset + Section_Info.HeaderLength + Rel_Whole_Offset
+ Section_Info.HOffset = Section_Offset + Rel_Whole_Offset
+ Section_Info.ROffset = Rel_Offset
+ if Section_Info.Header.Type == 0:
+ break
+ # The final Section in Ffs does not need to add padding, else must be 4-bytes align with Ffs start offset
+ Pad_Size = 0
+ if (Rel_Offset+Section_Info.HeaderLength+len(Section_Info.Data) != Data_Size):
+ Pad_Size = GetPadSize(Section_Info.Size, SECTION_COMMON_ALIGNMENT)
+ Section_Info.PadData = Pad_Size * b'\x00'
+ if Section_Info.Header.Type == 0x02:
+ Section_Info.DOffset = Section_Offset + Section_Info.ExtHeader.DataOffset + Rel_Whole_Offset
+ Section_Info.Data = Whole_Data[Rel_Offset+Section_Info.ExtHeader.DataOffset: Rel_Offset+Section_Info.Size]
+ # If Section is Version or UI type, it saves the version and UI info of its parent Ffs.
+ if Section_Info.Header.Type == 0x14:
+ ParTree.Data.Version = Section_Info.ExtHeader.GetVersionString()
+ if Section_Info.Header.Type == 0x15:
+ ParTree.Data.UiName = Section_Info.ExtHeader.GetUiString()
+ if Section_Info.Header.Type == 0x19:
+ if Section_Info.Data.replace(b'\x00', b'') == b'':
+ Section_Info.IsPadSection = True
+ Section_Offset += Section_Info.Size + Pad_Size
+ Rel_Offset += Section_Info.Size + Pad_Size
+ Section_Tree.Data = Section_Info
+ ParTree.insertChild(Section_Tree)
+
+class FvProduct(BinaryProduct):
+ ## ParserFv / GetFfs
+ def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ Ffs_Offset = 0
+ Rel_Offset = 0
+ # Get the Data from parent tree, if do not have the tree then get it from the whole_data.
+ if ParTree.Data != None:
+ Data_Size = len(ParTree.Data.Data)
+ Ffs_Offset = ParTree.Data.DOffset
+ Whole_Data = ParTree.Data.Data
+ else:
+ Data_Size = len(Whole_Data)
+ # Parser all the data to collect all the Ffs recorded in Fv.
+ while Rel_Offset < Data_Size:
+ # Create a FfsNode and set it as the FFsTree's Data
+ if Data_Size - Rel_Offset < 24:
+ Ffs_Tree = BIOSTREE('Free_Space')
+ Ffs_Tree.type = FFS_FREE_SPACE
+ Ffs_Tree.Data = FreeSpaceNode(Whole_Data[Rel_Offset:])
+ Ffs_Tree.Data.HOffset = Ffs_Offset + Rel_Whole_Offset
+ Ffs_Tree.Data.DOffset = Ffs_Tree.Data.HOffset
+ ParTree.Data.Free_Space = Data_Size - Rel_Offset
+ ParTree.insertChild(Ffs_Tree)
+ Rel_Offset = Data_Size
+ else:
+ Ffs_Info = FfsNode(Whole_Data[Rel_Offset:])
+ Ffs_Tree = BIOSTREE(Ffs_Info.Name)
+ Ffs_Info.HOffset = Ffs_Offset + Rel_Whole_Offset
+ Ffs_Info.DOffset = Ffs_Offset + Ffs_Info.Header.HeaderLength + Rel_Whole_Offset
+ Ffs_Info.ROffset = Rel_Offset
+ if Ffs_Info.Name == PADVECTOR:
+ Ffs_Tree.type = FFS_PAD
+ Ffs_Info.Data = Whole_Data[Rel_Offset+Ffs_Info.Header.HeaderLength: Rel_Offset+Ffs_Info.Size]
+ Ffs_Info.Size = len(Ffs_Info.Data) + Ffs_Info.Header.HeaderLength
+ # if current Ffs is the final ffs of Fv and full of b'\xff', define it with Free_Space
+ if struct2stream(Ffs_Info.Header).replace(b'\xff', b'') == b'':
+ Ffs_Tree.type = FFS_FREE_SPACE
+ Ffs_Info.Data = Whole_Data[Rel_Offset:]
+ Ffs_Info.Size = len(Ffs_Info.Data)
+ ParTree.Data.Free_Space = Ffs_Info.Size
+ else:
+ Ffs_Tree.type = FFS_TREE
+ Ffs_Info.Data = Whole_Data[Rel_Offset+Ffs_Info.Header.HeaderLength: Rel_Offset+Ffs_Info.Size]
+ # The final Ffs in Fv does not need to add padding, else must be 8-bytes align with Fv start offset
+ Pad_Size = 0
+ if Ffs_Tree.type != FFS_FREE_SPACE and (Rel_Offset+Ffs_Info.Header.HeaderLength+len(Ffs_Info.Data) != Data_Size):
+ Pad_Size = GetPadSize(Ffs_Info.Size, FFS_COMMON_ALIGNMENT)
+ Ffs_Info.PadData = Pad_Size * b'\xff'
+ Ffs_Offset += Ffs_Info.Size + Pad_Size
+ Rel_Offset += Ffs_Info.Size + Pad_Size
+ Ffs_Tree.Data = Ffs_Info
+ ParTree.insertChild(Ffs_Tree)
+
+class FdProduct(BinaryProduct):
+ type = [ROOT_FV_TREE, ROOT_TREE]
+
+ ## Create DataTree with first level /fv Info, then parser each Fv.
+ def ParserData(self, WholeFvTree, whole_data: bytes=b'', offset: int=0) -> None:
+ # Get all Fv image in Fd with offset and length
+ Fd_Struct = self.GetFvFromFd(whole_data)
+ data_size = len(whole_data)
+ Binary_count = 0
+ global Fv_count
+ # If the first Fv image is the Binary Fv, add it into the tree.
+ if Fd_Struct[0][1] != 0:
+ Binary_node = BIOSTREE('BINARY'+ str(Binary_count))
+ Binary_node.type = BINARY_DATA
+ Binary_node.Data = BinaryNode(str(Binary_count))
+ Binary_node.Data.Data = whole_data[:Fd_Struct[0][1]]
+ Binary_node.Data.Size = len(Binary_node.Data.Data)
+ Binary_node.Data.HOffset = 0 + offset
+ WholeFvTree.insertChild(Binary_node)
+ Binary_count += 1
+ # Add the first collected Fv image into the tree.
+ Cur_node = BIOSTREE(Fd_Struct[0][0]+ str(Fv_count))
+ Cur_node.type = Fd_Struct[0][0]
+ Cur_node.Data = FvNode(Fv_count, whole_data[Fd_Struct[0][1]:Fd_Struct[0][1]+Fd_Struct[0][2][0]])
+ Cur_node.Data.HOffset = Fd_Struct[0][1] + offset
+ Cur_node.Data.DOffset = Cur_node.Data.HOffset+Cur_node.Data.Header.HeaderLength
+ Cur_node.Data.Data = whole_data[Fd_Struct[0][1]+Cur_node.Data.Header.HeaderLength:Fd_Struct[0][1]+Cur_node.Data.Size]
+ WholeFvTree.insertChild(Cur_node)
+ Fv_count += 1
+ Fv_num = len(Fd_Struct)
+ # Add all the collected Fv image and the Binary Fv image between them into the tree.
+ for i in range(Fv_num-1):
+ if Fd_Struct[i][1]+Fd_Struct[i][2][0] != Fd_Struct[i+1][1]:
+ Binary_node = BIOSTREE('BINARY'+ str(Binary_count))
+ Binary_node.type = BINARY_DATA
+ Binary_node.Data = BinaryNode(str(Binary_count))
+ Binary_node.Data.Data = whole_data[Fd_Struct[i][1]+Fd_Struct[i][2][0]:Fd_Struct[i+1][1]]
+ Binary_node.Data.Size = len(Binary_node.Data.Data)
+ Binary_node.Data.HOffset = Fd_Struct[i][1]+Fd_Struct[i][2][0] + offset
+ WholeFvTree.insertChild(Binary_node)
+ Binary_count += 1
+ Cur_node = BIOSTREE(Fd_Struct[i+1][0]+ str(Fv_count))
+ Cur_node.type = Fd_Struct[i+1][0]
+ Cur_node.Data = FvNode(Fv_count, whole_data[Fd_Struct[i+1][1]:Fd_Struct[i+1][1]+Fd_Struct[i+1][2][0]])
+ Cur_node.Data.HOffset = Fd_Struct[i+1][1] + offset
+ Cur_node.Data.DOffset = Cur_node.Data.HOffset+Cur_node.Data.Header.HeaderLength
+ Cur_node.Data.Data = whole_data[Fd_Struct[i+1][1]+Cur_node.Data.Header.HeaderLength:Fd_Struct[i+1][1]+Cur_node.Data.Size]
+ WholeFvTree.insertChild(Cur_node)
+ Fv_count += 1
+ # If the final Fv image is the Binary Fv, add it into the tree
+ if Fd_Struct[-1][1] + Fd_Struct[-1][2][0] != data_size:
+ Binary_node = BIOSTREE('BINARY'+ str(Binary_count))
+ Binary_node.type = BINARY_DATA
+ Binary_node.Data = BinaryNode(str(Binary_count))
+ Binary_node.Data.Data = whole_data[Fd_Struct[-1][1]+Fd_Struct[-1][2][0]:]
+ Binary_node.Data.Size = len(Binary_node.Data.Data)
+ Binary_node.Data.HOffset = Fd_Struct[-1][1]+Fd_Struct[-1][2][0] + offset
+ WholeFvTree.insertChild(Binary_node)
+ Binary_count += 1
+
+ ## Get the first level Fv from Fd file.
+ def GetFvFromFd(self, whole_data: bytes=b'') -> list:
+ Fd_Struct = []
+ data_size = len(whole_data)
+ cur_index = 0
+ # Get all the EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE FV image offset and length.
+ while cur_index < data_size:
+ if EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE in whole_data[cur_index:]:
+ target_index = whole_data[cur_index:].index(EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE) + cur_index
+ if whole_data[target_index+24:target_index+28] == FVH_SIGNATURE:
+ Fd_Struct.append([FV_TREE, target_index - 16, unpack("Q", whole_data[target_index+16:target_index+24])])
+ cur_index = Fd_Struct[-1][1] + Fd_Struct[-1][2][0]
+ else:
+ cur_index = target_index + 16
+ else:
+ cur_index = data_size
+ cur_index = 0
+ # Get all the EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE FV image offset and length.
+ while cur_index < data_size:
+ if EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE in whole_data[cur_index:]:
+ target_index = whole_data[cur_index:].index(EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE) + cur_index
+ if whole_data[target_index+24:target_index+28] == FVH_SIGNATURE:
+ Fd_Struct.append([FV_TREE, target_index - 16, unpack("Q", whole_data[target_index+16:target_index+24])])
+ cur_index = Fd_Struct[-1][1] + Fd_Struct[-1][2][0]
+ else:
+ cur_index = target_index + 16
+ else:
+ cur_index = data_size
+ cur_index = 0
+ # Get all the EFI_SYSTEM_NVDATA_FV_GUID_BYTE FV image offset and length.
+ while cur_index < data_size:
+ if EFI_SYSTEM_NVDATA_FV_GUID_BYTE in whole_data[cur_index:]:
+ target_index = whole_data[cur_index:].index(EFI_SYSTEM_NVDATA_FV_GUID_BYTE) + cur_index
+ if whole_data[target_index+24:target_index+28] == FVH_SIGNATURE:
+ Fd_Struct.append([DATA_FV_TREE, target_index - 16, unpack("Q", whole_data[target_index+16:target_index+24])])
+ cur_index = Fd_Struct[-1][1] + Fd_Struct[-1][2][0]
+ else:
+ cur_index = target_index + 16
+ else:
+ cur_index = data_size
+ # Sort all the collect Fv image with offset.
+ Fd_Struct.sort(key=lambda x:x[1])
+ tmp_struct = copy.deepcopy(Fd_Struct)
+ tmp_index = 0
+ Fv_num = len(Fd_Struct)
+ # Remove the Fv image included in another Fv image.
+ for i in range(1,Fv_num):
+ if tmp_struct[i][1]+tmp_struct[i][2][0] < tmp_struct[i-1][1]+tmp_struct[i-1][2][0]:
+ Fd_Struct.remove(Fd_Struct[i-tmp_index])
+ tmp_index += 1
+ return Fd_Struct
+
+class ElfSectionProduct(BinaryProduct):
+ ## Decompress the compressed section.
+ def ParserData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ pass
+ def ParserSectionData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ pass
+ def ParserProgramData(self, Section_Tree, whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ pass
+
+class ElfProduct(BinaryProduct):
+
+ def ParserData(self, ParTree, Whole_Data: bytes, Rel_Whole_Offset: int=0) -> None:
+ Elf_Info = ElfNode(Whole_Data)
+ if Elf_Info.Header.ELF_PHOff != 0:
+ Elf_Info.GetProgramList(Whole_Data[Elf_Info.Header.ELF_PHOff:])
+ if Elf_Info.Header.ELF_SHOff != 0:
+ Elf_Info.GetSectionList(Whole_Data[Elf_Info.Header.ELF_SHOff:])
+ Elf_Info.FindUPLDSection(Whole_Data)
+ Elf_Tree = BIOSTREE(Elf_Info.Name)
+ Elf_Tree.type = ELF_TREE
+ Elf_Info.Data = Whole_Data[Elf_Info.HeaderLength:]
+ Elf_Tree.Data = Elf_Info
+ ParTree.insertChild(Elf_Tree)
+
+class ParserEntry():
+ FactoryTable:dict = {
+ SECTION_TREE: SectionFactory,
+ ROOT_SECTION_TREE: FfsFactory,
+ FFS_TREE: FfsFactory,
+ ROOT_FFS_TREE: FvFactory,
+ FV_TREE: FvFactory,
+ SEC_FV_TREE: FvFactory,
+ ROOT_FV_TREE: FdFactory,
+ ROOT_TREE: FdFactory,
+ ROOT_ELF_TREE: ElfFactory,
+ }
+
+ def GetTargetFactory(self, Tree_type: str) -> BinaryFactory:
+ if Tree_type in self.FactoryTable:
+ return self.FactoryTable[Tree_type]
+
+ def Generate_Product(self, TargetFactory: BinaryFactory, Tree, Data: bytes, Offset: int) -> None:
+ New_Product = TargetFactory.Create_Product()
+ New_Product.ParserData(Tree, Data, Offset)
+
+ def DataParser(self, Tree, Data: bytes, Offset: int) -> None:
+ TargetFactory = self.GetTargetFactory(Tree.type)
+ if TargetFactory:
+ self.Generate_Product(TargetFactory, Tree, Data, Offset)
diff --git a/BaseTools/Source/Python/FMMT/core/BiosTree.py b/BaseTools/Source/Python/FMMT/core/BiosTree.py
index c5a7b017f4..f776519bd1 100644
--- a/BaseTools/Source/Python/FMMT/core/BiosTree.py
+++ b/BaseTools/Source/Python/FMMT/core/BiosTree.py
@@ -1,242 +1,242 @@
-## @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'
-ROOT_ELF_TREE = 'ROOT_ELF_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'
-ELF_TREE = 'ELF'
-
-RootType = [ROOT_TREE, ROOT_FV_TREE, ROOT_FFS_TREE, ROOT_SECTION_TREE]
-FvType = [FV_TREE, SEC_FV_TREE]
-FfsType = FFS_TREE
-SecType = SECTION_TREE
-ElfType = [ROOT_ELF_TREE, ELF_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 or pos == len(self.Child):
- 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"] == ROOT_ELF_TREE:
- Info.append("ELF File: {}\n".format(Key))
- elif TargetDict[Key]["Type"] == ELF_TREE:
- ProducerId = ""
- ImageId = ""
- if TargetDict.get(Key).get('IfExist'):
- Identifier = TargetDict.get(Key).get('Identifier')
- for item in TargetDict.get(Key).get('ProducerId'):
- ProducerId += chr(item)
- for item in TargetDict.get(Key).get('ImageId'):
- ImageId += chr(item)
- Info.append("- UNIVERSAL_PAYLOAD_INFO")
- Info.append(" - 4 bytes align: {}".format(TargetDict.get(Key).get('Upld_Info_Align')))
- Info.append(" - Identifier: {} # 0x48444c50--PLDH / 0x444c5055--UPLD".format(hex(Identifier)))
- Info.append(" - SpecRevision: {}".format(hex(TargetDict.get(Key).get('SpecRevision'))))
- Info.append(" - Attribute: {}".format(hex(TargetDict.get(Key).get('Attribute'))))
- Info.append(" - Revision: {}".format(hex(TargetDict.get(Key).get('Revision'))))
- Info.append(" - Capability: {}".format(hex(TargetDict.get(Key).get('Capability'))))
- Info.append(" - ProducerId: {}".format(ProducerId))
- Info.append(" - ImageId: {}".format(ImageId))
- Info.append("\n")
- Info.append("- UPLD buffer")
- Info.append(" Buffer: {}".format(TargetDict.get(Key).get('Upld_Buffer')))
- else:
- print("Do not find the Upld Info section!!!\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 or self.type == ROOT_ELF_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 == ELF_TREE:
- key = str(self.Data.Name)
- TreeInfo[key] = collections.OrderedDict()
- TreeInfo[key]["Name"] = key
- TreeInfo[key]["Type"] = self.type
- TreeInfo[key]["IfExist"] = self.Data.UpldInfo
- if self.Data.UpldInfo:
- TreeInfo[key]["Identifier"] = self.Data.UpldInfo.Identifier
- TreeInfo[key]["SpecRevision"] = self.Data.UpldInfo.SpecRevision
- TreeInfo[key]["Attribute"] = self.Data.UpldInfo.Attribute
- TreeInfo[key]["Revision"] = self.Data.UpldInfo.Revision
- TreeInfo[key]["Capability"] = self.Data.UpldInfo.Capability
- TreeInfo[key]["ProducerId"] = self.Data.UpldInfo.ProducerId
- TreeInfo[key]["ImageId"] = self.Data.UpldInfo.ImageId
- TreeInfo[key]["Upld_Info_Align"] = self.Data.Upld_Info_Align
- TreeInfo[key]["Upld_Buffer"] = self.Data.UpldBuffer
- 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
+## @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'
+ROOT_ELF_TREE = 'ROOT_ELF_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'
+ELF_TREE = 'ELF'
+
+RootType = [ROOT_TREE, ROOT_FV_TREE, ROOT_FFS_TREE, ROOT_SECTION_TREE]
+FvType = [FV_TREE, SEC_FV_TREE]
+FfsType = FFS_TREE
+SecType = SECTION_TREE
+ElfType = [ROOT_ELF_TREE, ELF_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 or pos == len(self.Child):
+ 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"] == ROOT_ELF_TREE:
+ Info.append("ELF File: {}\n".format(Key))
+ elif TargetDict[Key]["Type"] == ELF_TREE:
+ ProducerId = ""
+ ImageId = ""
+ if TargetDict.get(Key).get('IfExist'):
+ Identifier = TargetDict.get(Key).get('Identifier')
+ for item in TargetDict.get(Key).get('ProducerId'):
+ ProducerId += chr(item)
+ for item in TargetDict.get(Key).get('ImageId'):
+ ImageId += chr(item)
+ Info.append("- UNIVERSAL_PAYLOAD_INFO")
+ Info.append(" - 4 bytes align: {}".format(TargetDict.get(Key).get('Upld_Info_Align')))
+ Info.append(" - Identifier: {} # 0x48444c50--PLDH / 0x444c5055--UPLD".format(hex(Identifier)))
+ Info.append(" - SpecRevision: {}".format(hex(TargetDict.get(Key).get('SpecRevision'))))
+ Info.append(" - Attribute: {}".format(hex(TargetDict.get(Key).get('Attribute'))))
+ Info.append(" - Revision: {}".format(hex(TargetDict.get(Key).get('Revision'))))
+ Info.append(" - Capability: {}".format(hex(TargetDict.get(Key).get('Capability'))))
+ Info.append(" - ProducerId: {}".format(ProducerId))
+ Info.append(" - ImageId: {}".format(ImageId))
+ Info.append("\n")
+ Info.append("- UPLD buffer")
+ Info.append(" Buffer: {}".format(TargetDict.get(Key).get('Upld_Buffer')))
+ else:
+ print("Do not find the Upld Info section!!!\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 or self.type == ROOT_ELF_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 == ELF_TREE:
+ key = str(self.Data.Name)
+ TreeInfo[key] = collections.OrderedDict()
+ TreeInfo[key]["Name"] = key
+ TreeInfo[key]["Type"] = self.type
+ TreeInfo[key]["IfExist"] = self.Data.UpldInfo
+ if self.Data.UpldInfo:
+ TreeInfo[key]["Identifier"] = self.Data.UpldInfo.Identifier
+ TreeInfo[key]["SpecRevision"] = self.Data.UpldInfo.SpecRevision
+ TreeInfo[key]["Attribute"] = self.Data.UpldInfo.Attribute
+ TreeInfo[key]["Revision"] = self.Data.UpldInfo.Revision
+ TreeInfo[key]["Capability"] = self.Data.UpldInfo.Capability
+ TreeInfo[key]["ProducerId"] = self.Data.UpldInfo.ProducerId
+ TreeInfo[key]["ImageId"] = self.Data.UpldInfo.ImageId
+ TreeInfo[key]["Upld_Info_Align"] = self.Data.Upld_Info_Align
+ TreeInfo[key]["Upld_Buffer"] = self.Data.UpldBuffer
+ 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
diff --git a/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py b/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
index 5ca4c20dc6..ba6a027c40 100644
--- a/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
+++ b/BaseTools/Source/Python/FMMT/core/BiosTreeNode.py
@@ -1,248 +1,248 @@
-## @file
-# This file is used to define the BIOS Tree Node.
-#
-# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-from FirmwareStorageFormat.UPLHeader import *
-from FirmwareStorageFormat.FvHeader import *
-from FirmwareStorageFormat.FfsFileHeader import *
-from FirmwareStorageFormat.SectionHeader import *
-from FirmwareStorageFormat.Common import *
-from utils.FmmtLogger import FmmtLogger as logger
-import uuid
-
-SectionHeaderType = {
- 0x01:'EFI_COMPRESSION_SECTION',
- 0x02:'EFI_GUID_DEFINED_SECTION',
- 0x03:'EFI_SECTION_DISPOSABLE',
- 0x10:'EFI_SECTION_PE32',
- 0x11:'EFI_SECTION_PIC',
- 0x12:'EFI_SECTION_TE',
- 0x13:'EFI_SECTION_DXE_DEPEX',
- 0x14:'EFI_SECTION_VERSION',
- 0x15:'EFI_SECTION_USER_INTERFACE',
- 0x16:'EFI_SECTION_COMPATIBILITY16',
- 0x17:'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',
- 0x18:'EFI_FREEFORM_SUBTYPE_GUID_SECTION',
- 0x19:'EFI_SECTION_RAW',
- 0x1B:'EFI_SECTION_PEI_DEPEX',
- 0x1C:'EFI_SECTION_MM_DEPEX'
-}
-HeaderType = [0x01, 0x02, 0x14, 0x15, 0x18]
-
-class BinaryNode:
- def __init__(self, name: str) -> None:
- self.Size = 0
- self.Name = "BINARY" + str(name)
- self.HOffset = 0
- self.Data = b''
-
-class ElfNode:
- def __init__(self, buffer: bytes) -> None:
- self.Header = ELF_HEADER32.from_buffer_copy(buffer)
- if self.Header.ELF_Identification[0:4] != b'\x7fELF':
- logger.error('Invalid Elf Header! Elf Identification {} is not ".ELF".'.format(self.Header.ELF_Identification))
- raise Exception("Process Failed: Invalid ELF Header Identification!")
- self.Class = self.Header.ELF_Identification[4]
- if self.Class == 0x02:
- self.Header = ELF_HEADER64.from_buffer_copy(buffer)
- elif self.Class != 0x01:
- logger.error('Invalid Elf Class! Elf Class {} is not 0x01 or 0x02.'.format(self.Class))
- raise Exception("Process Failed: Invalid ELF Class!")
-
- self.ProList = []
- self.SecList = []
- self.UpldInfoSection = None
- self.UpldInfo = None
- self.UpldBuffer = b''
- self.Name = "ELF"
- self.HeaderLength = len(struct2stream(self.Header))
- self.HOffset = 0
- self.DOffset = 0
- self.ROffset = 0
- self.Data = b''
- self.PadData = b''
- self.Upld_Info_Align = False
-
- def GetProgramList(self, buffer: bytes) -> None:
- for i in range(self.Header.ELF_PHNum):
- if self.Class == 0x01:
- ElfProgramHeader = ELF_PROGRAM_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
- elif self.Class == 0x02:
- ElfProgramHeader = ELF_PROGRAM_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
- self.ProList.append(ElfProgramHeader)
-
- def GetSectionList(self, buffer: bytes) -> None:
- for i in range(self.Header.ELF_SHNum):
- if self.Class == 0x01:
- ElfSectionHeader = ELF_SECTION_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
- elif self.Class == 0x02:
- ElfSectionHeader = ELF_SECTION_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
- self.SecList.append(ElfSectionHeader)
-
- def FindUPLDSection(self, buffer: bytes) -> None:
- for item in self.SecList:
- if buffer[item.SH_Offset:item.SH_Offset+4] == b'PLDH' or buffer[item.SH_Offset:item.SH_Offset+4] == b'UPLD':
- self.UpldInfoSection = item
- self.UpldInfo = UNIVERSAL_PAYLOAD_INFO.from_buffer_copy(buffer[item.SH_Offset:item.SH_Offset+item.SH_Size])
- self.UpldBuffer = struct2stream(self.UpldInfo)
- if (self.UpldInfoSection.SH_Offset) % 4 == 0:
- # if (self.UpldInfoSection.SH_Offset - self.Header.ELF_Entry) % 4 == 0:
- self.Upld_Info_Align = True
-
-class FvNode:
- def __init__(self, name, buffer: bytes) -> None:
- self.Header = EFI_FIRMWARE_VOLUME_HEADER.from_buffer_copy(buffer)
- Map_num = (self.Header.HeaderLength - 56)//8
- self.Header = Refine_FV_Header(Map_num).from_buffer_copy(buffer)
- self.FvId = "FV" + str(name)
- self.Name = "FV" + str(name)
- if self.Header.ExtHeaderOffset:
- self.ExtHeader = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer_copy(buffer[self.Header.ExtHeaderOffset:])
- self.Name = uuid.UUID(bytes_le=struct2stream(self.ExtHeader.FvName))
- self.ExtEntryOffset = self.Header.ExtHeaderOffset + 20
- if self.ExtHeader.ExtHeaderSize != 20:
- self.ExtEntryExist = 1
- self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY.from_buffer_copy(buffer[self.ExtEntryOffset:])
- self.ExtTypeExist = 1
- if self.ExtEntry.ExtEntryType == 0x01:
- nums = (self.ExtEntry.ExtEntrySize - 8) // 16
- self.ExtEntry = Refine_FV_EXT_ENTRY_OEM_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])
- elif self.ExtEntry.ExtEntryType == 0x02:
- nums = self.ExtEntry.ExtEntrySize - 20
- self.ExtEntry = Refine_FV_EXT_ENTRY_GUID_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])
- elif self.ExtEntry.ExtEntryType == 0x03:
- self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE.from_buffer_copy(buffer[self.ExtEntryOffset:])
- else:
- self.ExtTypeExist = 0
- else:
- self.ExtEntryExist = 0
- self.Size = self.Header.FvLength
- self.HeaderLength = self.Header.HeaderLength
- self.HOffset = 0
- self.DOffset = 0
- self.ROffset = 0
- self.Data = b''
- if self.Header.Signature != 1213613663:
- logger.error('Invalid Fv Header! Fv {} signature {} is not "_FVH".'.format(struct2stream(self.Header), self.Header.Signature))
- raise Exception("Process Failed: Fv Header Signature!")
- self.PadData = b''
- self.Free_Space = 0
- self.ModCheckSum()
-
- def ModCheckSum(self) -> None:
- # Fv Header Sums to 0.
- Header = struct2stream(self.Header)[::-1]
- Size = self.HeaderLength // 2
- Sum = 0
- for i in range(Size):
- Sum += int(Header[i*2: i*2 + 2].hex(), 16)
- if Sum & 0xffff:
- self.Header.Checksum = 0x10000 - (Sum - self.Header.Checksum) % 0x10000
-
- def ModFvExt(self) -> None:
- # If used space changes and self.ExtEntry.UsedSize exists, self.ExtEntry.UsedSize need to be changed.
- if self.Header.ExtHeaderOffset and self.ExtEntryExist and self.ExtTypeExist and self.ExtEntry.Hdr.ExtEntryType == 0x03:
- self.ExtEntry.UsedSize = self.Header.FvLength - self.Free_Space
-
- def ModFvSize(self) -> None:
- # If Fv Size changed, self.Header.FvLength and self.Header.BlockMap[i].NumBlocks need to be changed.
- BlockMapNum = len(self.Header.BlockMap)
- for i in range(BlockMapNum):
- if self.Header.BlockMap[i].Length:
- self.Header.BlockMap[i].NumBlocks = self.Header.FvLength // self.Header.BlockMap[i].Length
-
- def ModExtHeaderData(self) -> None:
- if self.Header.ExtHeaderOffset:
- ExtHeaderData = struct2stream(self.ExtHeader)
- ExtHeaderDataOffset = self.Header.ExtHeaderOffset - self.HeaderLength
- self.Data = self.Data[:ExtHeaderDataOffset] + ExtHeaderData + self.Data[ExtHeaderDataOffset+20:]
- if self.Header.ExtHeaderOffset and self.ExtEntryExist:
- ExtHeaderEntryData = struct2stream(self.ExtEntry)
- ExtHeaderEntryDataOffset = self.Header.ExtHeaderOffset + 20 - self.HeaderLength
- self.Data = self.Data[:ExtHeaderEntryDataOffset] + ExtHeaderEntryData + self.Data[ExtHeaderEntryDataOffset+len(ExtHeaderEntryData):]
-
-class FfsNode:
- def __init__(self, buffer: bytes) -> None:
- self.Header = EFI_FFS_FILE_HEADER.from_buffer_copy(buffer)
- # self.Attributes = unpack("<B", buffer[21:22])[0]
- if self.Header.FFS_FILE_SIZE != 0 and self.Header.Attributes != 0xff and self.Header.Attributes & 0x01 == 1:
- logger.error('Error Ffs Header! Ffs {} Header Size and Attributes is not matched!'.format(uuid.UUID(bytes_le=struct2stream(self.Header.Name))))
- raise Exception("Process Failed: Error Ffs Header!")
- if self.Header.FFS_FILE_SIZE == 0 and self.Header.Attributes & 0x01 == 1:
- self.Header = EFI_FFS_FILE_HEADER2.from_buffer_copy(buffer)
- self.Name = uuid.UUID(bytes_le=struct2stream(self.Header.Name))
- self.UiName = b''
- self.Version = b''
- self.Size = self.Header.FFS_FILE_SIZE
- self.HeaderLength = self.Header.HeaderLength
- self.HOffset = 0
- self.DOffset = 0
- self.ROffset = 0
- self.Data = b''
- self.PadData = b''
- self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align
-
- def ModCheckSum(self) -> None:
- HeaderData = struct2stream(self.Header)
- HeaderSum = 0
- for item in HeaderData:
- HeaderSum += item
- HeaderSum -= self.Header.State
- HeaderSum -= self.Header.IntegrityCheck.Checksum.File
- if HeaderSum & 0xff:
- Header = self.Header.IntegrityCheck.Checksum.Header + 0x100 - HeaderSum % 0x100
- self.Header.IntegrityCheck.Checksum.Header = Header % 0x100
-
-class SectionNode:
- def __init__(self, buffer: bytes) -> None:
- if buffer[0:3] != b'\xff\xff\xff':
- self.Header = EFI_COMMON_SECTION_HEADER.from_buffer_copy(buffer)
- else:
- self.Header = EFI_COMMON_SECTION_HEADER2.from_buffer_copy(buffer)
- if self.Header.Type in SectionHeaderType:
- self.Name = SectionHeaderType[self.Header.Type]
- elif self.Header.Type == 0:
- self.Name = "EFI_SECTION_ALL"
- else:
- self.Name = "SECTION"
- if self.Header.Type in HeaderType:
- self.ExtHeader = self.GetExtHeader(self.Header.Type, buffer[self.Header.Common_Header_Size():], (self.Header.SECTION_SIZE-self.Header.Common_Header_Size()))
- self.HeaderLength = self.Header.Common_Header_Size() + self.ExtHeader.ExtHeaderSize()
- else:
- self.ExtHeader = None
- self.HeaderLength = self.Header.Common_Header_Size()
- self.Size = self.Header.SECTION_SIZE
- self.Type = self.Header.Type
- self.HOffset = 0
- self.DOffset = 0
- self.ROffset = 0
- self.Data = b''
- self.OriData = b''
- self.OriHeader = b''
- self.PadData = b''
- self.IsPadSection = False
- self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align
-
- def GetExtHeader(self, Type: int, buffer: bytes, nums: int=0) -> None:
- if Type == 0x01:
- return EFI_COMPRESSION_SECTION.from_buffer_copy(buffer)
- elif Type == 0x02:
- return EFI_GUID_DEFINED_SECTION.from_buffer_copy(buffer)
- elif Type == 0x14:
- return Get_VERSION_Header((nums - 2)//2).from_buffer_copy(buffer)
- elif Type == 0x15:
- return Get_USER_INTERFACE_Header(nums//2).from_buffer_copy(buffer)
- elif Type == 0x18:
- return EFI_FREEFORM_SUBTYPE_GUID_SECTION.from_buffer_copy(buffer)
-
-class FreeSpaceNode:
- def __init__(self, buffer: bytes) -> None:
- self.Name = 'Free_Space'
- self.Data = buffer
- self.Size = len(buffer)
- self.HOffset = 0
- self.DOffset = 0
- self.ROffset = 0
- self.PadData = b''
+## @file
+# This file is used to define the BIOS Tree Node.
+#
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+from FirmwareStorageFormat.UPLHeader import *
+from FirmwareStorageFormat.FvHeader import *
+from FirmwareStorageFormat.FfsFileHeader import *
+from FirmwareStorageFormat.SectionHeader import *
+from FirmwareStorageFormat.Common import *
+from utils.FmmtLogger import FmmtLogger as logger
+import uuid
+
+SectionHeaderType = {
+ 0x01:'EFI_COMPRESSION_SECTION',
+ 0x02:'EFI_GUID_DEFINED_SECTION',
+ 0x03:'EFI_SECTION_DISPOSABLE',
+ 0x10:'EFI_SECTION_PE32',
+ 0x11:'EFI_SECTION_PIC',
+ 0x12:'EFI_SECTION_TE',
+ 0x13:'EFI_SECTION_DXE_DEPEX',
+ 0x14:'EFI_SECTION_VERSION',
+ 0x15:'EFI_SECTION_USER_INTERFACE',
+ 0x16:'EFI_SECTION_COMPATIBILITY16',
+ 0x17:'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',
+ 0x18:'EFI_FREEFORM_SUBTYPE_GUID_SECTION',
+ 0x19:'EFI_SECTION_RAW',
+ 0x1B:'EFI_SECTION_PEI_DEPEX',
+ 0x1C:'EFI_SECTION_MM_DEPEX'
+}
+HeaderType = [0x01, 0x02, 0x14, 0x15, 0x18]
+
+class BinaryNode:
+ def __init__(self, name: str) -> None:
+ self.Size = 0
+ self.Name = "BINARY" + str(name)
+ self.HOffset = 0
+ self.Data = b''
+
+class ElfNode:
+ def __init__(self, buffer: bytes) -> None:
+ self.Header = ELF_HEADER32.from_buffer_copy(buffer)
+ if self.Header.ELF_Identification[0:4] != b'\x7fELF':
+ logger.error('Invalid Elf Header! Elf Identification {} is not ".ELF".'.format(self.Header.ELF_Identification))
+ raise Exception("Process Failed: Invalid ELF Header Identification!")
+ self.Class = self.Header.ELF_Identification[4]
+ if self.Class == 0x02:
+ self.Header = ELF_HEADER64.from_buffer_copy(buffer)
+ elif self.Class != 0x01:
+ logger.error('Invalid Elf Class! Elf Class {} is not 0x01 or 0x02.'.format(self.Class))
+ raise Exception("Process Failed: Invalid ELF Class!")
+
+ self.ProList = []
+ self.SecList = []
+ self.UpldInfoSection = None
+ self.UpldInfo = None
+ self.UpldBuffer = b''
+ self.Name = "ELF"
+ self.HeaderLength = len(struct2stream(self.Header))
+ self.HOffset = 0
+ self.DOffset = 0
+ self.ROffset = 0
+ self.Data = b''
+ self.PadData = b''
+ self.Upld_Info_Align = False
+
+ def GetProgramList(self, buffer: bytes) -> None:
+ for i in range(self.Header.ELF_PHNum):
+ if self.Class == 0x01:
+ ElfProgramHeader = ELF_PROGRAM_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
+ elif self.Class == 0x02:
+ ElfProgramHeader = ELF_PROGRAM_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_PHEntSize:])
+ self.ProList.append(ElfProgramHeader)
+
+ def GetSectionList(self, buffer: bytes) -> None:
+ for i in range(self.Header.ELF_SHNum):
+ if self.Class == 0x01:
+ ElfSectionHeader = ELF_SECTION_HEADER32.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
+ elif self.Class == 0x02:
+ ElfSectionHeader = ELF_SECTION_HEADER64.from_buffer_copy(buffer[i*self.Header.ELF_SHEntSize:])
+ self.SecList.append(ElfSectionHeader)
+
+ def FindUPLDSection(self, buffer: bytes) -> None:
+ for item in self.SecList:
+ if buffer[item.SH_Offset:item.SH_Offset+4] == b'PLDH' or buffer[item.SH_Offset:item.SH_Offset+4] == b'UPLD':
+ self.UpldInfoSection = item
+ self.UpldInfo = UNIVERSAL_PAYLOAD_INFO.from_buffer_copy(buffer[item.SH_Offset:item.SH_Offset+item.SH_Size])
+ self.UpldBuffer = struct2stream(self.UpldInfo)
+ if (self.UpldInfoSection.SH_Offset) % 4 == 0:
+ # if (self.UpldInfoSection.SH_Offset - self.Header.ELF_Entry) % 4 == 0:
+ self.Upld_Info_Align = True
+
+class FvNode:
+ def __init__(self, name, buffer: bytes) -> None:
+ self.Header = EFI_FIRMWARE_VOLUME_HEADER.from_buffer_copy(buffer)
+ Map_num = (self.Header.HeaderLength - 56)//8
+ self.Header = Refine_FV_Header(Map_num).from_buffer_copy(buffer)
+ self.FvId = "FV" + str(name)
+ self.Name = "FV" + str(name)
+ if self.Header.ExtHeaderOffset:
+ self.ExtHeader = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer_copy(buffer[self.Header.ExtHeaderOffset:])
+ self.Name = uuid.UUID(bytes_le=struct2stream(self.ExtHeader.FvName))
+ self.ExtEntryOffset = self.Header.ExtHeaderOffset + 20
+ if self.ExtHeader.ExtHeaderSize != 20:
+ self.ExtEntryExist = 1
+ self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY.from_buffer_copy(buffer[self.ExtEntryOffset:])
+ self.ExtTypeExist = 1
+ if self.ExtEntry.ExtEntryType == 0x01:
+ nums = (self.ExtEntry.ExtEntrySize - 8) // 16
+ self.ExtEntry = Refine_FV_EXT_ENTRY_OEM_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])
+ elif self.ExtEntry.ExtEntryType == 0x02:
+ nums = self.ExtEntry.ExtEntrySize - 20
+ self.ExtEntry = Refine_FV_EXT_ENTRY_GUID_TYPE_Header(nums).from_buffer_copy(buffer[self.ExtEntryOffset:])
+ elif self.ExtEntry.ExtEntryType == 0x03:
+ self.ExtEntry = EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE.from_buffer_copy(buffer[self.ExtEntryOffset:])
+ else:
+ self.ExtTypeExist = 0
+ else:
+ self.ExtEntryExist = 0
+ self.Size = self.Header.FvLength
+ self.HeaderLength = self.Header.HeaderLength
+ self.HOffset = 0
+ self.DOffset = 0
+ self.ROffset = 0
+ self.Data = b''
+ if self.Header.Signature != 1213613663:
+ logger.error('Invalid Fv Header! Fv {} signature {} is not "_FVH".'.format(struct2stream(self.Header), self.Header.Signature))
+ raise Exception("Process Failed: Fv Header Signature!")
+ self.PadData = b''
+ self.Free_Space = 0
+ self.ModCheckSum()
+
+ def ModCheckSum(self) -> None:
+ # Fv Header Sums to 0.
+ Header = struct2stream(self.Header)[::-1]
+ Size = self.HeaderLength // 2
+ Sum = 0
+ for i in range(Size):
+ Sum += int(Header[i*2: i*2 + 2].hex(), 16)
+ if Sum & 0xffff:
+ self.Header.Checksum = 0x10000 - (Sum - self.Header.Checksum) % 0x10000
+
+ def ModFvExt(self) -> None:
+ # If used space changes and self.ExtEntry.UsedSize exists, self.ExtEntry.UsedSize need to be changed.
+ if self.Header.ExtHeaderOffset and self.ExtEntryExist and self.ExtTypeExist and self.ExtEntry.Hdr.ExtEntryType == 0x03:
+ self.ExtEntry.UsedSize = self.Header.FvLength - self.Free_Space
+
+ def ModFvSize(self) -> None:
+ # If Fv Size changed, self.Header.FvLength and self.Header.BlockMap[i].NumBlocks need to be changed.
+ BlockMapNum = len(self.Header.BlockMap)
+ for i in range(BlockMapNum):
+ if self.Header.BlockMap[i].Length:
+ self.Header.BlockMap[i].NumBlocks = self.Header.FvLength // self.Header.BlockMap[i].Length
+
+ def ModExtHeaderData(self) -> None:
+ if self.Header.ExtHeaderOffset:
+ ExtHeaderData = struct2stream(self.ExtHeader)
+ ExtHeaderDataOffset = self.Header.ExtHeaderOffset - self.HeaderLength
+ self.Data = self.Data[:ExtHeaderDataOffset] + ExtHeaderData + self.Data[ExtHeaderDataOffset+20:]
+ if self.Header.ExtHeaderOffset and self.ExtEntryExist:
+ ExtHeaderEntryData = struct2stream(self.ExtEntry)
+ ExtHeaderEntryDataOffset = self.Header.ExtHeaderOffset + 20 - self.HeaderLength
+ self.Data = self.Data[:ExtHeaderEntryDataOffset] + ExtHeaderEntryData + self.Data[ExtHeaderEntryDataOffset+len(ExtHeaderEntryData):]
+
+class FfsNode:
+ def __init__(self, buffer: bytes) -> None:
+ self.Header = EFI_FFS_FILE_HEADER.from_buffer_copy(buffer)
+ # self.Attributes = unpack("<B", buffer[21:22])[0]
+ if self.Header.FFS_FILE_SIZE != 0 and self.Header.Attributes != 0xff and self.Header.Attributes & 0x01 == 1:
+ logger.error('Error Ffs Header! Ffs {} Header Size and Attributes is not matched!'.format(uuid.UUID(bytes_le=struct2stream(self.Header.Name))))
+ raise Exception("Process Failed: Error Ffs Header!")
+ if self.Header.FFS_FILE_SIZE == 0 and self.Header.Attributes & 0x01 == 1:
+ self.Header = EFI_FFS_FILE_HEADER2.from_buffer_copy(buffer)
+ self.Name = uuid.UUID(bytes_le=struct2stream(self.Header.Name))
+ self.UiName = b''
+ self.Version = b''
+ self.Size = self.Header.FFS_FILE_SIZE
+ self.HeaderLength = self.Header.HeaderLength
+ self.HOffset = 0
+ self.DOffset = 0
+ self.ROffset = 0
+ self.Data = b''
+ self.PadData = b''
+ self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align
+
+ def ModCheckSum(self) -> None:
+ HeaderData = struct2stream(self.Header)
+ HeaderSum = 0
+ for item in HeaderData:
+ HeaderSum += item
+ HeaderSum -= self.Header.State
+ HeaderSum -= self.Header.IntegrityCheck.Checksum.File
+ if HeaderSum & 0xff:
+ Header = self.Header.IntegrityCheck.Checksum.Header + 0x100 - HeaderSum % 0x100
+ self.Header.IntegrityCheck.Checksum.Header = Header % 0x100
+
+class SectionNode:
+ def __init__(self, buffer: bytes) -> None:
+ if buffer[0:3] != b'\xff\xff\xff':
+ self.Header = EFI_COMMON_SECTION_HEADER.from_buffer_copy(buffer)
+ else:
+ self.Header = EFI_COMMON_SECTION_HEADER2.from_buffer_copy(buffer)
+ if self.Header.Type in SectionHeaderType:
+ self.Name = SectionHeaderType[self.Header.Type]
+ elif self.Header.Type == 0:
+ self.Name = "EFI_SECTION_ALL"
+ else:
+ self.Name = "SECTION"
+ if self.Header.Type in HeaderType:
+ self.ExtHeader = self.GetExtHeader(self.Header.Type, buffer[self.Header.Common_Header_Size():], (self.Header.SECTION_SIZE-self.Header.Common_Header_Size()))
+ self.HeaderLength = self.Header.Common_Header_Size() + self.ExtHeader.ExtHeaderSize()
+ else:
+ self.ExtHeader = None
+ self.HeaderLength = self.Header.Common_Header_Size()
+ self.Size = self.Header.SECTION_SIZE
+ self.Type = self.Header.Type
+ self.HOffset = 0
+ self.DOffset = 0
+ self.ROffset = 0
+ self.Data = b''
+ self.OriData = b''
+ self.OriHeader = b''
+ self.PadData = b''
+ self.IsPadSection = False
+ self.SectionMaxAlignment = SECTION_COMMON_ALIGNMENT # 4-align
+
+ def GetExtHeader(self, Type: int, buffer: bytes, nums: int=0) -> None:
+ if Type == 0x01:
+ return EFI_COMPRESSION_SECTION.from_buffer_copy(buffer)
+ elif Type == 0x02:
+ return EFI_GUID_DEFINED_SECTION.from_buffer_copy(buffer)
+ elif Type == 0x14:
+ return Get_VERSION_Header((nums - 2)//2).from_buffer_copy(buffer)
+ elif Type == 0x15:
+ return Get_USER_INTERFACE_Header(nums//2).from_buffer_copy(buffer)
+ elif Type == 0x18:
+ return EFI_FREEFORM_SUBTYPE_GUID_SECTION.from_buffer_copy(buffer)
+
+class FreeSpaceNode:
+ def __init__(self, buffer: bytes) -> None:
+ self.Name = 'Free_Space'
+ self.Data = buffer
+ self.Size = len(buffer)
+ self.HOffset = 0
+ self.DOffset = 0
+ self.ROffset = 0
+ self.PadData = b''
diff --git a/BaseTools/Source/Python/FMMT/core/FMMTOperation.py b/BaseTools/Source/Python/FMMT/core/FMMTOperation.py
index d4aa339703..d9ab6f69e4 100644
--- a/BaseTools/Source/Python/FMMT/core/FMMTOperation.py
+++ b/BaseTools/Source/Python/FMMT/core/FMMTOperation.py
@@ -1,232 +1,232 @@
-## @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):
- if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].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):
- if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].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):
- if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].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))
+## @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):
+ if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].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):
+ if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].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):
+ if FmmtParser.WholeFvTree.Findlist[index].Parent.key != Fv_name and FmmtParser.WholeFvTree.Findlist[index].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))
diff --git a/BaseTools/Source/Python/FMMT/core/FMMTParser.py b/BaseTools/Source/Python/FMMT/core/FMMTParser.py
index 25a2bde799..18de96c08e 100644
--- a/BaseTools/Source/Python/FMMT/core/FMMTParser.py
+++ b/BaseTools/Source/Python/FMMT/core/FMMTParser.py
@@ -1,87 +1,87 @@
-## @file
-# This file is used to define the interface of Bios Parser.
-#
-# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-from FirmwareStorageFormat.Common import *
-from core.BinaryFactoryProduct import ParserEntry
-from core.BiosTreeNode import *
-from core.BiosTree import *
-from core.GuidTools import *
-from utils.FmmtLogger import FmmtLogger as logger
-
-class FMMTParser:
- def __init__(self, name: str, TYPE: str) -> None:
- self.WholeFvTree = BIOSTREE(name)
- self.WholeFvTree.type = TYPE
- self.FinalData = b''
- self.BinaryInfo = []
-
- ## Parser the nodes in WholeTree.
- def ParserFromRoot(self, WholeFvTree=None, whole_data: bytes=b'', Reloffset: int=0) -> None:
- if WholeFvTree.type == ROOT_TREE or WholeFvTree.type == ROOT_FV_TREE or WholeFvTree.type == ROOT_ELF_TREE:
- ParserEntry().DataParser(self.WholeFvTree, whole_data, Reloffset)
- else:
- ParserEntry().DataParser(WholeFvTree, whole_data, Reloffset)
- for Child in WholeFvTree.Child:
- self.ParserFromRoot(Child, "")
-
- ## Encapuslation all the data in tree into self.FinalData
- def Encapsulation(self, rootTree, CompressStatus: bool) -> None:
- # If current node is Root node, skip it.
- if rootTree.type == ROOT_TREE or rootTree.type == ROOT_FV_TREE or rootTree.type == ROOT_FFS_TREE or rootTree.type == ROOT_SECTION_TREE:
- logger.debug('Encapsulated successfully!')
- # If current node do not have Header, just add Data.
- elif rootTree.type == BINARY_DATA or rootTree.type == FFS_FREE_SPACE:
- self.FinalData += rootTree.Data.Data
- rootTree.Child = []
- # If current node do not have Child and ExtHeader, just add its Header and Data.
- elif rootTree.type == DATA_FV_TREE or rootTree.type == FFS_PAD:
- self.FinalData += struct2stream(rootTree.Data.Header) + rootTree.Data.Data + rootTree.Data.PadData
- if rootTree.isFinalChild():
- ParTree = rootTree.Parent
- if ParTree.type != 'ROOT':
- self.FinalData += ParTree.Data.PadData
- rootTree.Child = []
- # If current node is not Section node and may have Child and ExtHeader, add its Header,ExtHeader. If do not have Child, add its Data.
- elif rootTree.type == FV_TREE or rootTree.type == FFS_TREE or rootTree.type == SEC_FV_TREE:
- if rootTree.HasChild():
- self.FinalData += struct2stream(rootTree.Data.Header)
- else:
- self.FinalData += struct2stream(rootTree.Data.Header) + rootTree.Data.Data + rootTree.Data.PadData
- if rootTree.isFinalChild():
- ParTree = rootTree.Parent
- if ParTree.type != 'ROOT':
- self.FinalData += ParTree.Data.PadData
- # If current node is Section, need to consider its ExtHeader, Child and Compressed Status.
- elif rootTree.type == SECTION_TREE:
- # Not compressed section
- if rootTree.Data.OriData == b'' or (rootTree.Data.OriData != b'' and CompressStatus):
- if rootTree.HasChild():
- if rootTree.Data.ExtHeader:
- self.FinalData += struct2stream(rootTree.Data.Header) + struct2stream(rootTree.Data.ExtHeader)
- else:
- self.FinalData += struct2stream(rootTree.Data.Header)
- else:
- Data = rootTree.Data.Data
- if rootTree.Data.ExtHeader:
- self.FinalData += struct2stream(rootTree.Data.Header) + struct2stream(rootTree.Data.ExtHeader) + Data + rootTree.Data.PadData
- else:
- self.FinalData += struct2stream(rootTree.Data.Header) + Data + rootTree.Data.PadData
- if rootTree.isFinalChild():
- ParTree = rootTree.Parent
- self.FinalData += ParTree.Data.PadData
- # If compressed section
- else:
- Data = rootTree.Data.OriData
- rootTree.Child = []
- if rootTree.Data.ExtHeader:
- self.FinalData += struct2stream(rootTree.Data.Header) + struct2stream(rootTree.Data.ExtHeader) + Data + rootTree.Data.PadData
- else:
- self.FinalData += struct2stream(rootTree.Data.Header) + Data + rootTree.Data.PadData
- if rootTree.isFinalChild():
- ParTree = rootTree.Parent
- self.FinalData += ParTree.Data.PadData
- for Child in rootTree.Child:
- self.Encapsulation(Child, CompressStatus)
+## @file
+# This file is used to define the interface of Bios Parser.
+#
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+from FirmwareStorageFormat.Common import *
+from core.BinaryFactoryProduct import ParserEntry
+from core.BiosTreeNode import *
+from core.BiosTree import *
+from core.GuidTools import *
+from utils.FmmtLogger import FmmtLogger as logger
+
+class FMMTParser:
+ def __init__(self, name: str, TYPE: str) -> None:
+ self.WholeFvTree = BIOSTREE(name)
+ self.WholeFvTree.type = TYPE
+ self.FinalData = b''
+ self.BinaryInfo = []
+
+ ## Parser the nodes in WholeTree.
+ def ParserFromRoot(self, WholeFvTree=None, whole_data: bytes=b'', Reloffset: int=0) -> None:
+ if WholeFvTree.type == ROOT_TREE or WholeFvTree.type == ROOT_FV_TREE or WholeFvTree.type == ROOT_ELF_TREE:
+ ParserEntry().DataParser(self.WholeFvTree, whole_data, Reloffset)
+ else:
+ ParserEntry().DataParser(WholeFvTree, whole_data, Reloffset)
+ for Child in WholeFvTree.Child:
+ self.ParserFromRoot(Child, "")
+
+ ## Encapuslation all the data in tree into self.FinalData
+ def Encapsulation(self, rootTree, CompressStatus: bool) -> None:
+ # If current node is Root node, skip it.
+ if rootTree.type == ROOT_TREE or rootTree.type == ROOT_FV_TREE or rootTree.type == ROOT_FFS_TREE or rootTree.type == ROOT_SECTION_TREE:
+ logger.debug('Encapsulated successfully!')
+ # If current node do not have Header, just add Data.
+ elif rootTree.type == BINARY_DATA or rootTree.type == FFS_FREE_SPACE:
+ self.FinalData += rootTree.Data.Data
+ rootTree.Child = []
+ # If current node do not have Child and ExtHeader, just add its Header and Data.
+ elif rootTree.type == DATA_FV_TREE or rootTree.type == FFS_PAD:
+ self.FinalData += struct2stream(rootTree.Data.Header) + rootTree.Data.Data + rootTree.Data.PadData
+ if rootTree.isFinalChild():
+ ParTree = rootTree.Parent
+ if ParTree.type != 'ROOT':
+ self.FinalData += ParTree.Data.PadData
+ rootTree.Child = []
+ # If current node is not Section node and may have Child and ExtHeader, add its Header,ExtHeader. If do not have Child, add its Data.
+ elif rootTree.type == FV_TREE or rootTree.type == FFS_TREE or rootTree.type == SEC_FV_TREE:
+ if rootTree.HasChild():
+ self.FinalData += struct2stream(rootTree.Data.Header)
+ else:
+ self.FinalData += struct2stream(rootTree.Data.Header) + rootTree.Data.Data + rootTree.Data.PadData
+ if rootTree.isFinalChild():
+ ParTree = rootTree.Parent
+ if ParTree.type != 'ROOT':
+ self.FinalData += ParTree.Data.PadData
+ # If current node is Section, need to consider its ExtHeader, Child and Compressed Status.
+ elif rootTree.type == SECTION_TREE:
+ # Not compressed section
+ if rootTree.Data.OriData == b'' or (rootTree.Data.OriData != b'' and CompressStatus):
+ if rootTree.HasChild():
+ if rootTree.Data.ExtHeader:
+ self.FinalData += struct2stream(rootTree.Data.Header) + struct2stream(rootTree.Data.ExtHeader)
+ else:
+ self.FinalData += struct2stream(rootTree.Data.Header)
+ else:
+ Data = rootTree.Data.Data
+ if rootTree.Data.ExtHeader:
+ self.FinalData += struct2stream(rootTree.Data.Header) + struct2stream(rootTree.Data.ExtHeader) + Data + rootTree.Data.PadData
+ else:
+ self.FinalData += struct2stream(rootTree.Data.Header) + Data + rootTree.Data.PadData
+ if rootTree.isFinalChild():
+ ParTree = rootTree.Parent
+ self.FinalData += ParTree.Data.PadData
+ # If compressed section
+ else:
+ Data = rootTree.Data.OriData
+ rootTree.Child = []
+ if rootTree.Data.ExtHeader:
+ self.FinalData += struct2stream(rootTree.Data.Header) + struct2stream(rootTree.Data.ExtHeader) + Data + rootTree.Data.PadData
+ else:
+ self.FinalData += struct2stream(rootTree.Data.Header) + Data + rootTree.Data.PadData
+ if rootTree.isFinalChild():
+ ParTree = rootTree.Parent
+ self.FinalData += ParTree.Data.PadData
+ for Child in rootTree.Child:
+ self.Encapsulation(Child, CompressStatus)
diff --git a/BaseTools/Source/Python/FMMT/core/FvHandler.py b/BaseTools/Source/Python/FMMT/core/FvHandler.py
index 7a60760336..0e11e47031 100644
--- a/BaseTools/Source/Python/FMMT/core/FvHandler.py
+++ b/BaseTools/Source/Python/FMMT/core/FvHandler.py
@@ -1,683 +1,683 @@
-## @file
-# This file is used to the implementation of Bios layout handler.
-#
-# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-import os
-from core.BiosTree import *
-from core.GuidTools import GUIDTools
-from core.BiosTreeNode import *
-from FirmwareStorageFormat.Common import *
-from utils.FmmtLogger import FmmtLogger as logger
-
-EFI_FVB2_ERASE_POLARITY = 0x00000800
-
-def ChangeSize(TargetTree, size_delta: int=0) -> None:
- # If Size increase delta, then should be: size_delta = -delta
- if type(TargetTree.Data.Header) == type(EFI_FFS_FILE_HEADER2()) or type(TargetTree.Data.Header) == type(EFI_COMMON_SECTION_HEADER2()):
- TargetTree.Data.Size -= size_delta
- TargetTree.Data.Header.ExtendedSize -= size_delta
- elif TargetTree.type == SECTION_TREE and TargetTree.Data.OriData:
- OriSize = TargetTree.Data.Header.SECTION_SIZE
- OriSize -= size_delta
- TargetTree.Data.Header.Size[0] = OriSize % (16**2)
- TargetTree.Data.Header.Size[1] = OriSize % (16**4) //(16**2)
- TargetTree.Data.Header.Size[2] = OriSize // (16**4)
- else:
- TargetTree.Data.Size -= size_delta
- TargetTree.Data.Header.Size[0] = TargetTree.Data.Size % (16**2)
- TargetTree.Data.Header.Size[1] = TargetTree.Data.Size % (16**4) //(16**2)
- TargetTree.Data.Header.Size[2] = TargetTree.Data.Size // (16**4)
-
-def ModifyFfsType(TargetFfs) -> None:
- if type(TargetFfs.Data.Header) == type(EFI_FFS_FILE_HEADER()) and TargetFfs.Data.Size > 0xFFFFFF:
- ExtendSize = TargetFfs.Data.Header.FFS_FILE_SIZE + 8
- New_Header = EFI_FFS_FILE_HEADER2()
- New_Header.Name = TargetFfs.Data.Header.Name
- New_Header.IntegrityCheck = TargetFfs.Data.Header.IntegrityCheck
- New_Header.Type = TargetFfs.Data.Header.Type
- New_Header.Attributes = TargetFfs.Data.Header.Attributes | 0x01 # set the Attribute with FFS_ATTRIB_LARGE_FILE (0x01)
- NewSize = 0
- New_Header.Size[0] = NewSize % (16**2) # minus the delta size of Header
- New_Header.Size[1] = NewSize % (16**4) //(16**2)
- New_Header.Size[2] = NewSize // (16**4)
- New_Header.State = TargetFfs.Data.Header.State
- New_Header.ExtendedSize = ExtendSize
- TargetFfs.Data.Header = New_Header
- TargetFfs.Data.Size = TargetFfs.Data.Header.FFS_FILE_SIZE
- TargetFfs.Data.HeaderLength = TargetFfs.Data.Header.HeaderLength
- TargetFfs.Data.ModCheckSum()
- elif type(TargetFfs.Data.Header) == type(EFI_FFS_FILE_HEADER2()) and TargetFfs.Data.Size <= 0xFFFFFF:
- New_Header = EFI_FFS_FILE_HEADER()
- New_Header.Name = TargetFfs.Data.Header.Name
- New_Header.IntegrityCheck = TargetFfs.Data.Header.IntegrityCheck
- New_Header.Type = TargetFfs.Data.Header.Type
- New_Header.Attributes = TargetFfs.Data.Header.Attributes - 1 # remove the FFS_ATTRIB_LARGE_FILE (0x01) from Attribute
- New_Header.Size[0] = (TargetFfs.Data.Size - 8) % (16**2) # minus the delta size of Header
- New_Header.Size[1] = (TargetFfs.Data.Size - 8) % (16**4) //(16**2)
- New_Header.Size[2] = (TargetFfs.Data.Size - 8) // (16**4)
- New_Header.State = TargetFfs.Data.Header.State
- TargetFfs.Data.Header = New_Header
- TargetFfs.Data.Size = TargetFfs.Data.Header.FFS_FILE_SIZE
- TargetFfs.Data.HeaderLength = TargetFfs.Data.Header.HeaderLength
- TargetFfs.Data.ModCheckSum()
- if struct2stream(TargetFfs.Parent.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE:
- NeedChange = True
- for item in TargetFfs.Parent.Child:
- if type(item.Data.Header) == type(EFI_FFS_FILE_HEADER2()):
- NeedChange = False
- if NeedChange:
- TargetFfs.Parent.Data.Header.FileSystemGuid = ModifyGuidFormat("8c8ce578-8a3d-4f1c-9935-896185c32dd3")
-
- if type(TargetFfs.Data.Header) == type(EFI_FFS_FILE_HEADER2()):
- TarParent = TargetFfs.Parent
- while TarParent:
- if TarParent.type == FV_TREE and struct2stream(TarParent.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE:
- TarParent.Data.Header.FileSystemGuid = ModifyGuidFormat("5473C07A-3DCB-4dca-BD6F-1E9689E7349A")
- TarParent = TarParent.Parent
-
-def PadSectionModify(PadSection, Offset) -> None:
- # Offset > 0, Size decrease; Offset < 0, Size increase;
- ChangeSize(PadSection, Offset)
- PadSection.Data.Data = (PadSection.Data.Size - PadSection.Data.HeaderLength) * b'\xff'
-
-def ModifySectionType(TargetSection) -> None:
- # If Section Size is increased larger than 0xFFFFFF, need modify Section Header from EFI_COMMON_SECTION_HEADER to EFI_COMMON_SECTION_HEADER2.
- if type(TargetSection.Data.Header) == type(EFI_COMMON_SECTION_HEADER()) and TargetSection.Data.Size >= 0xFFFFFF:
- New_Header = EFI_COMMON_SECTION_HEADER2()
- New_Header.Type = TargetSection.Data.Header.Type
- NewSize = 0xFFFFFF
- New_Header.Size[0] = NewSize % (16**2) # minus the delta size of Header
- New_Header.Size[1] = NewSize % (16**4) //(16**2)
- New_Header.Size[2] = NewSize // (16**4)
- New_Header.ExtendedSize = TargetSection.Data.Size + 4
- TargetSection.Data.Header = New_Header
- TargetSection.Data.Size = TargetSection.Data.Header.SECTION_SIZE
- # Align the Header's added 4 bit to 8-alignment to promise the following Ffs's align correctly.
- if TargetSection.LastRel.Data.IsPadSection:
- PadSectionModify(TargetSection.LastRel, -4)
- else:
- SecParent = TargetSection.Parent
- Target_index = SecParent.Child.index(TargetSection)
- NewPadSection = SectionNode(b'\x00\x00\x00\x19')
- SecParent.insertChild(NewPadSection, Target_index)
- # If Section Size is decreased smaller than 0xFFFFFF, need modify Section Header from EFI_COMMON_SECTION_HEADER2 to EFI_COMMON_SECTION_HEADER.
- elif type(TargetSection.Data.Header) == type(EFI_COMMON_SECTION_HEADER2()) and TargetSection.Data.Size < 0xFFFFFF:
- New_Header = EFI_COMMON_SECTION_HEADER()
- New_Header.Type = TargetSection.Data.Header.Type
- New_Header.Size[0] = (TargetSection.Data.Size - 4) % (16**2) # minus the delta size of Header
- New_Header.Size[1] = (TargetSection.Data.Size - 4) % (16**4) //(16**2)
- New_Header.Size[2] = (TargetSection.Data.Size - 4) // (16**4)
- TargetSection.Data.Header = New_Header
- TargetSection.Data.Size = TargetSection.Data.Header.SECTION_SIZE
- # Align the Header's added 4 bit to 8-alignment to promise the following Ffs's align correctly.
- if TargetSection.LastRel.Data.IsPadSection:
- PadSectionModify(TargetSection.LastRel, -4)
- else:
- SecParent = TargetSection.Parent
- Target_index = SecParent.Child.index(TargetSection)
- NewPadSection = SectionNode(b'\x00\x00\x00\x19')
- SecParent.insertChild(NewPadSection, Target_index)
-
-def ModifyFvExtData(TreeNode) -> None:
- FvExtData = b''
- if TreeNode.Data.Header.ExtHeaderOffset:
- FvExtHeader = struct2stream(TreeNode.Data.ExtHeader)
- FvExtData += FvExtHeader
- if TreeNode.Data.Header.ExtHeaderOffset and TreeNode.Data.ExtEntryExist:
- FvExtEntry = struct2stream(TreeNode.Data.ExtEntry)
- FvExtData += FvExtEntry
- if FvExtData:
- InfoNode = TreeNode.Child[0]
- InfoNode.Data.Data = FvExtData + InfoNode.Data.Data[TreeNode.Data.ExtHeader.ExtHeaderSize:]
- InfoNode.Data.ModCheckSum()
-
-def ModifyFvSystemGuid(TargetFv) -> None:
- if struct2stream(TargetFv.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE:
- TargetFv.Data.Header.FileSystemGuid = ModifyGuidFormat("5473C07A-3DCB-4dca-BD6F-1E9689E7349A")
- TargetFv.Data.ModCheckSum()
- TargetFv.Data.Data = b''
- for item in TargetFv.Child:
- if item.type == FFS_FREE_SPACE:
- TargetFv.Data.Data += item.Data.Data + item.Data.PadData
- else:
- TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
-
-class FvHandler:
- def __init__(self, NewFfs, TargetFfs=None) -> None:
- self.NewFfs = NewFfs
- self.TargetFfs = TargetFfs
- self.Status = False
- self.Remain_New_Free_Space = 0
-
- ## Use for Compress the Section Data
- def CompressData(self, TargetTree) -> None:
- TreePath = TargetTree.GetTreePath()
- pos = len(TreePath)
- while pos:
- if not self.Status:
- if TreePath[pos-1].type == SECTION_TREE and TreePath[pos-1].Data.Type == 0x02:
- self.CompressSectionData(TreePath[pos-1], None, TreePath[pos-1].Data.ExtHeader.SectionDefinitionGuid)
- else:
- if pos == len(TreePath):
- self.CompressSectionData(TreePath[pos-1], pos)
- else:
- self.CompressSectionData(TreePath[pos-1], None)
- pos -= 1
-
- def CompressSectionData(self, TargetTree, pos: int, GuidTool=None) -> None:
- NewData = b''
- temp_save_child = TargetTree.Child
- if TargetTree.Data:
- # Update current node data as adding all the header and data of its child node.
- for item in temp_save_child:
- if item.type == SECTION_TREE and not item.Data.OriData and item.Data.ExtHeader:
- NewData += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.Data + item.Data.PadData
- elif item.type == SECTION_TREE and item.Data.OriData and not item.Data.ExtHeader:
- NewData += struct2stream(item.Data.Header) + item.Data.OriData + item.Data.PadData
- elif item.type == SECTION_TREE and item.Data.OriData and item.Data.ExtHeader:
- NewData += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.OriData + item.Data.PadData
- elif item.type == FFS_FREE_SPACE:
- NewData += item.Data.Data + item.Data.PadData
- else:
- NewData += struct2stream(item.Data.Header) + item.Data.Data + item.Data.PadData
- # If node is FFS_TREE, update Pad data and Header info.
- # Remain_New_Free_Space is used for move more free space into lst level Fv.
- if TargetTree.type == FFS_TREE:
- New_Pad_Size = GetPadSize(len(NewData), 8)
- Size_delta = len(NewData) - len(TargetTree.Data.Data)
- ChangeSize(TargetTree, -Size_delta)
- Delta_Pad_Size = len(TargetTree.Data.PadData) - New_Pad_Size
- self.Remain_New_Free_Space += Delta_Pad_Size
- TargetTree.Data.PadData = b'\xff' * New_Pad_Size
- TargetTree.Data.ModCheckSum()
- # If node is FV_TREE, update Pad data and Header info.
- # Consume Remain_New_Free_Space is used for move more free space into lst level Fv.
- elif TargetTree.type == FV_TREE or TargetTree.type == SEC_FV_TREE and not pos:
- if self.Remain_New_Free_Space:
- if TargetTree.Data.Free_Space:
- TargetTree.Data.Free_Space += self.Remain_New_Free_Space
- NewData += self.Remain_New_Free_Space * b'\xff'
- TargetTree.Child[-1].Data.Data += self.Remain_New_Free_Space * b'\xff'
- else:
- TargetTree.Data.Data += self.Remain_New_Free_Space * b'\xff'
- New_Free_Space = BIOSTREE('FREE_SPACE')
- New_Free_Space.type = FFS_FREE_SPACE
- New_Free_Space.Data = FreeSpaceNode(b'\xff' * self.Remain_New_Free_Space)
- TargetTree.insertChild(New_Free_Space)
- self.Remain_New_Free_Space = 0
- if TargetTree.type == SEC_FV_TREE:
- Size_delta = len(NewData) + self.Remain_New_Free_Space - len(TargetTree.Data.Data)
- TargetTree.Data.Header.FvLength += Size_delta
- TargetTree.Data.ModFvExt()
- TargetTree.Data.ModFvSize()
- TargetTree.Data.ModExtHeaderData()
- ModifyFvExtData(TargetTree)
- TargetTree.Data.ModCheckSum()
- # If node is SECTION_TREE and not guided section, update Pad data and Header info.
- # Remain_New_Free_Space is used for move more free space into lst level Fv.
- elif TargetTree.type == SECTION_TREE and TargetTree.Data.Type != 0x02:
- New_Pad_Size = GetPadSize(len(NewData), 4)
- Size_delta = len(NewData) - len(TargetTree.Data.Data)
- ChangeSize(TargetTree, -Size_delta)
- if TargetTree.NextRel:
- Delta_Pad_Size = len(TargetTree.Data.PadData) - New_Pad_Size
- self.Remain_New_Free_Space += Delta_Pad_Size
- TargetTree.Data.PadData = b'\x00' * New_Pad_Size
- TargetTree.Data.Data = NewData
- if GuidTool:
- guidtool = GUIDTools().__getitem__(struct2stream(GuidTool))
- if not guidtool.ifexist:
- logger.error("GuidTool {} is not found when decompressing {} file.\n".format(guidtool.command, TargetTree.Parent.Data.Name))
- raise Exception("Process Failed: GuidTool not found!")
- CompressedData = guidtool.pack(TargetTree.Data.Data)
- if len(CompressedData) < len(TargetTree.Data.OriData):
- New_Pad_Size = GetPadSize(len(CompressedData), SECTION_COMMON_ALIGNMENT)
- Size_delta = len(CompressedData) - len(TargetTree.Data.OriData)
- ChangeSize(TargetTree, -Size_delta)
- if TargetTree.NextRel:
- TargetTree.Data.PadData = b'\x00' * New_Pad_Size
- self.Remain_New_Free_Space = len(TargetTree.Data.OriData) + len(TargetTree.Data.PadData) - len(CompressedData) - New_Pad_Size
- else:
- TargetTree.Data.PadData = b''
- self.Remain_New_Free_Space = len(TargetTree.Data.OriData) - len(CompressedData)
- TargetTree.Data.OriData = CompressedData
- elif len(CompressedData) == len(TargetTree.Data.OriData):
- TargetTree.Data.OriData = CompressedData
- elif len(CompressedData) > len(TargetTree.Data.OriData):
- New_Pad_Size = GetPadSize(len(CompressedData), SECTION_COMMON_ALIGNMENT)
- self.Remain_New_Free_Space = len(CompressedData) + New_Pad_Size - len(TargetTree.Data.OriData) - len(TargetTree.Data.PadData)
- self.ModifyTest(TargetTree, self.Remain_New_Free_Space)
- self.Status = True
-
- def ModifyTest(self, ParTree, Needed_Space: int) -> None:
- # If have needed space, will find if there have free space in parent tree, meanwhile update the node data.
- if Needed_Space > 0:
- # If current node is a Fv node
- if ParTree.type == FV_TREE or ParTree.type == SEC_FV_TREE:
- ParTree.Data.Data = b''
- # First check if Fv free space is enough for needed space.
- # If so, use the current Fv free space;
- # Else, use all the Free space, and recalculate needed space, continue finding in its parent node.
- Needed_Space = Needed_Space - ParTree.Data.Free_Space
- if Needed_Space < 0:
- ParTree.Child[-1].Data.Data = b'\xff' * (-Needed_Space)
- ParTree.Data.Free_Space = (-Needed_Space)
- self.Status = True
- else:
- if ParTree.type == FV_TREE:
- self.Status = False
- else:
- BlockSize = ParTree.Data.Header.BlockMap[0].Length
- New_Add_Len = BlockSize - Needed_Space%BlockSize
- if New_Add_Len % BlockSize:
- ParTree.Child[-1].Data.Data = b'\xff' * New_Add_Len
- ParTree.Data.Free_Space = New_Add_Len
- Needed_Space += New_Add_Len
- else:
- ParTree.Child.remove(ParTree.Child[-1])
- ParTree.Data.Free_Space = 0
- ParTree.Data.Size += Needed_Space
- ParTree.Data.Header.FvLength = ParTree.Data.Size
- ModifyFvSystemGuid(ParTree)
- for item in ParTree.Child:
- if item.type == FFS_FREE_SPACE:
- ParTree.Data.Data += item.Data.Data + item.Data.PadData
- else:
- ParTree.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
- ParTree.Data.ModFvExt()
- ParTree.Data.ModFvSize()
- ParTree.Data.ModExtHeaderData()
- ModifyFvExtData(ParTree)
- ParTree.Data.ModCheckSum()
- # If current node is a Ffs node
- elif ParTree.type == FFS_TREE:
- ParTree.Data.Data = b''
- OriHeaderLen = ParTree.Data.HeaderLength
- # Update its data as adding all the header and data of its child node.
- for item in ParTree.Child:
- if item.Data.OriData:
- if item.Data.ExtHeader:
- ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.OriData + item.Data.PadData
- else:
- ParTree.Data.Data += struct2stream(item.Data.Header)+ item.Data.OriData + item.Data.PadData
- else:
- if item.Data.ExtHeader:
- ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.Data + item.Data.PadData
- else:
- ParTree.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
- ChangeSize(ParTree, -Needed_Space)
- ModifyFfsType(ParTree)
- # Recalculate pad data, update needed space with Delta_Pad_Size.
- Needed_Space += ParTree.Data.HeaderLength - OriHeaderLen
- New_Pad_Size = GetPadSize(ParTree.Data.Size, FFS_COMMON_ALIGNMENT)
- Delta_Pad_Size = New_Pad_Size - len(ParTree.Data.PadData)
- Needed_Space += Delta_Pad_Size
- ParTree.Data.PadData = b'\xff' * GetPadSize(ParTree.Data.Size, FFS_COMMON_ALIGNMENT)
- ParTree.Data.ModCheckSum()
- # If current node is a Section node
- elif ParTree.type == SECTION_TREE:
- OriData = ParTree.Data.Data
- OriHeaderLen = ParTree.Data.HeaderLength
- ParTree.Data.Data = b''
- # Update its data as adding all the header and data of its child node.
- for item in ParTree.Child:
- if item.type == SECTION_TREE and item.Data.ExtHeader and item.Data.Type != 0x02:
- ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.Data + item.Data.PadData
- elif item.type == SECTION_TREE and item.Data.ExtHeader and item.Data.Type == 0x02:
- ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.OriData + item.Data.PadData
- else:
- ParTree.Data.Data += struct2stream(item.Data.Header) + item.Data.Data + item.Data.PadData
- # If the current section is guided section
- if ParTree.Data.Type == 0x02:
- guidtool = GUIDTools().__getitem__(struct2stream(ParTree.Data.ExtHeader.SectionDefinitionGuid))
- if not guidtool.ifexist:
- logger.error("GuidTool {} is not found when decompressing {} file.\n".format(guidtool.command, ParTree.Parent.Data.Name))
- raise Exception("Process Failed: GuidTool not found!")
- # Recompress current data, and recalculate the needed space
- CompressedData = guidtool.pack(ParTree.Data.Data)
- Needed_Space = len(CompressedData) - len(ParTree.Data.OriData)
- ParTree.Data.OriData = CompressedData
- New_Size = ParTree.Data.HeaderLength + len(CompressedData)
- ParTree.Data.Header.Size[0] = New_Size % (16**2)
- ParTree.Data.Header.Size[1] = New_Size % (16**4) //(16**2)
- ParTree.Data.Header.Size[2] = New_Size // (16**4)
- ParTree.Data.Size = ParTree.Data.Header.SECTION_SIZE
- ModifySectionType(ParTree)
- Needed_Space += ParTree.Data.HeaderLength - OriHeaderLen
- # Update needed space with Delta_Pad_Size
- if ParTree.NextRel:
- New_Pad_Size = GetPadSize(ParTree.Data.Size, SECTION_COMMON_ALIGNMENT)
- Delta_Pad_Size = New_Pad_Size - len(ParTree.Data.PadData)
- ParTree.Data.PadData = b'\x00' * New_Pad_Size
- Needed_Space += Delta_Pad_Size
- else:
- ParTree.Data.PadData = b''
- if Needed_Space < 0:
- self.Remain_New_Free_Space = len(ParTree.Data.OriData) - len(CompressedData)
- # If current section is not guided section
- elif Needed_Space:
- ChangeSize(ParTree, -Needed_Space)
- ModifySectionType(ParTree)
- # Update needed space with Delta_Pad_Size
- Needed_Space += ParTree.Data.HeaderLength - OriHeaderLen
- New_Pad_Size = GetPadSize(ParTree.Data.Size, SECTION_COMMON_ALIGNMENT)
- Delta_Pad_Size = New_Pad_Size - len(ParTree.Data.PadData)
- Needed_Space += Delta_Pad_Size
- ParTree.Data.PadData = b'\x00' * New_Pad_Size
- NewParTree = ParTree.Parent
- ROOT_TYPE = [ROOT_FV_TREE, ROOT_FFS_TREE, ROOT_SECTION_TREE, ROOT_TREE]
- if NewParTree and NewParTree.type not in ROOT_TYPE:
- self.ModifyTest(NewParTree, Needed_Space)
- # If current node have enough space, will recompress all the related node data, return true.
- else:
- self.CompressData(ParTree)
- self.Status = True
-
- def ReplaceFfs(self) -> bool:
- logger.debug('Start Replacing Process......')
- TargetFv = self.TargetFfs.Parent
- # If the Fv Header Attributes is EFI_FVB2_ERASE_POLARITY, Child Ffs Header State need be reversed.
- if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
- self.NewFfs.Data.Header.State = c_uint8(
- ~self.NewFfs.Data.Header.State)
- # NewFfs parsing will not calculate the PadSize, thus recalculate.
- self.NewFfs.Data.PadData = b'\xff' * GetPadSize(self.NewFfs.Data.Size, FFS_COMMON_ALIGNMENT)
- if self.NewFfs.Data.Size >= self.TargetFfs.Data.Size:
- Needed_Space = self.NewFfs.Data.Size + len(self.NewFfs.Data.PadData) - self.TargetFfs.Data.Size - len(self.TargetFfs.Data.PadData)
- # If TargetFv have enough free space, just move part of the free space to NewFfs.
- if Needed_Space == 0:
- Target_index = TargetFv.Child.index(self.TargetFfs)
- TargetFv.Child.remove(self.TargetFfs)
- TargetFv.insertChild(self.NewFfs, Target_index)
- # Modify TargetFv Header and ExtHeader info.
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModFvSize()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- # Recompress from the Fv node to update all the related node data.
- self.CompressData(TargetFv)
- # return the Status
- self.Status = True
- elif TargetFv.Data.Free_Space >= Needed_Space:
- # Modify TargetFv Child info and BiosTree.
- TargetFv.Child[-1].Data.Data = b'\xff' * (TargetFv.Data.Free_Space - Needed_Space)
- TargetFv.Data.Free_Space -= Needed_Space
- Target_index = TargetFv.Child.index(self.TargetFfs)
- TargetFv.Child.remove(self.TargetFfs)
- TargetFv.insertChild(self.NewFfs, Target_index)
- # Modify TargetFv Header and ExtHeader info.
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModFvSize()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- # Recompress from the Fv node to update all the related node data.
- self.CompressData(TargetFv)
- # return the Status
- self.Status = True
- # If TargetFv do not have enough free space, need move part of the free space of TargetFv's parent Fv to TargetFv/NewFfs.
- else:
- if TargetFv.type == FV_TREE:
- self.Status = False
- else:
- # Recalculate TargetFv needed space to keep it match the BlockSize setting.
- Needed_Space -= TargetFv.Data.Free_Space
- BlockSize = TargetFv.Data.Header.BlockMap[0].Length
- New_Add_Len = BlockSize - Needed_Space%BlockSize
- Target_index = TargetFv.Child.index(self.TargetFfs)
- if New_Add_Len % BlockSize:
- TargetFv.Child[-1].Data.Data = b'\xff' * New_Add_Len
- TargetFv.Data.Free_Space = New_Add_Len
- Needed_Space += New_Add_Len
- TargetFv.insertChild(self.NewFfs, Target_index)
- TargetFv.Child.remove(self.TargetFfs)
- else:
- TargetFv.Child.remove(self.TargetFfs)
- TargetFv.Data.Free_Space = 0
- TargetFv.insertChild(self.NewFfs)
- # Encapsulate the Fv Data for update.
- TargetFv.Data.Data = b''
- for item in TargetFv.Child:
- if item.type == FFS_FREE_SPACE:
- TargetFv.Data.Data += item.Data.Data + item.Data.PadData
- else:
- TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
- TargetFv.Data.Size += Needed_Space
- # Modify TargetFv Data Header and ExtHeader info.
- TargetFv.Data.Header.FvLength = TargetFv.Data.Size
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModFvSize()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- # Start free space calculating and moving process.
- self.ModifyTest(TargetFv.Parent, Needed_Space)
- else:
- New_Free_Space = self.TargetFfs.Data.Size + len(self.TargetFfs.Data.PadData) - self.NewFfs.Data.Size - len(self.NewFfs.Data.PadData)
- # If TargetFv already have free space, move the new free space into it.
- if TargetFv.Data.Free_Space:
- TargetFv.Child[-1].Data.Data += b'\xff' * New_Free_Space
- TargetFv.Data.Free_Space += New_Free_Space
- Target_index = TargetFv.Child.index(self.TargetFfs)
- TargetFv.Child.remove(self.TargetFfs)
- TargetFv.insertChild(self.NewFfs, Target_index)
- # If TargetFv do not have free space, create free space for Fv.
- else:
- New_Free_Space_Tree = BIOSTREE('FREE_SPACE')
- New_Free_Space_Tree.type = FFS_FREE_SPACE
- New_Free_Space_Tree.Data = FfsNode(b'\xff' * New_Free_Space)
- TargetFv.Data.Free_Space = New_Free_Space
- TargetFv.insertChild(New_Free_Space)
- Target_index = TargetFv.Child.index(self.TargetFfs)
- TargetFv.Child.remove(self.TargetFfs)
- TargetFv.insertChild(self.NewFfs, Target_index)
- # Modify TargetFv Header and ExtHeader info.
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModFvSize()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- # Recompress from the Fv node to update all the related node data.
- self.CompressData(TargetFv)
- self.Status = True
- logger.debug('Done!')
- return self.Status
-
- def AddFfs(self) -> bool:
- logger.debug('Start Adding Process......')
- # NewFfs parsing will not calculate the PadSize, thus recalculate.
- self.NewFfs.Data.PadData = b'\xff' * GetPadSize(self.NewFfs.Data.Size, FFS_COMMON_ALIGNMENT)
- if self.TargetFfs.type == FFS_FREE_SPACE:
- TargetLen = self.NewFfs.Data.Size + len(self.NewFfs.Data.PadData) - self.TargetFfs.Data.Size - len(self.TargetFfs.Data.PadData)
- TargetFv = self.TargetFfs.Parent
- # If the Fv Header Attributes is EFI_FVB2_ERASE_POLARITY, Child Ffs Header State need be reversed.
- if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
- self.NewFfs.Data.Header.State = c_uint8(
- ~self.NewFfs.Data.Header.State)
- # If TargetFv have enough free space, just move part of the free space to NewFfs, split free space to NewFfs and new free space.
- if TargetLen < 0:
- self.TargetFfs.Data.Data = b'\xff' * (-TargetLen)
- TargetFv.Data.Free_Space = (-TargetLen)
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- TargetFv.insertChild(self.NewFfs, -1)
- ModifyFfsType(self.NewFfs)
- # Recompress from the Fv node to update all the related node data.
- self.CompressData(TargetFv)
- self.Status = True
- elif TargetLen == 0:
- TargetFv.Child.remove(self.TargetFfs)
- TargetFv.insertChild(self.NewFfs)
- ModifyFfsType(self.NewFfs)
- # Recompress from the Fv node to update all the related node data.
- self.CompressData(TargetFv)
- self.Status = True
- # If TargetFv do not have enough free space, need move part of the free space of TargetFv's parent Fv to TargetFv/NewFfs.
- else:
- if TargetFv.type == FV_TREE:
- self.Status = False
- elif TargetFv.type == SEC_FV_TREE:
- # Recalculate TargetFv needed space to keep it match the BlockSize setting.
- BlockSize = TargetFv.Data.Header.BlockMap[0].Length
- New_Add_Len = BlockSize - TargetLen%BlockSize
- if New_Add_Len % BlockSize:
- self.TargetFfs.Data.Data = b'\xff' * New_Add_Len
- self.TargetFfs.Data.Size = New_Add_Len
- TargetLen += New_Add_Len
- TargetFv.insertChild(self.NewFfs, -1)
- TargetFv.Data.Free_Space = New_Add_Len
- else:
- TargetFv.Child.remove(self.TargetFfs)
- TargetFv.insertChild(self.NewFfs)
- TargetFv.Data.Free_Space = 0
- ModifyFfsType(self.NewFfs)
- ModifyFvSystemGuid(TargetFv)
- TargetFv.Data.Data = b''
- for item in TargetFv.Child:
- if item.type == FFS_FREE_SPACE:
- TargetFv.Data.Data += item.Data.Data + item.Data.PadData
- else:
- TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
- # Encapsulate the Fv Data for update.
- TargetFv.Data.Size += TargetLen
- TargetFv.Data.Header.FvLength = TargetFv.Data.Size
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModFvSize()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- # Start free space calculating and moving process.
- self.ModifyTest(TargetFv.Parent, TargetLen)
- else:
- # If TargetFv do not have free space, need directly move part of the free space of TargetFv's parent Fv to TargetFv/NewFfs.
- TargetLen = self.NewFfs.Data.Size + len(self.NewFfs.Data.PadData)
- TargetFv = self.TargetFfs.Parent
- if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
- self.NewFfs.Data.Header.State = c_uint8(
- ~self.NewFfs.Data.Header.State)
- if TargetFv.type == FV_TREE:
- self.Status = False
- elif TargetFv.type == SEC_FV_TREE:
- BlockSize = TargetFv.Data.Header.BlockMap[0].Length
- New_Add_Len = BlockSize - TargetLen%BlockSize
- if New_Add_Len % BlockSize:
- New_Free_Space = BIOSTREE('FREE_SPACE')
- New_Free_Space.type = FFS_FREE_SPACE
- New_Free_Space.Data = FreeSpaceNode(b'\xff' * New_Add_Len)
- TargetLen += New_Add_Len
- TargetFv.Data.Free_Space = New_Add_Len
- TargetFv.insertChild(self.NewFfs)
- TargetFv.insertChild(New_Free_Space)
- else:
- TargetFv.insertChild(self.NewFfs)
- ModifyFfsType(self.NewFfs)
- ModifyFvSystemGuid(TargetFv)
- TargetFv.Data.Data = b''
- for item in TargetFv.Child:
- if item.type == FFS_FREE_SPACE:
- TargetFv.Data.Data += item.Data.Data + item.Data.PadData
- else:
- TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
- TargetFv.Data.Size += TargetLen
- TargetFv.Data.Header.FvLength = TargetFv.Data.Size
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModFvSize()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- self.ModifyTest(TargetFv.Parent, TargetLen)
- logger.debug('Done!')
- return self.Status
-
- def DeleteFfs(self) -> bool:
- logger.debug('Start Deleting Process......')
- Delete_Ffs = self.TargetFfs
- Delete_Fv = Delete_Ffs.Parent
- # Calculate free space
- Add_Free_Space = Delete_Ffs.Data.Size + len(Delete_Ffs.Data.PadData)
- # If Ffs parent Fv have free space, follow the rules to merge the new free space.
- if Delete_Fv.Data.Free_Space:
- # If Fv is a Section fv, free space need to be recalculated to keep align with BlockSize.
- # Other free space saved in self.Remain_New_Free_Space, will be moved to the 1st level Fv.
- if Delete_Fv.type == SEC_FV_TREE:
- Used_Size = Delete_Fv.Data.Size - Delete_Fv.Data.Free_Space - Add_Free_Space
- BlockSize = Delete_Fv.Data.Header.BlockMap[0].Length
- New_Free_Space = BlockSize - Used_Size % BlockSize
- self.Remain_New_Free_Space += Delete_Fv.Data.Free_Space + Add_Free_Space - New_Free_Space
- Delete_Fv.Child[-1].Data.Data = New_Free_Space * b'\xff'
- Delete_Fv.Data.Free_Space = New_Free_Space
- # If Fv is lst level Fv, new free space will be merged with origin free space.
- else:
- Used_Size = Delete_Fv.Data.Size - Delete_Fv.Data.Free_Space - Add_Free_Space
- Delete_Fv.Child[-1].Data.Data += Add_Free_Space * b'\xff'
- Delete_Fv.Data.Free_Space += Add_Free_Space
- New_Free_Space = Delete_Fv.Data.Free_Space
- # If Ffs parent Fv not have free space, will create new free space node to save the free space.
- else:
- # If Fv is a Section fv, new free space need to be recalculated to keep align with BlockSize.
- # Then create a Free spcae node to save the 0xff data, and insert into the Fv.
- # If have more space left, move to 1st level fv.
- if Delete_Fv.type == SEC_FV_TREE:
- Used_Size = Delete_Fv.Data.Size - Add_Free_Space
- BlockSize = Delete_Fv.Data.Header.BlockMap[0].Length
- New_Free_Space = BlockSize - Used_Size % BlockSize
- self.Remain_New_Free_Space += Add_Free_Space - New_Free_Space
- Add_Free_Space = New_Free_Space
- # If Fv is lst level Fv, new free space node will be created to save the free space.
- else:
- Used_Size = Delete_Fv.Data.Size - Add_Free_Space
- New_Free_Space = Add_Free_Space
- New_Free_Space_Info = FfsNode(Add_Free_Space * b'\xff')
- New_Free_Space_Info.Data = Add_Free_Space * b'\xff'
- New_Ffs_Tree = BIOSTREE(New_Free_Space_Info.Name)
- New_Ffs_Tree.type = FFS_FREE_SPACE
- New_Ffs_Tree.Data = New_Free_Space_Info
- Delete_Fv.insertChild(New_Ffs_Tree)
- Delete_Fv.Data.Free_Space = Add_Free_Space
- Delete_Fv.Child.remove(Delete_Ffs)
- Delete_Fv.Data.Header.FvLength = Used_Size + New_Free_Space
- Delete_Fv.Data.ModFvExt()
- Delete_Fv.Data.ModFvSize()
- Delete_Fv.Data.ModExtHeaderData()
- ModifyFvExtData(Delete_Fv)
- Delete_Fv.Data.ModCheckSum()
- # Recompress from the Fv node to update all the related node data.
- self.CompressData(Delete_Fv)
- self.Status = True
- logger.debug('Done!')
- return self.Status
-
- def ShrinkFv(self) -> bool:
- TargetFv = self.NewFfs
- TargetFv.Data.Data = b''
- if not TargetFv.Data.Free_Space:
- self.Status = True
- else:
- BlockSize = TargetFv.Data.Header.BlockMap[0].Length
- New_Free_Space = TargetFv.Data.Free_Space%BlockSize
- Removed_Space = TargetFv.Data.Free_Space - New_Free_Space
- TargetFv.Child[-1].Data.Data = b'\xff' * New_Free_Space
- TargetFv.Data.Size -= Removed_Space
- TargetFv.Data.Header.FvLength = TargetFv.Data.Size
- if struct2stream(TargetFv.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE:
- if TargetFv.Data.Size <= 0xFFFFFF:
- TargetFv.Data.Header.FileSystemGuid = ModifyGuidFormat(
- "8c8ce578-8a3d-4f1c-9935-896185c32dd3")
-
- for item in TargetFv.Child:
- if item.type == FFS_FREE_SPACE:
- TargetFv.Data.Data += item.Data.Data + item.Data.PadData
- else:
- TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
- TargetFv.Data.ModFvExt()
- TargetFv.Data.ModFvSize()
- TargetFv.Data.ModExtHeaderData()
- ModifyFvExtData(TargetFv)
- TargetFv.Data.ModCheckSum()
- self.Status = True
- return self.Status
+## @file
+# This file is used to the implementation of Bios layout handler.
+#
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import os
+from core.BiosTree import *
+from core.GuidTools import GUIDTools
+from core.BiosTreeNode import *
+from FirmwareStorageFormat.Common import *
+from utils.FmmtLogger import FmmtLogger as logger
+
+EFI_FVB2_ERASE_POLARITY = 0x00000800
+
+def ChangeSize(TargetTree, size_delta: int=0) -> None:
+ # If Size increase delta, then should be: size_delta = -delta
+ if type(TargetTree.Data.Header) == type(EFI_FFS_FILE_HEADER2()) or type(TargetTree.Data.Header) == type(EFI_COMMON_SECTION_HEADER2()):
+ TargetTree.Data.Size -= size_delta
+ TargetTree.Data.Header.ExtendedSize -= size_delta
+ elif TargetTree.type == SECTION_TREE and TargetTree.Data.OriData:
+ OriSize = TargetTree.Data.Header.SECTION_SIZE
+ OriSize -= size_delta
+ TargetTree.Data.Header.Size[0] = OriSize % (16**2)
+ TargetTree.Data.Header.Size[1] = OriSize % (16**4) //(16**2)
+ TargetTree.Data.Header.Size[2] = OriSize // (16**4)
+ else:
+ TargetTree.Data.Size -= size_delta
+ TargetTree.Data.Header.Size[0] = TargetTree.Data.Size % (16**2)
+ TargetTree.Data.Header.Size[1] = TargetTree.Data.Size % (16**4) //(16**2)
+ TargetTree.Data.Header.Size[2] = TargetTree.Data.Size // (16**4)
+
+def ModifyFfsType(TargetFfs) -> None:
+ if type(TargetFfs.Data.Header) == type(EFI_FFS_FILE_HEADER()) and TargetFfs.Data.Size > 0xFFFFFF:
+ ExtendSize = TargetFfs.Data.Header.FFS_FILE_SIZE + 8
+ New_Header = EFI_FFS_FILE_HEADER2()
+ New_Header.Name = TargetFfs.Data.Header.Name
+ New_Header.IntegrityCheck = TargetFfs.Data.Header.IntegrityCheck
+ New_Header.Type = TargetFfs.Data.Header.Type
+ New_Header.Attributes = TargetFfs.Data.Header.Attributes | 0x01 # set the Attribute with FFS_ATTRIB_LARGE_FILE (0x01)
+ NewSize = 0
+ New_Header.Size[0] = NewSize % (16**2) # minus the delta size of Header
+ New_Header.Size[1] = NewSize % (16**4) //(16**2)
+ New_Header.Size[2] = NewSize // (16**4)
+ New_Header.State = TargetFfs.Data.Header.State
+ New_Header.ExtendedSize = ExtendSize
+ TargetFfs.Data.Header = New_Header
+ TargetFfs.Data.Size = TargetFfs.Data.Header.FFS_FILE_SIZE
+ TargetFfs.Data.HeaderLength = TargetFfs.Data.Header.HeaderLength
+ TargetFfs.Data.ModCheckSum()
+ elif type(TargetFfs.Data.Header) == type(EFI_FFS_FILE_HEADER2()) and TargetFfs.Data.Size <= 0xFFFFFF:
+ New_Header = EFI_FFS_FILE_HEADER()
+ New_Header.Name = TargetFfs.Data.Header.Name
+ New_Header.IntegrityCheck = TargetFfs.Data.Header.IntegrityCheck
+ New_Header.Type = TargetFfs.Data.Header.Type
+ New_Header.Attributes = TargetFfs.Data.Header.Attributes - 1 # remove the FFS_ATTRIB_LARGE_FILE (0x01) from Attribute
+ New_Header.Size[0] = (TargetFfs.Data.Size - 8) % (16**2) # minus the delta size of Header
+ New_Header.Size[1] = (TargetFfs.Data.Size - 8) % (16**4) //(16**2)
+ New_Header.Size[2] = (TargetFfs.Data.Size - 8) // (16**4)
+ New_Header.State = TargetFfs.Data.Header.State
+ TargetFfs.Data.Header = New_Header
+ TargetFfs.Data.Size = TargetFfs.Data.Header.FFS_FILE_SIZE
+ TargetFfs.Data.HeaderLength = TargetFfs.Data.Header.HeaderLength
+ TargetFfs.Data.ModCheckSum()
+ if struct2stream(TargetFfs.Parent.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE:
+ NeedChange = True
+ for item in TargetFfs.Parent.Child:
+ if type(item.Data.Header) == type(EFI_FFS_FILE_HEADER2()):
+ NeedChange = False
+ if NeedChange:
+ TargetFfs.Parent.Data.Header.FileSystemGuid = ModifyGuidFormat("8c8ce578-8a3d-4f1c-9935-896185c32dd3")
+
+ if type(TargetFfs.Data.Header) == type(EFI_FFS_FILE_HEADER2()):
+ TarParent = TargetFfs.Parent
+ while TarParent:
+ if TarParent.type == FV_TREE and struct2stream(TarParent.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE:
+ TarParent.Data.Header.FileSystemGuid = ModifyGuidFormat("5473C07A-3DCB-4dca-BD6F-1E9689E7349A")
+ TarParent = TarParent.Parent
+
+def PadSectionModify(PadSection, Offset) -> None:
+ # Offset > 0, Size decrease; Offset < 0, Size increase;
+ ChangeSize(PadSection, Offset)
+ PadSection.Data.Data = (PadSection.Data.Size - PadSection.Data.HeaderLength) * b'\xff'
+
+def ModifySectionType(TargetSection) -> None:
+ # If Section Size is increased larger than 0xFFFFFF, need modify Section Header from EFI_COMMON_SECTION_HEADER to EFI_COMMON_SECTION_HEADER2.
+ if type(TargetSection.Data.Header) == type(EFI_COMMON_SECTION_HEADER()) and TargetSection.Data.Size >= 0xFFFFFF:
+ New_Header = EFI_COMMON_SECTION_HEADER2()
+ New_Header.Type = TargetSection.Data.Header.Type
+ NewSize = 0xFFFFFF
+ New_Header.Size[0] = NewSize % (16**2) # minus the delta size of Header
+ New_Header.Size[1] = NewSize % (16**4) //(16**2)
+ New_Header.Size[2] = NewSize // (16**4)
+ New_Header.ExtendedSize = TargetSection.Data.Size + 4
+ TargetSection.Data.Header = New_Header
+ TargetSection.Data.Size = TargetSection.Data.Header.SECTION_SIZE
+ # Align the Header's added 4 bit to 8-alignment to promise the following Ffs's align correctly.
+ if TargetSection.LastRel.Data.IsPadSection:
+ PadSectionModify(TargetSection.LastRel, -4)
+ else:
+ SecParent = TargetSection.Parent
+ Target_index = SecParent.Child.index(TargetSection)
+ NewPadSection = SectionNode(b'\x00\x00\x00\x19')
+ SecParent.insertChild(NewPadSection, Target_index)
+ # If Section Size is decreased smaller than 0xFFFFFF, need modify Section Header from EFI_COMMON_SECTION_HEADER2 to EFI_COMMON_SECTION_HEADER.
+ elif type(TargetSection.Data.Header) == type(EFI_COMMON_SECTION_HEADER2()) and TargetSection.Data.Size < 0xFFFFFF:
+ New_Header = EFI_COMMON_SECTION_HEADER()
+ New_Header.Type = TargetSection.Data.Header.Type
+ New_Header.Size[0] = (TargetSection.Data.Size - 4) % (16**2) # minus the delta size of Header
+ New_Header.Size[1] = (TargetSection.Data.Size - 4) % (16**4) //(16**2)
+ New_Header.Size[2] = (TargetSection.Data.Size - 4) // (16**4)
+ TargetSection.Data.Header = New_Header
+ TargetSection.Data.Size = TargetSection.Data.Header.SECTION_SIZE
+ # Align the Header's added 4 bit to 8-alignment to promise the following Ffs's align correctly.
+ if TargetSection.LastRel.Data.IsPadSection:
+ PadSectionModify(TargetSection.LastRel, -4)
+ else:
+ SecParent = TargetSection.Parent
+ Target_index = SecParent.Child.index(TargetSection)
+ NewPadSection = SectionNode(b'\x00\x00\x00\x19')
+ SecParent.insertChild(NewPadSection, Target_index)
+
+def ModifyFvExtData(TreeNode) -> None:
+ FvExtData = b''
+ if TreeNode.Data.Header.ExtHeaderOffset:
+ FvExtHeader = struct2stream(TreeNode.Data.ExtHeader)
+ FvExtData += FvExtHeader
+ if TreeNode.Data.Header.ExtHeaderOffset and TreeNode.Data.ExtEntryExist:
+ FvExtEntry = struct2stream(TreeNode.Data.ExtEntry)
+ FvExtData += FvExtEntry
+ if FvExtData:
+ InfoNode = TreeNode.Child[0]
+ InfoNode.Data.Data = FvExtData + InfoNode.Data.Data[TreeNode.Data.ExtHeader.ExtHeaderSize:]
+ InfoNode.Data.ModCheckSum()
+
+def ModifyFvSystemGuid(TargetFv) -> None:
+ if struct2stream(TargetFv.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM2_GUID_BYTE:
+ TargetFv.Data.Header.FileSystemGuid = ModifyGuidFormat("5473C07A-3DCB-4dca-BD6F-1E9689E7349A")
+ TargetFv.Data.ModCheckSum()
+ TargetFv.Data.Data = b''
+ for item in TargetFv.Child:
+ if item.type == FFS_FREE_SPACE:
+ TargetFv.Data.Data += item.Data.Data + item.Data.PadData
+ else:
+ TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
+
+class FvHandler:
+ def __init__(self, NewFfs, TargetFfs=None) -> None:
+ self.NewFfs = NewFfs
+ self.TargetFfs = TargetFfs
+ self.Status = False
+ self.Remain_New_Free_Space = 0
+
+ ## Use for Compress the Section Data
+ def CompressData(self, TargetTree) -> None:
+ TreePath = TargetTree.GetTreePath()
+ pos = len(TreePath)
+ while pos:
+ if not self.Status:
+ if TreePath[pos-1].type == SECTION_TREE and TreePath[pos-1].Data.Type == 0x02:
+ self.CompressSectionData(TreePath[pos-1], None, TreePath[pos-1].Data.ExtHeader.SectionDefinitionGuid)
+ else:
+ if pos == len(TreePath):
+ self.CompressSectionData(TreePath[pos-1], pos)
+ else:
+ self.CompressSectionData(TreePath[pos-1], None)
+ pos -= 1
+
+ def CompressSectionData(self, TargetTree, pos: int, GuidTool=None) -> None:
+ NewData = b''
+ temp_save_child = TargetTree.Child
+ if TargetTree.Data:
+ # Update current node data as adding all the header and data of its child node.
+ for item in temp_save_child:
+ if item.type == SECTION_TREE and not item.Data.OriData and item.Data.ExtHeader:
+ NewData += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.Data + item.Data.PadData
+ elif item.type == SECTION_TREE and item.Data.OriData and not item.Data.ExtHeader:
+ NewData += struct2stream(item.Data.Header) + item.Data.OriData + item.Data.PadData
+ elif item.type == SECTION_TREE and item.Data.OriData and item.Data.ExtHeader:
+ NewData += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.OriData + item.Data.PadData
+ elif item.type == FFS_FREE_SPACE:
+ NewData += item.Data.Data + item.Data.PadData
+ else:
+ NewData += struct2stream(item.Data.Header) + item.Data.Data + item.Data.PadData
+ # If node is FFS_TREE, update Pad data and Header info.
+ # Remain_New_Free_Space is used for move more free space into lst level Fv.
+ if TargetTree.type == FFS_TREE:
+ New_Pad_Size = GetPadSize(len(NewData), 8)
+ Size_delta = len(NewData) - len(TargetTree.Data.Data)
+ ChangeSize(TargetTree, -Size_delta)
+ Delta_Pad_Size = len(TargetTree.Data.PadData) - New_Pad_Size
+ self.Remain_New_Free_Space += Delta_Pad_Size
+ TargetTree.Data.PadData = b'\xff' * New_Pad_Size
+ TargetTree.Data.ModCheckSum()
+ # If node is FV_TREE, update Pad data and Header info.
+ # Consume Remain_New_Free_Space is used for move more free space into lst level Fv.
+ elif TargetTree.type == FV_TREE or TargetTree.type == SEC_FV_TREE and not pos:
+ if self.Remain_New_Free_Space:
+ if TargetTree.Data.Free_Space:
+ TargetTree.Data.Free_Space += self.Remain_New_Free_Space
+ NewData += self.Remain_New_Free_Space * b'\xff'
+ TargetTree.Child[-1].Data.Data += self.Remain_New_Free_Space * b'\xff'
+ else:
+ TargetTree.Data.Data += self.Remain_New_Free_Space * b'\xff'
+ New_Free_Space = BIOSTREE('FREE_SPACE')
+ New_Free_Space.type = FFS_FREE_SPACE
+ New_Free_Space.Data = FreeSpaceNode(b'\xff' * self.Remain_New_Free_Space)
+ TargetTree.insertChild(New_Free_Space)
+ self.Remain_New_Free_Space = 0
+ if TargetTree.type == SEC_FV_TREE:
+ Size_delta = len(NewData) + self.Remain_New_Free_Space - len(TargetTree.Data.Data)
+ TargetTree.Data.Header.FvLength += Size_delta
+ TargetTree.Data.ModFvExt()
+ TargetTree.Data.ModFvSize()
+ TargetTree.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetTree)
+ TargetTree.Data.ModCheckSum()
+ # If node is SECTION_TREE and not guided section, update Pad data and Header info.
+ # Remain_New_Free_Space is used for move more free space into lst level Fv.
+ elif TargetTree.type == SECTION_TREE and TargetTree.Data.Type != 0x02:
+ New_Pad_Size = GetPadSize(len(NewData), 4)
+ Size_delta = len(NewData) - len(TargetTree.Data.Data)
+ ChangeSize(TargetTree, -Size_delta)
+ if TargetTree.NextRel:
+ Delta_Pad_Size = len(TargetTree.Data.PadData) - New_Pad_Size
+ self.Remain_New_Free_Space += Delta_Pad_Size
+ TargetTree.Data.PadData = b'\x00' * New_Pad_Size
+ TargetTree.Data.Data = NewData
+ if GuidTool:
+ guidtool = GUIDTools().__getitem__(struct2stream(GuidTool))
+ if not guidtool.ifexist:
+ logger.error("GuidTool {} is not found when decompressing {} file.\n".format(guidtool.command, TargetTree.Parent.Data.Name))
+ raise Exception("Process Failed: GuidTool not found!")
+ CompressedData = guidtool.pack(TargetTree.Data.Data)
+ if len(CompressedData) < len(TargetTree.Data.OriData):
+ New_Pad_Size = GetPadSize(len(CompressedData), SECTION_COMMON_ALIGNMENT)
+ Size_delta = len(CompressedData) - len(TargetTree.Data.OriData)
+ ChangeSize(TargetTree, -Size_delta)
+ if TargetTree.NextRel:
+ TargetTree.Data.PadData = b'\x00' * New_Pad_Size
+ self.Remain_New_Free_Space = len(TargetTree.Data.OriData) + len(TargetTree.Data.PadData) - len(CompressedData) - New_Pad_Size
+ else:
+ TargetTree.Data.PadData = b''
+ self.Remain_New_Free_Space = len(TargetTree.Data.OriData) - len(CompressedData)
+ TargetTree.Data.OriData = CompressedData
+ elif len(CompressedData) == len(TargetTree.Data.OriData):
+ TargetTree.Data.OriData = CompressedData
+ elif len(CompressedData) > len(TargetTree.Data.OriData):
+ New_Pad_Size = GetPadSize(len(CompressedData), SECTION_COMMON_ALIGNMENT)
+ self.Remain_New_Free_Space = len(CompressedData) + New_Pad_Size - len(TargetTree.Data.OriData) - len(TargetTree.Data.PadData)
+ self.ModifyTest(TargetTree, self.Remain_New_Free_Space)
+ self.Status = True
+
+ def ModifyTest(self, ParTree, Needed_Space: int) -> None:
+ # If have needed space, will find if there have free space in parent tree, meanwhile update the node data.
+ if Needed_Space > 0:
+ # If current node is a Fv node
+ if ParTree.type == FV_TREE or ParTree.type == SEC_FV_TREE:
+ ParTree.Data.Data = b''
+ # First check if Fv free space is enough for needed space.
+ # If so, use the current Fv free space;
+ # Else, use all the Free space, and recalculate needed space, continue finding in its parent node.
+ Needed_Space = Needed_Space - ParTree.Data.Free_Space
+ if Needed_Space < 0:
+ ParTree.Child[-1].Data.Data = b'\xff' * (-Needed_Space)
+ ParTree.Data.Free_Space = (-Needed_Space)
+ self.Status = True
+ else:
+ if ParTree.type == FV_TREE:
+ self.Status = False
+ else:
+ BlockSize = ParTree.Data.Header.BlockMap[0].Length
+ New_Add_Len = BlockSize - Needed_Space%BlockSize
+ if New_Add_Len % BlockSize:
+ ParTree.Child[-1].Data.Data = b'\xff' * New_Add_Len
+ ParTree.Data.Free_Space = New_Add_Len
+ Needed_Space += New_Add_Len
+ else:
+ ParTree.Child.remove(ParTree.Child[-1])
+ ParTree.Data.Free_Space = 0
+ ParTree.Data.Size += Needed_Space
+ ParTree.Data.Header.FvLength = ParTree.Data.Size
+ ModifyFvSystemGuid(ParTree)
+ for item in ParTree.Child:
+ if item.type == FFS_FREE_SPACE:
+ ParTree.Data.Data += item.Data.Data + item.Data.PadData
+ else:
+ ParTree.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
+ ParTree.Data.ModFvExt()
+ ParTree.Data.ModFvSize()
+ ParTree.Data.ModExtHeaderData()
+ ModifyFvExtData(ParTree)
+ ParTree.Data.ModCheckSum()
+ # If current node is a Ffs node
+ elif ParTree.type == FFS_TREE:
+ ParTree.Data.Data = b''
+ OriHeaderLen = ParTree.Data.HeaderLength
+ # Update its data as adding all the header and data of its child node.
+ for item in ParTree.Child:
+ if item.Data.OriData:
+ if item.Data.ExtHeader:
+ ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.OriData + item.Data.PadData
+ else:
+ ParTree.Data.Data += struct2stream(item.Data.Header)+ item.Data.OriData + item.Data.PadData
+ else:
+ if item.Data.ExtHeader:
+ ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.Data + item.Data.PadData
+ else:
+ ParTree.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
+ ChangeSize(ParTree, -Needed_Space)
+ ModifyFfsType(ParTree)
+ # Recalculate pad data, update needed space with Delta_Pad_Size.
+ Needed_Space += ParTree.Data.HeaderLength - OriHeaderLen
+ New_Pad_Size = GetPadSize(ParTree.Data.Size, FFS_COMMON_ALIGNMENT)
+ Delta_Pad_Size = New_Pad_Size - len(ParTree.Data.PadData)
+ Needed_Space += Delta_Pad_Size
+ ParTree.Data.PadData = b'\xff' * GetPadSize(ParTree.Data.Size, FFS_COMMON_ALIGNMENT)
+ ParTree.Data.ModCheckSum()
+ # If current node is a Section node
+ elif ParTree.type == SECTION_TREE:
+ OriData = ParTree.Data.Data
+ OriHeaderLen = ParTree.Data.HeaderLength
+ ParTree.Data.Data = b''
+ # Update its data as adding all the header and data of its child node.
+ for item in ParTree.Child:
+ if item.type == SECTION_TREE and item.Data.ExtHeader and item.Data.Type != 0x02:
+ ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.Data + item.Data.PadData
+ elif item.type == SECTION_TREE and item.Data.ExtHeader and item.Data.Type == 0x02:
+ ParTree.Data.Data += struct2stream(item.Data.Header) + struct2stream(item.Data.ExtHeader) + item.Data.OriData + item.Data.PadData
+ else:
+ ParTree.Data.Data += struct2stream(item.Data.Header) + item.Data.Data + item.Data.PadData
+ # If the current section is guided section
+ if ParTree.Data.Type == 0x02:
+ guidtool = GUIDTools().__getitem__(struct2stream(ParTree.Data.ExtHeader.SectionDefinitionGuid))
+ if not guidtool.ifexist:
+ logger.error("GuidTool {} is not found when decompressing {} file.\n".format(guidtool.command, ParTree.Parent.Data.Name))
+ raise Exception("Process Failed: GuidTool not found!")
+ # Recompress current data, and recalculate the needed space
+ CompressedData = guidtool.pack(ParTree.Data.Data)
+ Needed_Space = len(CompressedData) - len(ParTree.Data.OriData)
+ ParTree.Data.OriData = CompressedData
+ New_Size = ParTree.Data.HeaderLength + len(CompressedData)
+ ParTree.Data.Header.Size[0] = New_Size % (16**2)
+ ParTree.Data.Header.Size[1] = New_Size % (16**4) //(16**2)
+ ParTree.Data.Header.Size[2] = New_Size // (16**4)
+ ParTree.Data.Size = ParTree.Data.Header.SECTION_SIZE
+ ModifySectionType(ParTree)
+ Needed_Space += ParTree.Data.HeaderLength - OriHeaderLen
+ # Update needed space with Delta_Pad_Size
+ if ParTree.NextRel:
+ New_Pad_Size = GetPadSize(ParTree.Data.Size, SECTION_COMMON_ALIGNMENT)
+ Delta_Pad_Size = New_Pad_Size - len(ParTree.Data.PadData)
+ ParTree.Data.PadData = b'\x00' * New_Pad_Size
+ Needed_Space += Delta_Pad_Size
+ else:
+ ParTree.Data.PadData = b''
+ if Needed_Space < 0:
+ self.Remain_New_Free_Space = len(ParTree.Data.OriData) - len(CompressedData)
+ # If current section is not guided section
+ elif Needed_Space:
+ ChangeSize(ParTree, -Needed_Space)
+ ModifySectionType(ParTree)
+ # Update needed space with Delta_Pad_Size
+ Needed_Space += ParTree.Data.HeaderLength - OriHeaderLen
+ New_Pad_Size = GetPadSize(ParTree.Data.Size, SECTION_COMMON_ALIGNMENT)
+ Delta_Pad_Size = New_Pad_Size - len(ParTree.Data.PadData)
+ Needed_Space += Delta_Pad_Size
+ ParTree.Data.PadData = b'\x00' * New_Pad_Size
+ NewParTree = ParTree.Parent
+ ROOT_TYPE = [ROOT_FV_TREE, ROOT_FFS_TREE, ROOT_SECTION_TREE, ROOT_TREE]
+ if NewParTree and NewParTree.type not in ROOT_TYPE:
+ self.ModifyTest(NewParTree, Needed_Space)
+ # If current node have enough space, will recompress all the related node data, return true.
+ else:
+ self.CompressData(ParTree)
+ self.Status = True
+
+ def ReplaceFfs(self) -> bool:
+ logger.debug('Start Replacing Process......')
+ TargetFv = self.TargetFfs.Parent
+ # If the Fv Header Attributes is EFI_FVB2_ERASE_POLARITY, Child Ffs Header State need be reversed.
+ if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
+ self.NewFfs.Data.Header.State = c_uint8(
+ ~self.NewFfs.Data.Header.State)
+ # NewFfs parsing will not calculate the PadSize, thus recalculate.
+ self.NewFfs.Data.PadData = b'\xff' * GetPadSize(self.NewFfs.Data.Size, FFS_COMMON_ALIGNMENT)
+ if self.NewFfs.Data.Size >= self.TargetFfs.Data.Size:
+ Needed_Space = self.NewFfs.Data.Size + len(self.NewFfs.Data.PadData) - self.TargetFfs.Data.Size - len(self.TargetFfs.Data.PadData)
+ # If TargetFv have enough free space, just move part of the free space to NewFfs.
+ if Needed_Space == 0:
+ Target_index = TargetFv.Child.index(self.TargetFfs)
+ TargetFv.Child.remove(self.TargetFfs)
+ TargetFv.insertChild(self.NewFfs, Target_index)
+ # Modify TargetFv Header and ExtHeader info.
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModFvSize()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ # Recompress from the Fv node to update all the related node data.
+ self.CompressData(TargetFv)
+ # return the Status
+ self.Status = True
+ elif TargetFv.Data.Free_Space >= Needed_Space:
+ # Modify TargetFv Child info and BiosTree.
+ TargetFv.Child[-1].Data.Data = b'\xff' * (TargetFv.Data.Free_Space - Needed_Space)
+ TargetFv.Data.Free_Space -= Needed_Space
+ Target_index = TargetFv.Child.index(self.TargetFfs)
+ TargetFv.Child.remove(self.TargetFfs)
+ TargetFv.insertChild(self.NewFfs, Target_index)
+ # Modify TargetFv Header and ExtHeader info.
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModFvSize()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ # Recompress from the Fv node to update all the related node data.
+ self.CompressData(TargetFv)
+ # return the Status
+ self.Status = True
+ # If TargetFv do not have enough free space, need move part of the free space of TargetFv's parent Fv to TargetFv/NewFfs.
+ else:
+ if TargetFv.type == FV_TREE:
+ self.Status = False
+ else:
+ # Recalculate TargetFv needed space to keep it match the BlockSize setting.
+ Needed_Space -= TargetFv.Data.Free_Space
+ BlockSize = TargetFv.Data.Header.BlockMap[0].Length
+ New_Add_Len = BlockSize - Needed_Space%BlockSize
+ Target_index = TargetFv.Child.index(self.TargetFfs)
+ if New_Add_Len % BlockSize:
+ TargetFv.Child[-1].Data.Data = b'\xff' * New_Add_Len
+ TargetFv.Data.Free_Space = New_Add_Len
+ Needed_Space += New_Add_Len
+ TargetFv.insertChild(self.NewFfs, Target_index)
+ TargetFv.Child.remove(self.TargetFfs)
+ else:
+ TargetFv.Child.remove(self.TargetFfs)
+ TargetFv.Data.Free_Space = 0
+ TargetFv.insertChild(self.NewFfs)
+ # Encapsulate the Fv Data for update.
+ TargetFv.Data.Data = b''
+ for item in TargetFv.Child:
+ if item.type == FFS_FREE_SPACE:
+ TargetFv.Data.Data += item.Data.Data + item.Data.PadData
+ else:
+ TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
+ TargetFv.Data.Size += Needed_Space
+ # Modify TargetFv Data Header and ExtHeader info.
+ TargetFv.Data.Header.FvLength = TargetFv.Data.Size
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModFvSize()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ # Start free space calculating and moving process.
+ self.ModifyTest(TargetFv.Parent, Needed_Space)
+ else:
+ New_Free_Space = self.TargetFfs.Data.Size + len(self.TargetFfs.Data.PadData) - self.NewFfs.Data.Size - len(self.NewFfs.Data.PadData)
+ # If TargetFv already have free space, move the new free space into it.
+ if TargetFv.Data.Free_Space:
+ TargetFv.Child[-1].Data.Data += b'\xff' * New_Free_Space
+ TargetFv.Data.Free_Space += New_Free_Space
+ Target_index = TargetFv.Child.index(self.TargetFfs)
+ TargetFv.Child.remove(self.TargetFfs)
+ TargetFv.insertChild(self.NewFfs, Target_index)
+ # If TargetFv do not have free space, create free space for Fv.
+ else:
+ New_Free_Space_Tree = BIOSTREE('FREE_SPACE')
+ New_Free_Space_Tree.type = FFS_FREE_SPACE
+ New_Free_Space_Tree.Data = FfsNode(b'\xff' * New_Free_Space)
+ TargetFv.Data.Free_Space = New_Free_Space
+ TargetFv.insertChild(New_Free_Space)
+ Target_index = TargetFv.Child.index(self.TargetFfs)
+ TargetFv.Child.remove(self.TargetFfs)
+ TargetFv.insertChild(self.NewFfs, Target_index)
+ # Modify TargetFv Header and ExtHeader info.
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModFvSize()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ # Recompress from the Fv node to update all the related node data.
+ self.CompressData(TargetFv)
+ self.Status = True
+ logger.debug('Done!')
+ return self.Status
+
+ def AddFfs(self) -> bool:
+ logger.debug('Start Adding Process......')
+ # NewFfs parsing will not calculate the PadSize, thus recalculate.
+ self.NewFfs.Data.PadData = b'\xff' * GetPadSize(self.NewFfs.Data.Size, FFS_COMMON_ALIGNMENT)
+ if self.TargetFfs.type == FFS_FREE_SPACE:
+ TargetLen = self.NewFfs.Data.Size + len(self.NewFfs.Data.PadData) - self.TargetFfs.Data.Size - len(self.TargetFfs.Data.PadData)
+ TargetFv = self.TargetFfs.Parent
+ # If the Fv Header Attributes is EFI_FVB2_ERASE_POLARITY, Child Ffs Header State need be reversed.
+ if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
+ self.NewFfs.Data.Header.State = c_uint8(
+ ~self.NewFfs.Data.Header.State)
+ # If TargetFv have enough free space, just move part of the free space to NewFfs, split free space to NewFfs and new free space.
+ if TargetLen < 0:
+ self.TargetFfs.Data.Data = b'\xff' * (-TargetLen)
+ TargetFv.Data.Free_Space = (-TargetLen)
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ TargetFv.insertChild(self.NewFfs, -1)
+ ModifyFfsType(self.NewFfs)
+ # Recompress from the Fv node to update all the related node data.
+ self.CompressData(TargetFv)
+ self.Status = True
+ elif TargetLen == 0:
+ TargetFv.Child.remove(self.TargetFfs)
+ TargetFv.insertChild(self.NewFfs)
+ ModifyFfsType(self.NewFfs)
+ # Recompress from the Fv node to update all the related node data.
+ self.CompressData(TargetFv)
+ self.Status = True
+ # If TargetFv do not have enough free space, need move part of the free space of TargetFv's parent Fv to TargetFv/NewFfs.
+ else:
+ if TargetFv.type == FV_TREE:
+ self.Status = False
+ elif TargetFv.type == SEC_FV_TREE:
+ # Recalculate TargetFv needed space to keep it match the BlockSize setting.
+ BlockSize = TargetFv.Data.Header.BlockMap[0].Length
+ New_Add_Len = BlockSize - TargetLen%BlockSize
+ if New_Add_Len % BlockSize:
+ self.TargetFfs.Data.Data = b'\xff' * New_Add_Len
+ self.TargetFfs.Data.Size = New_Add_Len
+ TargetLen += New_Add_Len
+ TargetFv.insertChild(self.NewFfs, -1)
+ TargetFv.Data.Free_Space = New_Add_Len
+ else:
+ TargetFv.Child.remove(self.TargetFfs)
+ TargetFv.insertChild(self.NewFfs)
+ TargetFv.Data.Free_Space = 0
+ ModifyFfsType(self.NewFfs)
+ ModifyFvSystemGuid(TargetFv)
+ TargetFv.Data.Data = b''
+ for item in TargetFv.Child:
+ if item.type == FFS_FREE_SPACE:
+ TargetFv.Data.Data += item.Data.Data + item.Data.PadData
+ else:
+ TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
+ # Encapsulate the Fv Data for update.
+ TargetFv.Data.Size += TargetLen
+ TargetFv.Data.Header.FvLength = TargetFv.Data.Size
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModFvSize()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ # Start free space calculating and moving process.
+ self.ModifyTest(TargetFv.Parent, TargetLen)
+ else:
+ # If TargetFv do not have free space, need directly move part of the free space of TargetFv's parent Fv to TargetFv/NewFfs.
+ TargetLen = self.NewFfs.Data.Size + len(self.NewFfs.Data.PadData)
+ TargetFv = self.TargetFfs.Parent
+ if TargetFv.Data.Header.Attributes & EFI_FVB2_ERASE_POLARITY:
+ self.NewFfs.Data.Header.State = c_uint8(
+ ~self.NewFfs.Data.Header.State)
+ if TargetFv.type == FV_TREE:
+ self.Status = False
+ elif TargetFv.type == SEC_FV_TREE:
+ BlockSize = TargetFv.Data.Header.BlockMap[0].Length
+ New_Add_Len = BlockSize - TargetLen%BlockSize
+ if New_Add_Len % BlockSize:
+ New_Free_Space = BIOSTREE('FREE_SPACE')
+ New_Free_Space.type = FFS_FREE_SPACE
+ New_Free_Space.Data = FreeSpaceNode(b'\xff' * New_Add_Len)
+ TargetLen += New_Add_Len
+ TargetFv.Data.Free_Space = New_Add_Len
+ TargetFv.insertChild(self.NewFfs)
+ TargetFv.insertChild(New_Free_Space)
+ else:
+ TargetFv.insertChild(self.NewFfs)
+ ModifyFfsType(self.NewFfs)
+ ModifyFvSystemGuid(TargetFv)
+ TargetFv.Data.Data = b''
+ for item in TargetFv.Child:
+ if item.type == FFS_FREE_SPACE:
+ TargetFv.Data.Data += item.Data.Data + item.Data.PadData
+ else:
+ TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
+ TargetFv.Data.Size += TargetLen
+ TargetFv.Data.Header.FvLength = TargetFv.Data.Size
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModFvSize()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ self.ModifyTest(TargetFv.Parent, TargetLen)
+ logger.debug('Done!')
+ return self.Status
+
+ def DeleteFfs(self) -> bool:
+ logger.debug('Start Deleting Process......')
+ Delete_Ffs = self.TargetFfs
+ Delete_Fv = Delete_Ffs.Parent
+ # Calculate free space
+ Add_Free_Space = Delete_Ffs.Data.Size + len(Delete_Ffs.Data.PadData)
+ # If Ffs parent Fv have free space, follow the rules to merge the new free space.
+ if Delete_Fv.Data.Free_Space:
+ # If Fv is a Section fv, free space need to be recalculated to keep align with BlockSize.
+ # Other free space saved in self.Remain_New_Free_Space, will be moved to the 1st level Fv.
+ if Delete_Fv.type == SEC_FV_TREE:
+ Used_Size = Delete_Fv.Data.Size - Delete_Fv.Data.Free_Space - Add_Free_Space
+ BlockSize = Delete_Fv.Data.Header.BlockMap[0].Length
+ New_Free_Space = BlockSize - Used_Size % BlockSize
+ self.Remain_New_Free_Space += Delete_Fv.Data.Free_Space + Add_Free_Space - New_Free_Space
+ Delete_Fv.Child[-1].Data.Data = New_Free_Space * b'\xff'
+ Delete_Fv.Data.Free_Space = New_Free_Space
+ # If Fv is lst level Fv, new free space will be merged with origin free space.
+ else:
+ Used_Size = Delete_Fv.Data.Size - Delete_Fv.Data.Free_Space - Add_Free_Space
+ Delete_Fv.Child[-1].Data.Data += Add_Free_Space * b'\xff'
+ Delete_Fv.Data.Free_Space += Add_Free_Space
+ New_Free_Space = Delete_Fv.Data.Free_Space
+ # If Ffs parent Fv not have free space, will create new free space node to save the free space.
+ else:
+ # If Fv is a Section fv, new free space need to be recalculated to keep align with BlockSize.
+ # Then create a Free spcae node to save the 0xff data, and insert into the Fv.
+ # If have more space left, move to 1st level fv.
+ if Delete_Fv.type == SEC_FV_TREE:
+ Used_Size = Delete_Fv.Data.Size - Add_Free_Space
+ BlockSize = Delete_Fv.Data.Header.BlockMap[0].Length
+ New_Free_Space = BlockSize - Used_Size % BlockSize
+ self.Remain_New_Free_Space += Add_Free_Space - New_Free_Space
+ Add_Free_Space = New_Free_Space
+ # If Fv is lst level Fv, new free space node will be created to save the free space.
+ else:
+ Used_Size = Delete_Fv.Data.Size - Add_Free_Space
+ New_Free_Space = Add_Free_Space
+ New_Free_Space_Info = FfsNode(Add_Free_Space * b'\xff')
+ New_Free_Space_Info.Data = Add_Free_Space * b'\xff'
+ New_Ffs_Tree = BIOSTREE(New_Free_Space_Info.Name)
+ New_Ffs_Tree.type = FFS_FREE_SPACE
+ New_Ffs_Tree.Data = New_Free_Space_Info
+ Delete_Fv.insertChild(New_Ffs_Tree)
+ Delete_Fv.Data.Free_Space = Add_Free_Space
+ Delete_Fv.Child.remove(Delete_Ffs)
+ Delete_Fv.Data.Header.FvLength = Used_Size + New_Free_Space
+ Delete_Fv.Data.ModFvExt()
+ Delete_Fv.Data.ModFvSize()
+ Delete_Fv.Data.ModExtHeaderData()
+ ModifyFvExtData(Delete_Fv)
+ Delete_Fv.Data.ModCheckSum()
+ # Recompress from the Fv node to update all the related node data.
+ self.CompressData(Delete_Fv)
+ self.Status = True
+ logger.debug('Done!')
+ return self.Status
+
+ def ShrinkFv(self) -> bool:
+ TargetFv = self.NewFfs
+ TargetFv.Data.Data = b''
+ if not TargetFv.Data.Free_Space:
+ self.Status = True
+ else:
+ BlockSize = TargetFv.Data.Header.BlockMap[0].Length
+ New_Free_Space = TargetFv.Data.Free_Space%BlockSize
+ Removed_Space = TargetFv.Data.Free_Space - New_Free_Space
+ TargetFv.Child[-1].Data.Data = b'\xff' * New_Free_Space
+ TargetFv.Data.Size -= Removed_Space
+ TargetFv.Data.Header.FvLength = TargetFv.Data.Size
+ if struct2stream(TargetFv.Data.Header.FileSystemGuid) == EFI_FIRMWARE_FILE_SYSTEM3_GUID_BYTE:
+ if TargetFv.Data.Size <= 0xFFFFFF:
+ TargetFv.Data.Header.FileSystemGuid = ModifyGuidFormat(
+ "8c8ce578-8a3d-4f1c-9935-896185c32dd3")
+
+ for item in TargetFv.Child:
+ if item.type == FFS_FREE_SPACE:
+ TargetFv.Data.Data += item.Data.Data + item.Data.PadData
+ else:
+ TargetFv.Data.Data += struct2stream(item.Data.Header)+ item.Data.Data + item.Data.PadData
+ TargetFv.Data.ModFvExt()
+ TargetFv.Data.ModFvSize()
+ TargetFv.Data.ModExtHeaderData()
+ ModifyFvExtData(TargetFv)
+ TargetFv.Data.ModCheckSum()
+ self.Status = True
+ return self.Status
diff --git a/BaseTools/Source/Python/FMMT/core/GuidTools.py b/BaseTools/Source/Python/FMMT/core/GuidTools.py
index f6bdeffa50..65c997bea5 100644
--- a/BaseTools/Source/Python/FMMT/core/GuidTools.py
+++ b/BaseTools/Source/Python/FMMT/core/GuidTools.py
@@ -1,179 +1,179 @@
-## @file
-# This file is used to define the FMMT dependent external tool management class.
-#
-# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-##
-import glob
-import logging
-import os
-import shutil
-import sys
-import tempfile
-import uuid
-from FirmwareStorageFormat.Common import *
-from utils.FmmtLogger import FmmtLogger as logger
-import subprocess
-
-def ExecuteCommand(cmd: list) -> None:
- subprocess.run(cmd,stdout=subprocess.DEVNULL)
-
-class GUIDTool:
- def __init__(self, guid: str, short_name: str, command: str) -> None:
- self.guid: str = guid
- self.short_name: str = short_name
- self.command: str = command
- self.ifexist: bool = False
-
- def pack(self, buffer: bytes) -> bytes:
- """
- compress file.
- """
- tool = self.command
- if tool:
- tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))
- ToolInputFile = os.path.join(tmp, "pack_uncompress_sec_file")
- ToolOuputFile = os.path.join(tmp, "pack_sec_file")
- try:
- file = open(ToolInputFile, "wb")
- file.write(buffer)
- file.close()
- command = [tool, '-e', '-o', ToolOuputFile,
- ToolInputFile]
- ExecuteCommand(command)
- buf = open(ToolOuputFile, "rb")
- res_buffer = buf.read()
- except Exception as msg:
- logger.error(msg)
- return ""
- else:
- buf.close()
- if os.path.exists(tmp):
- shutil.rmtree(tmp)
- return res_buffer
- else:
- logger.error(
- "Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")
- logger.info("Its GUID is: %s" % self.guid)
- return ""
-
-
- def unpack(self, buffer: bytes) -> bytes:
- """
- buffer: remove common header
- uncompress file
- """
- tool = self.command
- if tool:
- tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))
- ToolInputFile = os.path.join(tmp, "unpack_sec_file")
- ToolOuputFile = os.path.join(tmp, "unpack_uncompress_sec_file")
- try:
- file = open(ToolInputFile, "wb")
- file.write(buffer)
- file.close()
- command = [tool, '-d', '-o', ToolOuputFile, ToolInputFile]
- ExecuteCommand(command)
- buf = open(ToolOuputFile, "rb")
- res_buffer = buf.read()
- except Exception as msg:
- logger.error(msg)
- return ""
- else:
- buf.close()
- if os.path.exists(tmp):
- shutil.rmtree(tmp)
- return res_buffer
- else:
- logger.error("Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")
- logger.info("Its GUID is: %s" % self.guid)
- return ""
-
-class GUIDTools:
- '''
- GUIDTools is responsible for reading FMMTConfig.ini, verify the tools and provide interfaces to access those tools.
- '''
- default_tools = {
- struct2stream(ModifyGuidFormat("a31280ad-481e-41b6-95e8-127f4c984779")): GUIDTool("a31280ad-481e-41b6-95e8-127f4c984779", "TIANO", "TianoCompress"),
- struct2stream(ModifyGuidFormat("ee4e5898-3914-4259-9d6e-dc7bd79403cf")): GUIDTool("ee4e5898-3914-4259-9d6e-dc7bd79403cf", "LZMA", "LzmaCompress"),
- struct2stream(ModifyGuidFormat("fc1bcdb0-7d31-49aa-936a-a4600d9dd083")): GUIDTool("fc1bcdb0-7d31-49aa-936a-a4600d9dd083", "CRC32", "GenCrc32"),
- struct2stream(ModifyGuidFormat("d42ae6bd-1352-4bfb-909a-ca72a6eae889")): GUIDTool("d42ae6bd-1352-4bfb-909a-ca72a6eae889", "LZMAF86", "LzmaF86Compress"),
- struct2stream(ModifyGuidFormat("3d532050-5cda-4fd0-879e-0f7f630d5afb")): GUIDTool("3d532050-5cda-4fd0-879e-0f7f630d5afb", "BROTLI", "BrotliCompress"),
- }
-
- def __init__(self, tooldef_file: str=None) -> None:
- self.dir = os.path.join(os.path.dirname(__file__), "..")
- self.tooldef_file = tooldef_file if tooldef_file else os.path.join(self.dir, "FmmtConf.ini")
- self.tooldef = dict()
-
- def SetConfigFile(self) -> None:
- if os.environ['FmmtConfPath']:
- self.tooldef_file = os.path.join(os.environ['FmmtConfPath'], 'FmmtConf.ini')
- else:
- PathList = os.environ['PATH'].split(os.pathsep)
- for CurrentPath in PathList:
- if os.path.exists(os.path.join(CurrentPath, 'FmmtConf.ini')):
- self.tooldef_file = os.path.join(CurrentPath, 'FmmtConf.ini')
- break
-
- def VerifyTools(self, guidtool) -> None:
- """
- Verify Tools and Update Tools path.
- """
- path_env = os.environ.get("PATH")
- path_env_list = path_env.split(os.pathsep)
- path_env_list.append(os.path.dirname(__file__))
- path_env_list = list(set(path_env_list))
- cmd = guidtool.command
- if os.path.isabs(cmd):
- if not os.path.exists(cmd):
- if guidtool not in self.default_tools:
- logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
- logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")
- else:
- logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
- else:
- guidtool.ifexist = True
- else:
- for syspath in path_env_list:
- if glob.glob(os.path.join(syspath, cmd+"*")):
- guidtool.ifexist = True
- break
- else:
- if guidtool not in self.default_tools:
- logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
- logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")
- else:
- logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
-
- def LoadingTools(self) -> None:
- self.SetConfigFile()
- if os.path.exists(self.tooldef_file):
- with open(self.tooldef_file, "r") as fd:
- config_data = fd.readlines()
- for line in config_data:
- try:
- if not line.startswith("#"):
- guid, short_name, command = line.split()
- new_format_guid = struct2stream(ModifyGuidFormat(guid.strip()))
- self.tooldef[new_format_guid] = GUIDTool(
- guid.strip(), short_name.strip(), command.strip())
- except:
- logger.error("GuidTool load error!")
- continue
- else:
- self.tooldef.update(self.default_tools)
-
- def __getitem__(self, guid):
- if not self.tooldef:
- self.LoadingTools()
- guid_tool = self.tooldef.get(guid)
- if guid_tool:
- self.VerifyTools(guid_tool)
- return guid_tool
- else:
- logger.error("{} GuidTool is not defined!".format(guid))
- raise Exception("Process Failed: is not defined!")
-
-guidtools = GUIDTools()
-
+## @file
+# This file is used to define the FMMT dependent external tool management class.
+#
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import glob
+import logging
+import os
+import shutil
+import sys
+import tempfile
+import uuid
+from FirmwareStorageFormat.Common import *
+from utils.FmmtLogger import FmmtLogger as logger
+import subprocess
+
+def ExecuteCommand(cmd: list) -> None:
+ subprocess.run(cmd,stdout=subprocess.DEVNULL)
+
+class GUIDTool:
+ def __init__(self, guid: str, short_name: str, command: str) -> None:
+ self.guid: str = guid
+ self.short_name: str = short_name
+ self.command: str = command
+ self.ifexist: bool = False
+
+ def pack(self, buffer: bytes) -> bytes:
+ """
+ compress file.
+ """
+ tool = self.command
+ if tool:
+ tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))
+ ToolInputFile = os.path.join(tmp, "pack_uncompress_sec_file")
+ ToolOuputFile = os.path.join(tmp, "pack_sec_file")
+ try:
+ file = open(ToolInputFile, "wb")
+ file.write(buffer)
+ file.close()
+ command = [tool, '-e', '-o', ToolOuputFile,
+ ToolInputFile]
+ ExecuteCommand(command)
+ buf = open(ToolOuputFile, "rb")
+ res_buffer = buf.read()
+ except Exception as msg:
+ logger.error(msg)
+ return ""
+ else:
+ buf.close()
+ if os.path.exists(tmp):
+ shutil.rmtree(tmp)
+ return res_buffer
+ else:
+ logger.error(
+ "Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")
+ logger.info("Its GUID is: %s" % self.guid)
+ return ""
+
+
+ def unpack(self, buffer: bytes) -> bytes:
+ """
+ buffer: remove common header
+ uncompress file
+ """
+ tool = self.command
+ if tool:
+ tmp = tempfile.mkdtemp(dir=os.environ.get('tmp'))
+ ToolInputFile = os.path.join(tmp, "unpack_sec_file")
+ ToolOuputFile = os.path.join(tmp, "unpack_uncompress_sec_file")
+ try:
+ file = open(ToolInputFile, "wb")
+ file.write(buffer)
+ file.close()
+ command = [tool, '-d', '-o', ToolOuputFile, ToolInputFile]
+ ExecuteCommand(command)
+ buf = open(ToolOuputFile, "rb")
+ res_buffer = buf.read()
+ except Exception as msg:
+ logger.error(msg)
+ return ""
+ else:
+ buf.close()
+ if os.path.exists(tmp):
+ shutil.rmtree(tmp)
+ return res_buffer
+ else:
+ logger.error("Error parsing section: EFI_SECTION_GUID_DEFINED cannot be parsed at this time.")
+ logger.info("Its GUID is: %s" % self.guid)
+ return ""
+
+class GUIDTools:
+ '''
+ GUIDTools is responsible for reading FMMTConfig.ini, verify the tools and provide interfaces to access those tools.
+ '''
+ default_tools = {
+ struct2stream(ModifyGuidFormat("a31280ad-481e-41b6-95e8-127f4c984779")): GUIDTool("a31280ad-481e-41b6-95e8-127f4c984779", "TIANO", "TianoCompress"),
+ struct2stream(ModifyGuidFormat("ee4e5898-3914-4259-9d6e-dc7bd79403cf")): GUIDTool("ee4e5898-3914-4259-9d6e-dc7bd79403cf", "LZMA", "LzmaCompress"),
+ struct2stream(ModifyGuidFormat("fc1bcdb0-7d31-49aa-936a-a4600d9dd083")): GUIDTool("fc1bcdb0-7d31-49aa-936a-a4600d9dd083", "CRC32", "GenCrc32"),
+ struct2stream(ModifyGuidFormat("d42ae6bd-1352-4bfb-909a-ca72a6eae889")): GUIDTool("d42ae6bd-1352-4bfb-909a-ca72a6eae889", "LZMAF86", "LzmaF86Compress"),
+ struct2stream(ModifyGuidFormat("3d532050-5cda-4fd0-879e-0f7f630d5afb")): GUIDTool("3d532050-5cda-4fd0-879e-0f7f630d5afb", "BROTLI", "BrotliCompress"),
+ }
+
+ def __init__(self, tooldef_file: str=None) -> None:
+ self.dir = os.path.join(os.path.dirname(__file__), "..")
+ self.tooldef_file = tooldef_file if tooldef_file else os.path.join(self.dir, "FmmtConf.ini")
+ self.tooldef = dict()
+
+ def SetConfigFile(self) -> None:
+ if os.environ['FmmtConfPath']:
+ self.tooldef_file = os.path.join(os.environ['FmmtConfPath'], 'FmmtConf.ini')
+ else:
+ PathList = os.environ['PATH'].split(os.pathsep)
+ for CurrentPath in PathList:
+ if os.path.exists(os.path.join(CurrentPath, 'FmmtConf.ini')):
+ self.tooldef_file = os.path.join(CurrentPath, 'FmmtConf.ini')
+ break
+
+ def VerifyTools(self, guidtool) -> None:
+ """
+ Verify Tools and Update Tools path.
+ """
+ path_env = os.environ.get("PATH")
+ path_env_list = path_env.split(os.pathsep)
+ path_env_list.append(os.path.dirname(__file__))
+ path_env_list = list(set(path_env_list))
+ cmd = guidtool.command
+ if os.path.isabs(cmd):
+ if not os.path.exists(cmd):
+ if guidtool not in self.default_tools:
+ logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
+ logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")
+ else:
+ logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
+ else:
+ guidtool.ifexist = True
+ else:
+ for syspath in path_env_list:
+ if glob.glob(os.path.join(syspath, cmd+"*")):
+ guidtool.ifexist = True
+ break
+ else:
+ if guidtool not in self.default_tools:
+ logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
+ logger.error("Please goto edk2 repo in current console, run 'edksetup.bat rebuild' command, and try again.\n")
+ else:
+ logger.error("Tool Not found %s, which causes compress/uncompress process error." % cmd)
+
+ def LoadingTools(self) -> None:
+ self.SetConfigFile()
+ if os.path.exists(self.tooldef_file):
+ with open(self.tooldef_file, "r") as fd:
+ config_data = fd.readlines()
+ for line in config_data:
+ try:
+ if not line.startswith("#"):
+ guid, short_name, command = line.split()
+ new_format_guid = struct2stream(ModifyGuidFormat(guid.strip()))
+ self.tooldef[new_format_guid] = GUIDTool(
+ guid.strip(), short_name.strip(), command.strip())
+ except:
+ logger.error("GuidTool load error!")
+ continue
+ else:
+ self.tooldef.update(self.default_tools)
+
+ def __getitem__(self, guid):
+ if not self.tooldef:
+ self.LoadingTools()
+ guid_tool = self.tooldef.get(guid)
+ if guid_tool:
+ self.VerifyTools(guid_tool)
+ return guid_tool
+ else:
+ logger.error("{} GuidTool is not defined!".format(guid))
+ raise Exception("Process Failed: is not defined!")
+
+guidtools = GUIDTools()
+
diff --git a/BaseTools/Source/Python/FMMT/utils/FmmtLogger.py b/BaseTools/Source/Python/FMMT/utils/FmmtLogger.py
index 385f098310..d9ff5e324b 100644
--- a/BaseTools/Source/Python/FMMT/utils/FmmtLogger.py
+++ b/BaseTools/Source/Python/FMMT/utils/FmmtLogger.py
@@ -1,31 +1,31 @@
-## @file
-# This file is used to define the Fmmt Logger.
-#
-# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-
-##
-
-import logging
-import sys
-import os
-
-logfile = 'FMMT_Build.log'
-if os.path.exists(logfile):
- os.remove(logfile)
-
-FmmtLogger = logging.getLogger('FMMT')
-FmmtLogger.setLevel(logging.DEBUG)
-
-log_stream_handler=logging.StreamHandler(sys.stdout)
-log_file_handler=logging.FileHandler(logfile)
-log_stream_handler.setLevel(logging.INFO)
-
-stream_format=logging.Formatter("%(levelname)-8s: %(message)s")
-file_format=logging.Formatter("%(levelname)-8s: %(message)s")
-
-log_stream_handler.setFormatter(stream_format)
-log_file_handler.setFormatter(file_format)
-
-FmmtLogger.addHandler(log_stream_handler)
-FmmtLogger.addHandler(log_file_handler)
+## @file
+# This file is used to define the Fmmt Logger.
+#
+# Copyright (c) 2021-, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+
+##
+
+import logging
+import sys
+import os
+
+logfile = 'FMMT_Build.log'
+if os.path.exists(logfile):
+ os.remove(logfile)
+
+FmmtLogger = logging.getLogger('FMMT')
+FmmtLogger.setLevel(logging.DEBUG)
+
+log_stream_handler=logging.StreamHandler(sys.stdout)
+log_file_handler=logging.FileHandler(logfile)
+log_stream_handler.setLevel(logging.INFO)
+
+stream_format=logging.Formatter("%(levelname)-8s: %(message)s")
+file_format=logging.Formatter("%(levelname)-8s: %(message)s")
+
+log_stream_handler.setFormatter(stream_format)
+log_file_handler.setFormatter(file_format)
+
+FmmtLogger.addHandler(log_stream_handler)
+FmmtLogger.addHandler(log_file_handler)