Example #1
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!!!')
Example #2
0
 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
Example #3
0
 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 ""
Example #4
0
 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!")
Example #5
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))
Example #6
0
 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)
Example #7
0
 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
Example #8
0
 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
Example #9
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))
Example #10
0
 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()
Example #11
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))
Example #12
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))
Example #13
0
 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)
Example #14
0
 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
Example #15
0
 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