Пример #1
0
 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
Пример #2
0
 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)
Пример #3
0
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:
        for item in FmmtParser.WholeFvTree.Findlist:
            if item.Parent.key != Fv_name and item.Parent.Data.Name != Fv_name:
                FmmtParser.WholeFvTree.Findlist.remove(item)
    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))
    else:
        logger.error('Target Ffs not found!!!')
Пример #4
0
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:
        for item in FmmtParser.WholeFvTree.Findlist:
            if item.Parent.key != Fv_name and item.Parent.Data.Name != Fv_name:
                FmmtParser.WholeFvTree.Findlist.remove(item)
    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))
Пример #5
0
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))
Пример #6
0
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))
Пример #7
0
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:
        for item in FmmtParser.WholeFvTree.Findlist:
            if item.Parent.key != Fv_name and item.Parent.Data.Name != Fv_name:
                FmmtParser.WholeFvTree.Findlist.remove(item)
    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))
Пример #8
0
 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.Status = True
             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)
         elif TargetLen == 0:
             self.Status = True
             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)
         # 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
Пример #9
0
 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 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 - self.NewFfs.Data.Size
         # 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)
             self.Status = True
         # 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)
             self.Status = True
         # 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)
     logger.debug('Done!')
     return self.Status