mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 11:13:53 +01:00 
			
		
		
		
	Signed-off-by: lzeng14 Reviewed-by: lgao4 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12585 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			609 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			609 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   FFS file access utilities.
 | |
| 
 | |
|   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions
 | |
|   of the BSD License which accompanies this distribution.  The
 | |
|   full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "FwVolDriver.h"
 | |
| 
 | |
| #define PHYSICAL_ADDRESS_TO_POINTER(Address)  ((VOID *) ((UINTN) Address))
 | |
| 
 | |
| /**
 | |
|   Set File State in the FfsHeader.
 | |
| 
 | |
|   @param  State          File state to be set into FFS header.
 | |
|   @param  FfsHeader      Points to the FFS file header
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SetFileState (
 | |
|   IN UINT8                State,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Set File State in the FfsHeader
 | |
|   //
 | |
|   FfsHeader->State = (EFI_FFS_FILE_STATE) (FfsHeader->State ^ State);
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the FFS file state by checking the highest bit set in the header's state field.
 | |
| 
 | |
|   @param  ErasePolarity  Erase polarity attribute of the firmware volume
 | |
|   @param  FfsHeader      Points to the FFS file header
 | |
| 
 | |
|   @return FFS File state
 | |
| 
 | |
| **/
 | |
| EFI_FFS_FILE_STATE
 | |
| GetFileState (
 | |
|   IN UINT8                ErasePolarity,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   EFI_FFS_FILE_STATE  FileState;
 | |
|   UINT8               HighestBit;
 | |
| 
 | |
|   FileState = FfsHeader->State;
 | |
| 
 | |
|   if (ErasePolarity != 0) {
 | |
|     FileState = (EFI_FFS_FILE_STATE)~FileState;
 | |
|   }
 | |
| 
 | |
|   HighestBit = 0x80;
 | |
|   while (HighestBit != 0 && ((HighestBit & FileState) == 0)) {
 | |
|     HighestBit >>= 1;
 | |
|   }
 | |
| 
 | |
|   return (EFI_FFS_FILE_STATE) HighestBit;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the Buffer Address to LBA Entry Address.
 | |
| 
 | |
|   @param FvDevice        Cached FvDevice
 | |
|   @param BufferAddress   Address of Buffer
 | |
|   @param LbaListEntry    Pointer to the got LBA entry that contains the address.
 | |
| 
 | |
|   @retval EFI_NOT_FOUND  Buffer address is out of FvDevice.
 | |
|   @retval EFI_SUCCESS    LBA entry is found for Buffer address.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Buffer2LbaEntry (
 | |
|   IN     FV_DEVICE              *FvDevice,
 | |
|   IN     EFI_PHYSICAL_ADDRESS   BufferAddress,
 | |
|   OUT LBA_ENTRY                 **LbaListEntry
 | |
|   )
 | |
| {
 | |
|   LBA_ENTRY   *LbaEntry;
 | |
|   LIST_ENTRY  *Link;
 | |
| 
 | |
|   Link      = FvDevice->LbaHeader.ForwardLink;
 | |
|   LbaEntry  = (LBA_ENTRY *) Link;
 | |
| 
 | |
|   //
 | |
|   // Locate LBA which contains the address
 | |
|   //
 | |
|   while (&LbaEntry->Link != &FvDevice->LbaHeader) {
 | |
|     if ((EFI_PHYSICAL_ADDRESS) (UINTN) (LbaEntry->StartingAddress) > BufferAddress) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Link      = LbaEntry->Link.ForwardLink;
 | |
|     LbaEntry  = (LBA_ENTRY *) Link;
 | |
|   }
 | |
| 
 | |
|   if (&LbaEntry->Link == &FvDevice->LbaHeader) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   Link      = LbaEntry->Link.BackLink;
 | |
|   LbaEntry  = (LBA_ENTRY *) Link;
 | |
| 
 | |
|   if (&LbaEntry->Link == &FvDevice->LbaHeader) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   *LbaListEntry = LbaEntry;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the Buffer Address to LBA Address & Offset.
 | |
| 
 | |
|   @param FvDevice        Cached FvDevice
 | |
|   @param BufferAddress   Address of Buffer
 | |
|   @param Lba             Pointer to the gob Lba value
 | |
|   @param Offset          Pointer to the got Offset
 | |
| 
 | |
|   @retval EFI_NOT_FOUND  Buffer address is out of FvDevice.
 | |
|   @retval EFI_SUCCESS    LBA and Offset is found for Buffer address.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| Buffer2Lba (
 | |
|   IN     FV_DEVICE              *FvDevice,
 | |
|   IN     EFI_PHYSICAL_ADDRESS   BufferAddress,
 | |
|   OUT EFI_LBA                   *Lba,
 | |
|   OUT UINTN                     *Offset
 | |
|   )
 | |
| {
 | |
|   LBA_ENTRY   *LbaEntry;
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   LbaEntry = NULL;
 | |
| 
 | |
|   Status = Buffer2LbaEntry (
 | |
|             FvDevice,
 | |
|             BufferAddress,
 | |
|             &LbaEntry
 | |
|             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   *Lba    = LbaEntry->LbaIndex;
 | |
|   *Offset = (UINTN) BufferAddress - (UINTN) LbaEntry->StartingAddress;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check if a block of buffer is erased.
 | |
| 
 | |
|   @param  ErasePolarity  Erase polarity attribute of the firmware volume
 | |
|   @param  Buffer         The buffer to be checked
 | |
|   @param  BufferSize     Size of the buffer in bytes
 | |
| 
 | |
|   @retval TRUE           The block of buffer is erased
 | |
|   @retval FALSE          The block of buffer is not erased
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsBufferErased (
 | |
|   IN UINT8    ErasePolarity,
 | |
|   IN UINT8    *Buffer,
 | |
|   IN UINTN    BufferSize
 | |
|   )
 | |
| {
 | |
|   UINTN Count;
 | |
|   UINT8 EraseByte;
 | |
| 
 | |
|   if (ErasePolarity == 1) {
 | |
|     EraseByte = 0xFF;
 | |
|   } else {
 | |
|     EraseByte = 0;
 | |
|   }
 | |
| 
 | |
|   for (Count = 0; Count < BufferSize; Count++) {
 | |
|     if (Buffer[Count] != EraseByte) {
 | |
|       return FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Verify checksum of the firmware volume header.
 | |
| 
 | |
|   @param  FvHeader       Points to the firmware volume header to be checked
 | |
| 
 | |
|   @retval TRUE           Checksum verification passed
 | |
|   @retval FALSE          Checksum verification failed
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| VerifyFvHeaderChecksum (
 | |
|   IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
 | |
|   )
 | |
| {
 | |
|   UINT16  Checksum;
 | |
| 
 | |
|   Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength);
 | |
| 
 | |
|   if (Checksum == 0) {
 | |
|     return TRUE;
 | |
|   } else {
 | |
|     return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Verify checksum of the FFS file header.
 | |
| 
 | |
|   @param  FfsHeader      Points to the FFS file header to be checked
 | |
| 
 | |
|   @retval TRUE           Checksum verification passed
 | |
|   @retval FALSE          Checksum verification failed
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| VerifyHeaderChecksum (
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   UINT8 HeaderChecksum;
 | |
| 
 | |
|   if (IS_FFS_FILE2 (FfsHeader)) {
 | |
|     HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER2));
 | |
|   } else {
 | |
|     HeaderChecksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
 | |
|   }
 | |
|   HeaderChecksum = (UINT8) (HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File);
 | |
| 
 | |
|   if (HeaderChecksum == 0) {
 | |
|     return TRUE;
 | |
|   } else {
 | |
|     return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Verify checksum of the FFS file data.
 | |
| 
 | |
|   @param  FfsHeader      Points to the FFS file header to be checked
 | |
| 
 | |
|   @retval TRUE           Checksum verification passed
 | |
|   @retval FALSE          Checksum verification failed
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| VerifyFileChecksum (
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   UINT8                   FileChecksum;
 | |
|   EFI_FV_FILE_ATTRIBUTES  Attributes;
 | |
| 
 | |
|   Attributes = FfsHeader->Attributes;
 | |
| 
 | |
|   if ((Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
 | |
| 
 | |
|     //
 | |
|     // Check checksum of FFS data
 | |
|     //
 | |
|     if (IS_FFS_FILE2 (FfsHeader)) {
 | |
|       FileChecksum = CalculateSum8 ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER2));
 | |
|     } else {
 | |
|       FileChecksum = CalculateSum8 ((UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER));
 | |
|     }
 | |
|     FileChecksum = (UINT8) (FileChecksum + FfsHeader->IntegrityCheck.Checksum.File);
 | |
| 
 | |
|     if (FileChecksum == 0) {
 | |
|       return TRUE;
 | |
|     } else {
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|   } else {
 | |
| 
 | |
|     if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
 | |
|       return FALSE;
 | |
|     } else {
 | |
|       return TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check if it's a valid FFS file header.
 | |
| 
 | |
|   @param  ErasePolarity  Erase polarity attribute of the firmware volume
 | |
|   @param  FfsHeader      Points to the FFS file header to be checked
 | |
| 
 | |
|   @retval TRUE           Valid FFS file header
 | |
|   @retval FALSE          Invalid FFS file header
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsValidFFSHeader (
 | |
|   IN UINT8                ErasePolarity,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   EFI_FFS_FILE_STATE  FileState;
 | |
| 
 | |
|   //
 | |
|   // Check if it is a free space
 | |
|   //
 | |
|   if (IsBufferErased (
 | |
|         ErasePolarity,
 | |
|         (UINT8 *) FfsHeader,
 | |
|         sizeof (EFI_FFS_FILE_HEADER)
 | |
|         )) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   FileState = GetFileState (ErasePolarity, FfsHeader);
 | |
| 
 | |
|   switch (FileState) {
 | |
|   case EFI_FILE_HEADER_CONSTRUCTION:
 | |
|     //
 | |
|     // fall through
 | |
|     //
 | |
|   case EFI_FILE_HEADER_INVALID:
 | |
|     return FALSE;
 | |
| 
 | |
|   case EFI_FILE_HEADER_VALID:
 | |
|     //
 | |
|     // fall through
 | |
|     //
 | |
|   case EFI_FILE_DATA_VALID:
 | |
|     //
 | |
|     // fall through
 | |
|     //
 | |
|   case EFI_FILE_MARKED_FOR_UPDATE:
 | |
|     //
 | |
|     // fall through
 | |
|     //
 | |
|   case EFI_FILE_DELETED:
 | |
|     //
 | |
|     // Here we need to verify header checksum
 | |
|     //
 | |
|     if (!VerifyHeaderChecksum (FfsHeader)) {
 | |
|       return FALSE;
 | |
|     }
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     //
 | |
|     // return
 | |
|     //
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get next possible of Firmware File System Header.
 | |
| 
 | |
|   @param  ErasePolarity  Erase polarity attribute of the firmware volume
 | |
|   @param  FfsHeader      Points to the FFS file header to be skipped.
 | |
| 
 | |
|   @return  Pointer to next FFS header.
 | |
| 
 | |
| **/
 | |
| EFI_PHYSICAL_ADDRESS
 | |
| GetNextPossibleFileHeader (
 | |
|   IN UINT8                ErasePolarity,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   UINT32  FileLength;
 | |
|   UINT32  SkipLength;
 | |
| 
 | |
|   if (!IsValidFFSHeader (ErasePolarity, FfsHeader)) {
 | |
|     //
 | |
|     // Skip this header
 | |
|     //
 | |
|     if (IS_FFS_FILE2 (FfsHeader)) {
 | |
|       return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2);
 | |
|     } else {
 | |
|       return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + sizeof (EFI_FFS_FILE_HEADER);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (IS_FFS_FILE2 (FfsHeader)) {
 | |
|     FileLength = FFS_FILE2_SIZE (FfsHeader);
 | |
|   } else {
 | |
|     FileLength = FFS_FILE_SIZE (FfsHeader);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Since FileLength is not multiple of 8, we need skip some bytes
 | |
|   // to get next possible header
 | |
|   //
 | |
|   SkipLength = FileLength;
 | |
|   while ((SkipLength & 0x07) != 0) {
 | |
|     SkipLength++;
 | |
|   }
 | |
| 
 | |
|   return (EFI_PHYSICAL_ADDRESS) (UINTN) FfsHeader + SkipLength;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Search FFS file with the same FFS name in FV Cache.
 | |
| 
 | |
|   @param  FvDevice     Cached FV image.
 | |
|   @param  FfsHeader    Points to the FFS file header to be skipped.
 | |
|   @param  StateBit     FFS file state bit to be checked.
 | |
| 
 | |
|   @return  Pointer to next found FFS header. NULL will return if no found.
 | |
| 
 | |
| **/
 | |
| EFI_FFS_FILE_HEADER *
 | |
| DuplicateFileExist (
 | |
|   IN FV_DEVICE            *FvDevice,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader,
 | |
|   IN EFI_FFS_FILE_STATE   StateBit
 | |
|   )
 | |
| {
 | |
|   UINT8               *Ptr;
 | |
|   EFI_FFS_FILE_HEADER *NextFfsFile;
 | |
| 
 | |
|   //
 | |
|   // Search duplicate file, not from the beginning of FV,
 | |
|   // just search the next ocurrence of this file
 | |
|   //
 | |
|   NextFfsFile = FfsHeader;
 | |
| 
 | |
|   do {
 | |
|     Ptr = (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (
 | |
|                       GetNextPossibleFileHeader (FvDevice->ErasePolarity,
 | |
|                       NextFfsFile)
 | |
|                       );
 | |
|     NextFfsFile = (EFI_FFS_FILE_HEADER *) Ptr;
 | |
| 
 | |
|     if ((UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength - Ptr <
 | |
|         sizeof (EFI_FFS_FILE_HEADER)
 | |
|           ) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (!IsValidFFSHeader (FvDevice->ErasePolarity, NextFfsFile)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (!VerifyFileChecksum (NextFfsFile)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (CompareGuid (&NextFfsFile->Name, &FfsHeader->Name)) {
 | |
|       if (GetFileState (FvDevice->ErasePolarity, NextFfsFile) == StateBit) {
 | |
|         return NextFfsFile;
 | |
|       }
 | |
|     }
 | |
|   } while (Ptr < (UINT8 *) PHYSICAL_ADDRESS_TO_POINTER (FvDevice->CachedFv) + FvDevice->FwVolHeader->FvLength);
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Change FFS file header state and write to FV.
 | |
| 
 | |
|   @param  FvDevice     Cached FV image.
 | |
|   @param  FfsHeader    Points to the FFS file header to be updated.
 | |
|   @param  State        FFS file state to be set.
 | |
| 
 | |
|   @retval EFI_SUCCESS  File state is writen into FV.
 | |
|   @retval others       File state can't be writen into FV.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| UpdateHeaderBit (
 | |
|   IN FV_DEVICE            *FvDevice,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader,
 | |
|   IN EFI_FFS_FILE_STATE   State
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_LBA     Lba;
 | |
|   UINTN       Offset;
 | |
|   UINTN       NumBytesWritten;
 | |
| 
 | |
|   Lba    = 0;
 | |
|   Offset = 0;
 | |
| 
 | |
|   SetFileState (State, FfsHeader);
 | |
| 
 | |
|   Buffer2Lba (
 | |
|     FvDevice,
 | |
|     (EFI_PHYSICAL_ADDRESS) (UINTN) (&FfsHeader->State),
 | |
|     &Lba,
 | |
|     &Offset
 | |
|     );
 | |
|   //
 | |
|   // Write the state byte into FV
 | |
|   //
 | |
|   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
 | |
|   Status = FvDevice->Fvb->Write (
 | |
|                             FvDevice->Fvb,
 | |
|                             Lba,
 | |
|                             Offset,
 | |
|                             &NumBytesWritten,
 | |
|                             &FfsHeader->State
 | |
|                             );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check if it's a valid FFS file.
 | |
|   Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first.
 | |
| 
 | |
|   @param  FvDevice       Cached FV image.
 | |
|   @param  FfsHeader      Points to the FFS file to be checked
 | |
| 
 | |
|   @retval TRUE           Valid FFS file
 | |
|   @retval FALSE          Invalid FFS file
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsValidFFSFile (
 | |
|   IN FV_DEVICE            *FvDevice,
 | |
|   IN EFI_FFS_FILE_HEADER  *FfsHeader
 | |
|   )
 | |
| {
 | |
|   EFI_FFS_FILE_STATE  FileState;
 | |
|   UINT8               ErasePolarity;
 | |
| 
 | |
|   ErasePolarity = FvDevice->ErasePolarity;
 | |
| 
 | |
|   FileState     = GetFileState (ErasePolarity, FfsHeader);
 | |
| 
 | |
|   switch (FileState) {
 | |
|   case EFI_FILE_DATA_VALID:
 | |
|     if (!VerifyFileChecksum (FfsHeader)) {
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // Check if there is another duplicated file with the EFI_FILE_DATA_VALID
 | |
|     //
 | |
|     if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) {
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|     break;
 | |
| 
 | |
|   case EFI_FILE_MARKED_FOR_UPDATE:
 | |
|     if (!VerifyFileChecksum (FfsHeader)) {
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
 | |
|       //
 | |
|       // since its data area is not unperturbed, it cannot be reclaimed,
 | |
|       // marked it as deleted
 | |
|       //
 | |
|       UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED);
 | |
|       return TRUE;
 | |
| 
 | |
|     } else if (DuplicateFileExist (FvDevice, FfsHeader, EFI_FILE_DATA_VALID) != NULL) {
 | |
|       //
 | |
|       // Here the found file is more recent than this file,
 | |
|       // mark it as deleted
 | |
|       //
 | |
|       UpdateHeaderBit (FvDevice, FfsHeader, EFI_FILE_DELETED);
 | |
|       return TRUE;
 | |
| 
 | |
|     } else {
 | |
|       return TRUE;
 | |
|     }
 | |
| 
 | |
|     break;
 | |
| 
 | |
|   case EFI_FILE_DELETED:
 | |
|     if (!VerifyFileChecksum (FfsHeader)) {
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 |