BaseTools/FMMT: Add Extract FV function

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3938

With this patch "-e" parameter supports extract FV function.
Usage: FMMT -e Inputfile TargetFv Outputfile

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Signed-off-by: Yuwei Chen <yuwei.chen@intel.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
This commit is contained in:
Chen, Christine 2022-09-16 09:50:56 +08:00 committed by mergify[bot]
parent b03dceb87f
commit 0e6db46b1b
3 changed files with 31 additions and 22 deletions

View File

@ -24,7 +24,8 @@ parser.add_argument("-d", "--Delete", dest="Delete", nargs='+',
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 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='+',

View File

@ -63,9 +63,10 @@ def DeleteFfs(inputfile: str, TargetFfs_name: str, outputfile: str, Fv_name: str
FmmtParser.WholeFvTree.FindNode(TargetFfs_name, FmmtParser.WholeFvTree.Findlist)
# Choose the Specfic DeleteFfs with Fv info
if Fv_name:
for item in FmmtParser.WholeFvTree.Findlist:
if item.Parent.key != Fv_name and item.Parent.Data.Name != Fv_name:
FmmtParser.WholeFvTree.Findlist.remove(item)
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:
@ -149,9 +150,10 @@ def ReplaceFfs(inputfile: str, Ffs_name: str, newffsfile: str, outputfile: str,
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:
for item in FmmtParser.WholeFvTree.Findlist:
if item.Parent.key != Fv_name and item.Parent.Data.Name != Fv_name:
FmmtParser.WholeFvTree.Findlist.remove(item)
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)
@ -180,18 +182,25 @@ def ExtractFfs(inputfile: str, Ffs_name: str, outputfile: str, Fv_name: str=None
logger.debug('Done!')
FmmtParser.WholeFvTree.FindNode(Ffs_name, FmmtParser.WholeFvTree.Findlist)
if Fv_name:
for item in FmmtParser.WholeFvTree.Findlist:
if item.Parent.key != Fv_name and item.Parent.Data.Name != Fv_name:
FmmtParser.WholeFvTree.Findlist.remove(item)
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]
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))
if TargetNode.type == FV_TREE or SEC_FV_TREE or 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 not found!!!')
logger.error('Target Ffs/Fv not found!!!')

View File

@ -155,7 +155,6 @@ class FvHandler:
def CompressData(self, TargetTree) -> None:
TreePath = TargetTree.GetTreePath()
pos = len(TreePath)
self.Status = False
while pos:
if not self.Status:
if TreePath[pos-1].type == SECTION_TREE and TreePath[pos-1].Data.Type == 0x02:
@ -487,7 +486,6 @@ class FvHandler:
~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.Status = True
self.TargetFfs.Data.Data = b'\xff' * (-TargetLen)
TargetFv.Data.Free_Space = (-TargetLen)
TargetFv.Data.ModFvExt()
@ -498,13 +496,14 @@ class FvHandler:
ModifyFfsType(self.NewFfs)
# Recompress from the Fv node to update all the related node data.
self.CompressData(TargetFv)
elif TargetLen == 0:
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: