]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c
Remove IntelFrameworkModulePkg
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / FwVolDxe / FwVolWrite.c
diff --git a/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c b/IntelFrameworkModulePkg/Universal/FirmwareVolume/FwVolDxe/FwVolWrite.c
deleted file mode 100644 (file)
index 804f966..0000000
+++ /dev/null
@@ -1,1614 +0,0 @@
-/** @file\r
-  Implements write firmware file.\r
-\r
-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "FwVolDriver.h"\r
-\r
-/**\r
-  Calculate the checksum for the FFS header.\r
-\r
-  @param FfsHeader   FFS File Header which needs to calculate the checksum\r
-\r
-**/\r
-VOID\r
-SetHeaderChecksum (\r
-  IN EFI_FFS_FILE_HEADER *FfsHeader\r
-  )\r
-{\r
-  EFI_FFS_FILE_STATE  State;\r
-  UINT8               FileChecksum;\r
-\r
-  //\r
-  // The state and the File checksum are not included\r
-  //\r
-  State = FfsHeader->State;\r
-  FfsHeader->State = 0;\r
-\r
-  FileChecksum = FfsHeader->IntegrityCheck.Checksum.File;\r
-  FfsHeader->IntegrityCheck.Checksum.File = 0;\r
-\r
-  FfsHeader->IntegrityCheck.Checksum.Header = 0;\r
-\r
-  if (IS_FFS_FILE2 (FfsHeader)) {\r
-    FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r
-      (UINT8 *) FfsHeader,\r
-      sizeof (EFI_FFS_FILE_HEADER2)\r
-      );\r
-  } else {\r
-    FfsHeader->IntegrityCheck.Checksum.Header = CalculateCheckSum8 (\r
-      (UINT8 *) FfsHeader,\r
-      sizeof (EFI_FFS_FILE_HEADER)\r
-      );\r
-  }\r
-\r
-  FfsHeader->State                          = State;\r
-  FfsHeader->IntegrityCheck.Checksum.File   = FileChecksum;\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  Calculate the checksum for the FFS File.\r
-\r
-  @param FfsHeader       FFS File Header which needs to calculate the checksum\r
-  @param ActualFileSize  The whole Ffs File Length.\r
-\r
-**/\r
-VOID\r
-SetFileChecksum (\r
-  IN EFI_FFS_FILE_HEADER *FfsHeader,\r
-  IN UINTN               ActualFileSize\r
-  )\r
-{\r
-  if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {\r
-\r
-    FfsHeader->IntegrityCheck.Checksum.File = 0;\r
-\r
-    if (IS_FFS_FILE2 (FfsHeader)) {\r
-      FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r
-        (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2),\r
-        ActualFileSize - sizeof (EFI_FFS_FILE_HEADER2)\r
-        );\r
-    } else {\r
-      FfsHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 (\r
-        (UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER),\r
-        ActualFileSize - sizeof (EFI_FFS_FILE_HEADER)\r
-        );\r
-    }\r
-\r
-  } else {\r
-\r
-    FfsHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
-\r
-  }\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  Get the alignment value from File Attributes.\r
-\r
-  @param FfsAttributes  FFS attribute\r
-\r
-  @return Alignment value.\r
-\r
-**/\r
-UINTN\r
-GetRequiredAlignment (\r
-  IN EFI_FV_FILE_ATTRIBUTES FfsAttributes\r
-  )\r
-{\r
-  UINTN AlignmentValue;\r
-\r
-  AlignmentValue = FfsAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT;\r
-\r
-  if (AlignmentValue <= 3) {\r
-    return 0x08;\r
-  }\r
-\r
-  if (AlignmentValue > 16) {\r
-    //\r
-    // Anyway, we won't reach this code\r
-    //\r
-    return 0x08;\r
-  }\r
-\r
-  return (UINTN)1 << AlignmentValue;\r
-\r
-}\r
-\r
-/**\r
-  Calculate the leading Pad file size to meet the alignment requirement.\r
-\r
-  @param FvDevice          Cached Firmware Volume.\r
-  @param StartAddress      The starting address to write the FFS File.\r
-  @param BufferSize        The FFS File Buffer Size.\r
-  @param RequiredAlignment FFS File Data alignment requirement.\r
-\r
-  @return The required Pad File Size.\r
-\r
-**/\r
-UINTN\r
-CalculatePadFileSize (\r
-  IN FV_DEVICE            *FvDevice,\r
-  IN EFI_PHYSICAL_ADDRESS StartAddress,\r
-  IN UINTN                BufferSize,\r
-  IN UINTN                RequiredAlignment\r
-  )\r
-{\r
-  UINTN DataStartPos;\r
-  UINTN RelativePos;\r
-  UINTN PadSize;\r
-\r
-  if (BufferSize > 0x00FFFFFF) {\r
-    DataStartPos  = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER2);\r
-  } else {\r
-    DataStartPos  = (UINTN) StartAddress + sizeof (EFI_FFS_FILE_HEADER);\r
-  }\r
-  RelativePos   = DataStartPos - (UINTN) FvDevice->CachedFv;\r
-\r
-  PadSize       = 0;\r
-\r
-  while ((RelativePos & (RequiredAlignment - 1)) != 0) {\r
-    RelativePos++;\r
-    PadSize++;\r
-  }\r
-  //\r
-  // If padsize is 0, no pad file needed;\r
-  // If padsize is great than 24, then pad file can be created\r
-  //\r
-  if ((PadSize == 0) || (PadSize >= sizeof (EFI_FFS_FILE_HEADER))) {\r
-    return PadSize;\r
-  }\r
-\r
-  //\r
-  // Perhaps following method can save space\r
-  //\r
-  RelativePos = DataStartPos - (UINTN) FvDevice->CachedFv + sizeof (EFI_FFS_FILE_HEADER);\r
-  PadSize     = sizeof (EFI_FFS_FILE_HEADER);\r
-\r
-  while ((RelativePos & (RequiredAlignment - 1)) != 0) {\r
-    RelativePos++;\r
-    PadSize++;\r
-  }\r
-\r
-  return PadSize;\r
-}\r
-\r
-/**\r
-  Convert EFI_FV_FILE_ATTRIBUTES to FFS_FILE_ATTRIBUTES.\r
-\r
-  @param FvFileAttrib    The value of EFI_FV_FILE_ATTRIBUTES\r
-  @param FfsFileAttrib   Pointer to the got FFS_FILE_ATTRIBUTES value.\r
-\r
-**/\r
-VOID\r
-FvFileAttrib2FfsFileAttrib (\r
-  IN     EFI_FV_FILE_ATTRIBUTES  FvFileAttrib,\r
-  OUT UINT8                      *FfsFileAttrib\r
-  )\r
-{\r
-  UINT8 FvFileAlignment;\r
-  UINT8 FfsFileAlignment;\r
-  UINT8 FfsFileAlignment2;\r
-\r
-  FvFileAlignment   = (UINT8) (FvFileAttrib & EFI_FV_FILE_ATTRIB_ALIGNMENT);\r
-  FfsFileAlignment  = 0;\r
-  FfsFileAlignment2 = 0;\r
-\r
-  switch (FvFileAlignment) {\r
-  case 0:\r
-    //\r
-    // fall through\r
-    //\r
-  case 1:\r
-    //\r
-    // fall through\r
-    //\r
-  case 2:\r
-    //\r
-    // fall through\r
-    //\r
-  case 3:\r
-    //\r
-    // fall through\r
-    //\r
-    FfsFileAlignment = 0;\r
-    break;\r
-\r
-  case 4:\r
-    //\r
-    // fall through\r
-    //\r
-  case 5:\r
-    //\r
-    // fall through\r
-    //\r
-  case 6:\r
-    //\r
-    // fall through\r
-    //\r
-    FfsFileAlignment = 1;\r
-    break;\r
-\r
-  case 7:\r
-    //\r
-    // fall through\r
-    //\r
-  case 8:\r
-    //\r
-    // fall through\r
-    //\r
-    FfsFileAlignment = 2;\r
-    break;\r
-\r
-  case 9:\r
-    FfsFileAlignment = 3;\r
-    break;\r
-\r
-  case 10:\r
-    //\r
-    // fall through\r
-    //\r
-  case 11:\r
-    //\r
-    // fall through\r
-    //\r
-    FfsFileAlignment = 4;\r
-    break;\r
-\r
-  case 12:\r
-    //\r
-    // fall through\r
-    //\r
-  case 13:\r
-    //\r
-    // fall through\r
-    //\r
-  case 14:\r
-    //\r
-    // fall through\r
-    //\r
-    FfsFileAlignment = 5;\r
-    break;\r
-\r
-  case 15:\r
-    FfsFileAlignment = 6;\r
-    break;\r
-\r
-  case 16:\r
-    FfsFileAlignment = 7;\r
-    break;\r
-\r
-  case 17:\r
-    FfsFileAlignment = 0;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  case 18:\r
-    FfsFileAlignment = 1;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  case 19:\r
-    FfsFileAlignment = 2;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  case 20:\r
-    FfsFileAlignment = 3;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  case 21:\r
-    FfsFileAlignment = 4;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  case 22:\r
-    FfsFileAlignment = 5;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  case 23:\r
-    FfsFileAlignment = 6;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  case 24:\r
-    FfsFileAlignment = 7;\r
-    FfsFileAlignment2 = 1;\r
-    break;\r
-  }\r
-\r
-  *FfsFileAttrib = (UINT8) ((FfsFileAlignment << 3) | (FfsFileAlignment2 << 1));\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  Locate a free space entry that can hold this FFS file.\r
-\r
-  @param FvDevice          Cached Firmware Volume.\r
-  @param Size              The FFS file size.\r
-  @param RequiredAlignment FFS File Data alignment requirement.\r
-  @param PadSize           Pointer to the size of leading Pad File.\r
-  @param FreeSpaceEntry    Pointer to the Free Space Entry that meets the requirement.\r
-\r
-  @retval EFI_SUCCESS     The free space entry is found.\r
-  @retval EFI_NOT_FOUND   The free space entry can't be found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvLocateFreeSpaceEntry (\r
-  IN  FV_DEVICE             *FvDevice,\r
-  IN  UINTN                 Size,\r
-  IN  UINTN                 RequiredAlignment,\r
-  OUT UINTN                 *PadSize,\r
-  OUT FREE_SPACE_ENTRY      **FreeSpaceEntry\r
-  )\r
-{\r
-  FREE_SPACE_ENTRY  *FreeSpaceListEntry;\r
-  LIST_ENTRY        *Link;\r
-  UINTN             PadFileSize;\r
-\r
-  Link                = FvDevice->FreeSpaceHeader.ForwardLink;\r
-  FreeSpaceListEntry  = (FREE_SPACE_ENTRY *) Link;\r
-\r
-  //\r
-  // Loop the free space entry list to find one that can hold the\r
-  // required the file size\r
-  //\r
-  while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) {\r
-    PadFileSize = CalculatePadFileSize (\r
-                    FvDevice,\r
-                    (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceListEntry->StartingAddress,\r
-                    Size,\r
-                    RequiredAlignment\r
-                    );\r
-    if (FreeSpaceListEntry->Length >= Size + PadFileSize) {\r
-      *FreeSpaceEntry = FreeSpaceListEntry;\r
-      *PadSize        = PadFileSize;\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink;\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-\r
-}\r
-\r
-/**\r
-  Locate Pad File for writing, this is got from FV Cache.\r
-\r
-  @param FvDevice           Cached Firmware Volume.\r
-  @param Size               The required FFS file size.\r
-  @param RequiredAlignment  FFS File Data alignment requirement.\r
-  @param PadSize            Pointer to the size of leading Pad File.\r
-  @param PadFileEntry       Pointer to the Pad File Entry that meets the requirement.\r
-\r
-  @retval EFI_SUCCESS     The required pad file is found.\r
-  @retval EFI_NOT_FOUND   The required pad file can't be found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvLocatePadFile (\r
-  IN  FV_DEVICE           *FvDevice,\r
-  IN  UINTN               Size,\r
-  IN  UINTN               RequiredAlignment,\r
-  OUT UINTN               *PadSize,\r
-  OUT FFS_FILE_LIST_ENTRY **PadFileEntry\r
-  )\r
-{\r
-  FFS_FILE_LIST_ENTRY *FileEntry;\r
-  EFI_FFS_FILE_STATE  FileState;\r
-  EFI_FFS_FILE_HEADER *FileHeader;\r
-  UINTN               PadAreaLength;\r
-  UINTN               PadFileSize;\r
-  UINTN               HeaderSize;\r
-\r
-  FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r
-\r
-  //\r
-  // travel through the whole file list to get the pad file entry\r
-  //\r
-  while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) {\r
-\r
-    FileHeader  = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader;\r
-    FileState   = GetFileState (FvDevice->ErasePolarity, FileHeader);\r
-\r
-    if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) {\r
-      //\r
-      // we find one valid pad file, check its free area length\r
-      //\r
-      if (IS_FFS_FILE2 (FileHeader)) {\r
-        HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
-        PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r
-      } else {\r
-        HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
-        PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r
-      }\r
-\r
-      PadFileSize = CalculatePadFileSize (\r
-                      FvDevice,\r
-                      (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize,\r
-                      Size,\r
-                      RequiredAlignment\r
-                      );\r
-      if (PadAreaLength >= (Size + PadFileSize)) {\r
-        *PadSize      = PadFileSize;\r
-        *PadFileEntry = FileEntry;\r
-        return EFI_SUCCESS;\r
-      }\r
-    }\r
-\r
-    FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink);\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  Locate a suitable pad file for multiple file writing.\r
-\r
-  @param FvDevice          Cached Firmware Volume.\r
-  @param NumOfFiles        The number of Files that needed updating\r
-  @param BufferSize        The array of each file size.\r
-  @param RequiredAlignment The array of of FFS File Data alignment requirement.\r
-  @param PadSize           The array of size of each leading Pad File.\r
-  @param TotalSizeNeeded   The totalsize that can hold these files.\r
-  @param PadFileEntry      Pointer to the Pad File Entry that meets the requirement.\r
-\r
-  @retval EFI_SUCCESS     The required pad file is found.\r
-  @retval EFI_NOT_FOUND   The required pad file can't be found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvSearchSuitablePadFile (\r
-  IN FV_DEVICE              *FvDevice,\r
-  IN UINTN                  NumOfFiles,\r
-  IN UINTN                  *BufferSize,\r
-  IN UINTN                  *RequiredAlignment,\r
-  OUT UINTN                 *PadSize,\r
-  OUT UINTN                 *TotalSizeNeeded,\r
-  OUT FFS_FILE_LIST_ENTRY   **PadFileEntry\r
-  )\r
-{\r
-  FFS_FILE_LIST_ENTRY *FileEntry;\r
-  EFI_FFS_FILE_STATE  FileState;\r
-  EFI_FFS_FILE_HEADER *FileHeader;\r
-  UINTN               PadAreaLength;\r
-  UINTN               TotalSize;\r
-  UINTN               Index;\r
-  UINTN               HeaderSize;\r
-\r
-  FileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;\r
-\r
-  //\r
-  // travel through the whole file list to get the pad file entry\r
-  //\r
-  while (FileEntry != (FFS_FILE_LIST_ENTRY *) &FvDevice->FfsFileListHeader) {\r
-\r
-    FileHeader  = (EFI_FFS_FILE_HEADER *) FileEntry->FfsHeader;\r
-    FileState   = GetFileState (FvDevice->ErasePolarity, FileHeader);\r
-\r
-    if ((FileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) && (FileState == EFI_FILE_DATA_VALID)) {\r
-      //\r
-      // we find one valid pad file, check its length\r
-      //\r
-      if (IS_FFS_FILE2 (FileHeader)) {\r
-        HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
-        PadAreaLength = FFS_FILE2_SIZE (FileHeader) - HeaderSize;\r
-      } else {\r
-        HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
-        PadAreaLength = FFS_FILE_SIZE (FileHeader) - HeaderSize;\r
-      }\r
-      TotalSize     = 0;\r
-\r
-      for (Index = 0; Index < NumOfFiles; Index++) {\r
-        PadSize[Index] = CalculatePadFileSize (\r
-                      FvDevice,\r
-                      (EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader + HeaderSize + TotalSize,\r
-                      BufferSize[Index],\r
-                      RequiredAlignment[Index]\r
-                      );\r
-        TotalSize += PadSize[Index];\r
-        TotalSize += BufferSize[Index];\r
-\r
-        if (TotalSize > PadAreaLength) {\r
-          break;\r
-        }\r
-      }\r
-\r
-      if (PadAreaLength >= TotalSize) {\r
-        *PadFileEntry     = FileEntry;\r
-        *TotalSizeNeeded  = TotalSize;\r
-        return EFI_SUCCESS;\r
-      }\r
-    }\r
-\r
-    FileEntry = (FFS_FILE_LIST_ENTRY *) (FileEntry->Link.ForwardLink);\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  Locate a Free Space entry which can hold these files, including\r
-  meeting the alignment requirements.\r
-\r
-  @param FvDevice          Cached Firmware Volume.\r
-  @param NumOfFiles        The number of Files that needed updating\r
-  @param BufferSize        The array of each file size.\r
-  @param RequiredAlignment The array of of FFS File Data alignment requirement.\r
-  @param PadSize           The array of size of each leading Pad File.\r
-  @param TotalSizeNeeded   The got total size that can hold these files.\r
-  @param FreeSpaceEntry    The Free Space Entry that can hold these files.\r
-\r
-  @retval EFI_SUCCESS     The free space entry is found.\r
-  @retval EFI_NOT_FOUND   The free space entry can't be found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvSearchSuitableFreeSpace (\r
-  IN FV_DEVICE              *FvDevice,\r
-  IN UINTN                  NumOfFiles,\r
-  IN UINTN                  *BufferSize,\r
-  IN UINTN                  *RequiredAlignment,\r
-  OUT UINTN                 *PadSize,\r
-  OUT UINTN                 *TotalSizeNeeded,\r
-  OUT FREE_SPACE_ENTRY      **FreeSpaceEntry\r
-  )\r
-{\r
-  FREE_SPACE_ENTRY  *FreeSpaceListEntry;\r
-  LIST_ENTRY        *Link;\r
-  UINTN             TotalSize;\r
-  UINTN             Index;\r
-  UINT8             *StartAddr;\r
-\r
-  Link                = FvDevice->FreeSpaceHeader.ForwardLink;\r
-\r
-  FreeSpaceListEntry  = (FREE_SPACE_ENTRY *) Link;\r
-\r
-  while ((LIST_ENTRY *) FreeSpaceListEntry != &FvDevice->FreeSpaceHeader) {\r
-    TotalSize = 0;\r
-    StartAddr = FreeSpaceListEntry->StartingAddress;\r
-\r
-    //\r
-    // Calculate the totalsize we need\r
-    //\r
-    for (Index = 0; Index < NumOfFiles; Index++) {\r
-      //\r
-      // Perhaps we don't need an EFI_FFS_FILE_HEADER, the first file\r
-      // have had its leading pad file.\r
-      //\r
-      PadSize[Index] = CalculatePadFileSize (\r
-                    FvDevice,\r
-                    (EFI_PHYSICAL_ADDRESS) (UINTN) StartAddr + TotalSize,\r
-                    BufferSize[Index],\r
-                    RequiredAlignment[Index]\r
-                    );\r
-\r
-      TotalSize += PadSize[Index];\r
-      TotalSize += BufferSize[Index];\r
-\r
-      if (TotalSize > FreeSpaceListEntry->Length) {\r
-        break;\r
-      }\r
-    }\r
-\r
-    if (FreeSpaceListEntry->Length >= TotalSize) {\r
-      *FreeSpaceEntry   = FreeSpaceListEntry;\r
-      *TotalSizeNeeded  = TotalSize;\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    FreeSpaceListEntry = (FREE_SPACE_ENTRY *) FreeSpaceListEntry->Link.ForwardLink;\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  Calculate the length of the remaining space in FV.\r
-\r
-  @param FvDevice        Cached Firmware Volume\r
-  @param Offset          Current offset to FV base address.\r
-  @param Lba             LBA number for the current offset.\r
-  @param LOffset         Offset in block for the current offset.\r
-\r
-  @return the length of remaining space.\r
-\r
-**/\r
-UINTN\r
-CalculateRemainingLength (\r
-  IN     FV_DEVICE                            *FvDevice,\r
-  IN     UINTN                                Offset,\r
-  OUT  EFI_LBA                                *Lba,\r
-  OUT  UINTN                                  *LOffset\r
-  )\r
-{\r
-  LIST_ENTRY      *Link;\r
-  LBA_ENTRY       *LbaEntry;\r
-  UINTN           Count;\r
-\r
-  Count     = 0;\r
-  *Lba      = 0;\r
-  Link      = FvDevice->LbaHeader.ForwardLink;\r
-  LbaEntry  = (LBA_ENTRY *) Link;\r
-\r
-  while (&LbaEntry->Link != &FvDevice->LbaHeader) {\r
-    if (Count > Offset) {\r
-      break;\r
-    }\r
-\r
-    Count += LbaEntry->BlockLength;\r
-    (*Lba)++;\r
-    Link      = LbaEntry->Link.ForwardLink;\r
-    LbaEntry  = (LBA_ENTRY *) Link;\r
-  }\r
-\r
-  if (Count <= Offset) {\r
-    return 0;\r
-  }\r
-\r
-  Link      = LbaEntry->Link.BackLink;\r
-  LbaEntry  = (LBA_ENTRY *) Link;\r
-\r
-  (*Lba)--;\r
-  *LOffset  = (UINTN) (LbaEntry->BlockLength - (Count - Offset));\r
-\r
-  Count     = 0;\r
-  while (&LbaEntry->Link != &FvDevice->LbaHeader) {\r
-\r
-    Count += LbaEntry->BlockLength;\r
-\r
-    Link      = LbaEntry->Link.ForwardLink;\r
-    LbaEntry  = (LBA_ENTRY *) Link;\r
-  }\r
-\r
-  Count -= *LOffset;\r
-\r
-  return Count;\r
-}\r
-\r
-/**\r
-  Writes data beginning at Lba:Offset from FV. The write terminates either\r
-  when *NumBytes of data have been written, or when the firmware end is\r
-  reached.  *NumBytes is updated to reflect the actual number of bytes\r
-  written.\r
-\r
-  @param FvDevice        Cached Firmware Volume\r
-  @param Offset          Offset in the block at which to begin write\r
-  @param NumBytes        At input, indicates the requested write size.\r
-                         At output, indicates the actual number of bytes written.\r
-  @param Buffer          Buffer containing source data for the write.\r
-\r
-  @retval EFI_SUCCESS  Data is successfully written into FV.\r
-  @return error        Data is failed written.\r
-\r
-**/\r
-EFI_STATUS\r
-FvcWrite (\r
-  IN     FV_DEVICE                            *FvDevice,\r
-  IN     UINTN                                Offset,\r
-  IN OUT UINTN                                *NumBytes,\r
-  IN     UINT8                                *Buffer\r
-  )\r
-{\r
-  EFI_STATUS                          Status;\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  EFI_LBA                             Lba;\r
-  UINTN                               LOffset;\r
-  EFI_FVB_ATTRIBUTES_2                FvbAttributes;\r
-  UINTN                               RemainingLength;\r
-  UINTN                               WriteLength;\r
-  UINT8                               *TmpBuffer;\r
-\r
-  LOffset = 0;\r
-  RemainingLength = CalculateRemainingLength (FvDevice, Offset, &Lba, &LOffset);\r
-  if ((UINTN) (*NumBytes) > RemainingLength) {\r
-    *NumBytes = (UINTN) RemainingLength;\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Fvb = FvDevice->Fvb;\r
-\r
-  Status = Fvb->GetAttributes (\r
-                  Fvb,\r
-                  &FvbAttributes\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if ((FvbAttributes & EFI_FV2_WRITE_STATUS) == 0) {\r
-    return EFI_ACCESS_DENIED;\r
-  }\r
-\r
-  RemainingLength = *NumBytes;\r
-  WriteLength     = RemainingLength;\r
-  TmpBuffer       = Buffer;\r
-\r
-  do {\r
-    Status = Fvb->Write (\r
-                    Fvb,\r
-                    Lba,\r
-                    LOffset,\r
-                    &WriteLength,\r
-                    TmpBuffer\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
-\r
-    if (Status == EFI_BAD_BUFFER_SIZE) {\r
-      Lba++;\r
-      LOffset = 0;\r
-      TmpBuffer += WriteLength;\r
-      RemainingLength -= WriteLength;\r
-      WriteLength = (UINTN) RemainingLength;\r
-\r
-      continue;\r
-    } else {\r
-      return Status;\r
-    }\r
-  } while (1);\r
-\r
-Done:\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Create a new FFS file into Firmware Volume device.\r
-\r
-  @param FvDevice        Cached Firmware Volume.\r
-  @param FfsFileBuffer   A buffer that holds an FFS file,(it contains\r
-                         a File Header which is in init state).\r
-  @param BufferSize      The size of FfsFileBuffer.\r
-  @param ActualFileSize  The actual file length, it may not be multiples of 8.\r
-  @param FileName        The FFS File Name.\r
-  @param FileType        The FFS File Type.\r
-  @param FileAttributes  The Attributes of the FFS File to be created.\r
-\r
-  @retval EFI_SUCCESS           FFS fle is added into FV.\r
-  @retval EFI_INVALID_PARAMETER File type is not valid.\r
-  @retval EFI_DEVICE_ERROR      FV doesn't set writable attribute.\r
-  @retval EFI_NOT_FOUND         FV has no enough space for the added file.\r
-\r
-**/\r
-EFI_STATUS\r
-FvCreateNewFile (\r
-  IN FV_DEVICE                *FvDevice,\r
-  IN UINT8                    *FfsFileBuffer,\r
-  IN UINTN                    BufferSize,\r
-  IN UINTN                    ActualFileSize,\r
-  IN EFI_GUID                 *FileName,\r
-  IN EFI_FV_FILETYPE          FileType,\r
-  IN EFI_FV_FILE_ATTRIBUTES   FileAttributes\r
-  )\r
-{\r
-  EFI_STATUS                          Status;\r
-  EFI_FFS_FILE_HEADER                 *FileHeader;\r
-  EFI_PHYSICAL_ADDRESS                BufferPtr;\r
-  UINTN                               Offset;\r
-  UINTN                               NumBytesWritten;\r
-  UINTN                               StateOffset;\r
-  FREE_SPACE_ENTRY                    *FreeSpaceEntry;\r
-  UINTN                               RequiredAlignment;\r
-  UINTN                               PadFileSize;\r
-  FFS_FILE_LIST_ENTRY                 *PadFileEntry;\r
-  EFI_FFS_FILE_ATTRIBUTES             TmpFileAttribute;\r
-  FFS_FILE_LIST_ENTRY                 *FfsFileEntry;\r
-  UINTN                               HeaderSize;\r
-\r
-  //\r
-  // File Type: 0x0E~0xE0 are reserved\r
-  //\r
-  if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // First find a free space that can hold this image.\r
-  // Check alignment, FFS at least must be aligned at 8-byte boundary\r
-  //\r
-  RequiredAlignment = GetRequiredAlignment (FileAttributes);\r
-\r
-  Status = FvLocateFreeSpaceEntry (\r
-            FvDevice,\r
-            BufferSize,\r
-            RequiredAlignment,\r
-            &PadFileSize,\r
-            &FreeSpaceEntry\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Maybe we need to find a PAD file that can hold this image\r
-    //\r
-    Status = FvCreateNewFileInsidePadFile (\r
-              FvDevice,\r
-              FfsFileBuffer,\r
-              BufferSize,\r
-              ActualFileSize,\r
-              FileName,\r
-              FileType,\r
-              FileAttributes\r
-              );\r
-\r
-    return Status;\r
-  }\r
-\r
-  BufferPtr     = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress;\r
-\r
-  //\r
-  // If we need a leading PAD File, create it first.\r
-  //\r
-  if (PadFileSize != 0) {\r
-    Status = FvCreatePadFileInFreeSpace (\r
-              FvDevice,\r
-              FreeSpaceEntry,\r
-              PadFileSize - sizeof (EFI_FFS_FILE_HEADER),\r
-              &PadFileEntry\r
-              );\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-  //\r
-  // Maybe we create a pad file, so re-get the free space starting address\r
-  // and length\r
-  //\r
-  BufferPtr     = (EFI_PHYSICAL_ADDRESS) (UINTN) FreeSpaceEntry->StartingAddress;\r
-\r
-  //\r
-  // File creation step 1: Allocate File Header,\r
-  // Mark EFI_FILE_HEADER_CONSTRUCTION bit to TRUE,\r
-  // Write Name, IntegrityCheck.Header, Type, Attributes, and Size\r
-  //\r
-  FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;\r
-  if (ActualFileSize > 0x00FFFFFF) {\r
-    HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
-  } else {\r
-    HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
-  }\r
-  SetFileState (EFI_FILE_HEADER_CONSTRUCTION, FileHeader);\r
-\r
-  Offset          = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
-  StateOffset     = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r
-\r
-  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            StateOffset,\r
-            &NumBytesWritten,\r
-            &FileHeader->State\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // update header 2 cache\r
-  //\r
-  CopyMem (\r
-    (UINT8 *) (UINTN) BufferPtr,\r
-    FileHeader,\r
-    HeaderSize\r
-    );\r
-\r
-  //\r
-  // update Free Space Entry, now need to substract the file header length\r
-  //\r
-  FreeSpaceEntry->StartingAddress += HeaderSize;\r
-  FreeSpaceEntry->Length -= HeaderSize;\r
-\r
-  CopyGuid (&FileHeader->Name, FileName);\r
-  FileHeader->Type = FileType;\r
-\r
-  //\r
-  // Convert FvFileAttribute to FfsFileAttributes\r
-  //\r
-  FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute);\r
-\r
-  FileHeader->Attributes = TmpFileAttribute;\r
-\r
-  //\r
-  // File size is including the FFS File Header.\r
-  //\r
-  if (ActualFileSize > 0x00FFFFFF) {\r
-    ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;\r
-    *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
-    FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;\r
-  } else {\r
-    *(UINT32 *) FileHeader->Size &= 0xFF000000;\r
-    *(UINT32 *) FileHeader->Size |= ActualFileSize;\r
-  }\r
-\r
-  SetHeaderChecksum (FileHeader);\r
-\r
-  Offset          = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
-\r
-  NumBytesWritten = HeaderSize;\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            Offset,\r
-            &NumBytesWritten,\r
-            (UINT8 *) FileHeader\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // update header 2 cache\r
-  //\r
-  CopyMem (\r
-    (UINT8 *) (UINTN) BufferPtr,\r
-    FileHeader,\r
-    HeaderSize\r
-    );\r
-\r
-  //\r
-  // end of step 1\r
-  //\r
-  // File creation step 2:\r
-  // MARK EFI_FILE_HEADER_VALID bit to TRUE,\r
-  // Write IntegrityCheck.File, File Data\r
-  //\r
-  SetFileState (EFI_FILE_HEADER_VALID, FileHeader);\r
-\r
-  Offset          = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
-  StateOffset     = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r
-\r
-  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            StateOffset,\r
-            &NumBytesWritten,\r
-            &FileHeader->State\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // update header 2 cache\r
-  //\r
-  CopyMem (\r
-    (UINT8 *) (UINTN) BufferPtr,\r
-    FileHeader,\r
-    HeaderSize\r
-    );\r
-\r
-  //\r
-  // update Free Space Entry, now need to substract the file data length\r
-  //\r
-  FreeSpaceEntry->StartingAddress += (BufferSize - HeaderSize);\r
-  FreeSpaceEntry->Length -= (BufferSize - HeaderSize);\r
-\r
-  //\r
-  // Calculate File Checksum\r
-  //\r
-  SetFileChecksum (FileHeader, ActualFileSize);\r
-\r
-  Offset          = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
-\r
-  NumBytesWritten = BufferSize;\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            Offset,\r
-            &NumBytesWritten,\r
-            FfsFileBuffer\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // each time write block successfully, write also to cache\r
-  //\r
-  CopyMem (\r
-    (UINT8 *) (UINTN) BufferPtr,\r
-    FfsFileBuffer,\r
-    NumBytesWritten\r
-    );\r
-\r
-  //\r
-  // Step 3: Mark EFI_FILE_DATA_VALID to TRUE\r
-  //\r
-  SetFileState (EFI_FILE_DATA_VALID, FileHeader);\r
-\r
-  Offset          = (UINTN) (BufferPtr - FvDevice->CachedFv);\r
-  StateOffset     = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r
-\r
-  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            StateOffset,\r
-            &NumBytesWritten,\r
-            &FileHeader->State\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // update header 2 cache\r
-  //\r
-  CopyMem (\r
-    (UINT8 *) (UINTN) BufferPtr,\r
-    FileHeader,\r
-    HeaderSize\r
-    );\r
-\r
-  //\r
-  // If successfully, insert an FfsFileEntry at the end of ffs file list\r
-  //\r
-\r
-  FfsFileEntry            = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));\r
-  ASSERT (FfsFileEntry   != NULL);\r
-  FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) BufferPtr;\r
-  InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);\r
-\r
-  //\r
-  // Set cache file to this file\r
-  //\r
-  FvDevice->CurrentFfsFile = FfsFileEntry;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Update a File, so after successful update, there are 2 files existing\r
-  in FV, one is marked for deleted, and another one is valid.\r
-\r
-  @param FvDevice          Cached Firmware Volume.\r
-  @param FfsFileBuffer     A buffer that holds an FFS file,(it contains\r
-                           a File Header which is in init state).\r
-  @param BufferSize        The size of FfsFileBuffer.\r
-  @param ActualFileSize    The actual file length, it may not be multiples of 8.\r
-  @param FileName          The FFS File Name.\r
-  @param NewFileType       The FFS File Type.\r
-  @param NewFileAttributes The Attributes of the FFS File to be created.\r
-\r
-  @retval EFI_SUCCESS           FFS fle is updated into FV.\r
-  @retval EFI_INVALID_PARAMETER File type is not valid.\r
-  @retval EFI_DEVICE_ERROR      FV doesn't set writable attribute.\r
-  @retval EFI_NOT_FOUND         FV has no enough space for the added file.\r
-                                FFS with same file name is not found in FV.\r
-\r
-**/\r
-EFI_STATUS\r
-FvUpdateFile (\r
-  IN FV_DEVICE                *FvDevice,\r
-  IN UINT8                    *FfsFileBuffer,\r
-  IN UINTN                    BufferSize,\r
-  IN UINTN                    ActualFileSize,\r
-  IN EFI_GUID                 *FileName,\r
-  IN EFI_FV_FILETYPE          NewFileType,\r
-  IN EFI_FV_FILE_ATTRIBUTES   NewFileAttributes\r
-  )\r
-{\r
-  EFI_STATUS                          Status;\r
-  EFI_FIRMWARE_VOLUME2_PROTOCOL       *Fv;\r
-  UINTN                               NumBytesWritten;\r
-  EFI_FV_FILETYPE                     OldFileType;\r
-  EFI_FV_FILE_ATTRIBUTES              OldFileAttributes;\r
-  UINTN                               OldFileSize;\r
-  EFI_FFS_FILE_HEADER                 *OldFileHeader;\r
-  UINTN                               OldOffset;\r
-  UINTN                               OldStateOffset;\r
-  FFS_FILE_LIST_ENTRY                 *OldFfsFileEntry;\r
-  UINTN                               Key;\r
-  EFI_GUID                            FileNameGuid;\r
-\r
-  Fv  = &FvDevice->Fv;\r
-\r
-  //\r
-  // Step 1, find old file,\r
-  // Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE in the older header\r
-  //\r
-\r
-  //\r
-  // Check if the file was read last time.\r
-  //\r
-  OldFileHeader   = NULL;\r
-  OldFfsFileEntry = FvDevice->CurrentFfsFile;\r
-\r
-  if (OldFfsFileEntry != NULL) {\r
-    OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader;\r
-  }\r
-\r
-  if ((OldFfsFileEntry == NULL) || (!CompareGuid (&OldFileHeader->Name, FileName))) {\r
-    Key = 0;\r
-    do {\r
-      OldFileType = 0;\r
-      Status = Fv->GetNextFile (\r
-                    Fv,\r
-                    &Key,\r
-                    &OldFileType,\r
-                    &FileNameGuid,\r
-                    &OldFileAttributes,\r
-                    &OldFileSize\r
-                    );\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    } while (!CompareGuid (&FileNameGuid, FileName));\r
-\r
-    //\r
-    // Get FfsFileEntry from the search key\r
-    //\r
-    OldFfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key;\r
-\r
-    //\r
-    // Double check file state before being ready to be removed\r
-    //\r
-    OldFileHeader = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry->FfsHeader;\r
-  } else {\r
-    //\r
-    // Mark the cache file to invalid\r
-    //\r
-    FvDevice->CurrentFfsFile = NULL;\r
-  }\r
-  //\r
-  // Update File: Mark EFI_FILE_MARKED_FOR_UPDATE to TRUE\r
-  //\r
-  SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader);\r
-\r
-  OldOffset       = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv);\r
-  OldStateOffset  = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader;\r
-\r
-  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            OldStateOffset,\r
-            &NumBytesWritten,\r
-            &OldFileHeader->State\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // if failed, write the bit back in the cache, its XOR operation.\r
-    //\r
-    SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldFileHeader);\r
-\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Step 2, Create New Files\r
-  //\r
-  Status = FvCreateNewFile (\r
-            FvDevice,\r
-            FfsFileBuffer,\r
-            BufferSize,\r
-            ActualFileSize,\r
-            FileName,\r
-            NewFileType,\r
-            NewFileAttributes\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // If successfully, remove this file entry,\r
-  // although delete file may fail.\r
-  //\r
-  (OldFfsFileEntry->Link.BackLink)->ForwardLink = OldFfsFileEntry->Link.ForwardLink;\r
-  (OldFfsFileEntry->Link.ForwardLink)->BackLink = OldFfsFileEntry->Link.BackLink;\r
-  FreePool (OldFfsFileEntry);\r
-\r
-  //\r
-  // Step 3: Delete old files,\r
-  // by marking EFI_FILE_DELETED to TRUE\r
-  //\r
-  SetFileState (EFI_FILE_DELETED, OldFileHeader);\r
-\r
-  OldOffset       = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) OldFileHeader - FvDevice->CachedFv);\r
-  OldStateOffset  = OldOffset + (UINT8 *) &OldFileHeader->State - (UINT8 *) OldFileHeader;\r
-\r
-  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            OldStateOffset,\r
-            &NumBytesWritten,\r
-            &OldFileHeader->State\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // if failed, write the bit back in the cache, its XOR operation.\r
-    //\r
-    SetFileState (EFI_FILE_DELETED, OldFileHeader);\r
-\r
-    return Status;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Deleted a given file from FV device.\r
-\r
-  @param FvDevice        Cached Firmware Volume.\r
-  @param NameGuid        The FFS File Name.\r
-\r
-  @retval EFI_SUCCESS    FFS file with the specified FFS name is removed.\r
-  @retval EFI_NOT_FOUND  FFS file with the specified FFS name is not found.\r
-\r
-**/\r
-EFI_STATUS\r
-FvDeleteFile (\r
-  IN FV_DEVICE  *FvDevice,\r
-  IN EFI_GUID   *NameGuid\r
-  )\r
-{\r
-  EFI_STATUS                          Status;\r
-  UINTN                               Key;\r
-  EFI_GUID                            FileNameGuid;\r
-  EFI_FV_FILETYPE                     FileType;\r
-  EFI_FV_FILE_ATTRIBUTES              FileAttributes;\r
-  UINTN                               FileSize;\r
-  EFI_FFS_FILE_HEADER                 *FileHeader;\r
-  FFS_FILE_LIST_ENTRY                 *FfsFileEntry;\r
-  EFI_FFS_FILE_STATE                  FileState;\r
-  EFI_FIRMWARE_VOLUME2_PROTOCOL        *Fv;\r
-  UINTN                               Offset;\r
-  UINTN                               StateOffset;\r
-  UINTN                               NumBytesWritten;\r
-\r
-  Fv  = &FvDevice->Fv;\r
-\r
-  //\r
-  // Check if the file was read last time.\r
-  //\r
-  FileHeader    = NULL;\r
-  FfsFileEntry  = FvDevice->CurrentFfsFile;\r
-\r
-  if (FfsFileEntry != NULL) {\r
-    FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;\r
-  }\r
-\r
-  if ((FfsFileEntry == NULL) || (!CompareGuid (&FileHeader->Name, NameGuid))) {\r
-    //\r
-    // Next search for the file using GetNextFile\r
-    //\r
-    Key = 0;\r
-    do {\r
-      FileType = 0;\r
-      Status = Fv->GetNextFile (\r
-                    Fv,\r
-                    &Key,\r
-                    &FileType,\r
-                    &FileNameGuid,\r
-                    &FileAttributes,\r
-                    &FileSize\r
-                    );\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    } while (!CompareGuid (&FileNameGuid, NameGuid));\r
-\r
-    //\r
-    // Get FfsFileEntry from the search key\r
-    //\r
-    FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key;\r
-\r
-    //\r
-    // Double check file state before being ready to be removed\r
-    //\r
-    FileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;\r
-  } else {\r
-    //\r
-    // Mark the cache file to NULL\r
-    //\r
-    FvDevice->CurrentFfsFile = NULL;\r
-  }\r
-\r
-  FileState = GetFileState (FvDevice->ErasePolarity, FileHeader);\r
-\r
-  if (FileState == EFI_FILE_HEADER_INVALID) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  if (FileState == EFI_FILE_DELETED) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-  //\r
-  // Delete File: Mark EFI_FILE_DELETED to TRUE\r
-  //\r
-  SetFileState (EFI_FILE_DELETED, FileHeader);\r
-\r
-  Offset          = (UINTN) ((EFI_PHYSICAL_ADDRESS) (UINTN) FileHeader - FvDevice->CachedFv);\r
-  StateOffset     = Offset + (UINT8 *) &FileHeader->State - (UINT8 *) FileHeader;\r
-\r
-  NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);\r
-  Status = FvcWrite (\r
-            FvDevice,\r
-            StateOffset,\r
-            &NumBytesWritten,\r
-            &FileHeader->State\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // if failed, write the bit back in the cache, its XOR operation.\r
-    //\r
-    SetFileState (EFI_FILE_DELETED, FileHeader);\r
-\r
-    return Status;\r
-  }\r
-  //\r
-  // If successfully, remove this file entry\r
-  //\r
-  FvDevice->CurrentFfsFile                    = NULL;\r
-\r
-  (FfsFileEntry->Link.BackLink)->ForwardLink  = FfsFileEntry->Link.ForwardLink;\r
-  (FfsFileEntry->Link.ForwardLink)->BackLink  = FfsFileEntry->Link.BackLink;\r
-  FreePool (FfsFileEntry);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Writes one or more files to the firmware volume.\r
-\r
-  @param  This                   Indicates the calling context.\r
-  @param  NumberOfFiles          Number of files.\r
-  @param  WritePolicy            WritePolicy indicates the level of reliability\r
-                                 for the write in the event of a power failure or\r
-                                 other system failure during the write operation.\r
-  @param  FileData               FileData is an pointer to an array of\r
-                                 EFI_FV_WRITE_DATA. Each element of array\r
-                                 FileData represents a file to be written.\r
-\r
-  @retval EFI_SUCCESS            Files successfully written to firmware volume\r
-  @retval EFI_OUT_OF_RESOURCES   Not enough buffer to be allocated.\r
-  @retval EFI_DEVICE_ERROR       Device error.\r
-  @retval EFI_WRITE_PROTECTED    Write protected.\r
-  @retval EFI_NOT_FOUND          Not found.\r
-  @retval EFI_INVALID_PARAMETER  Invalid parameter.\r
-  @retval EFI_UNSUPPORTED        This function not supported.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-FvWriteFile (\r
-  IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL   *This,\r
-  IN UINT32                         NumberOfFiles,\r
-  IN EFI_FV_WRITE_POLICY            WritePolicy,\r
-  IN EFI_FV_WRITE_FILE_DATA         *FileData\r
-  )\r
-{\r
-  EFI_STATUS                          Status;\r
-  UINTN                               Index1;\r
-  UINTN                               Index2;\r
-  UINT8                               *FileBuffer;\r
-  UINTN                               BufferSize;\r
-  UINTN                               ActualSize;\r
-  UINT8                               ErasePolarity;\r
-  FV_DEVICE                           *FvDevice;\r
-  EFI_FV_FILETYPE                     FileType;\r
-  EFI_FV_FILE_ATTRIBUTES              FileAttributes;\r
-  UINTN                               Size;\r
-  BOOLEAN                             CreateNewFile[MAX_FILES];\r
-  UINTN                               NumDelete;\r
-  EFI_FV_ATTRIBUTES                   FvAttributes;\r
-  UINT32                              AuthenticationStatus;\r
-  UINTN                               HeaderSize;\r
-\r
-  if (NumberOfFiles > MAX_FILES) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Status = EFI_SUCCESS;\r
-\r
-  SetMem (CreateNewFile, NumberOfFiles, TRUE);\r
-\r
-  FvDevice  = FV_DEVICE_FROM_THIS (This);\r
-\r
-  //\r
-  // First check the volume attributes.\r
-  //\r
-  Status = This->GetVolumeAttributes (\r
-                  This,\r
-                  &FvAttributes\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  //\r
-  // Can we have write right?\r
-  //\r
-  if ((FvAttributes & EFI_FV2_WRITE_STATUS) == 0) {\r
-    return EFI_WRITE_PROTECTED;\r
-  }\r
-\r
-  ErasePolarity = FvDevice->ErasePolarity;\r
-\r
-  //\r
-  // Loop for all files\r
-  //\r
-  NumDelete = 0;\r
-  for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r
-\r
-    if ((FileData[Index1].BufferSize + sizeof (EFI_FFS_FILE_HEADER) > 0x00FFFFFF) && !FvDevice->IsFfs3Fv) {\r
-      //\r
-      // Found a file needs a FFS3 formatted file to store it, but it is in a non-FFS3 formatted FV.\r
-      //\r
-      DEBUG ((EFI_D_ERROR, "FFS3 formatted file can't be written in a non-FFS3 formatted FV.\n"));\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    if (FileData[Index1].BufferSize == 0) {\r
-      //\r
-      // Here we will delete this file\r
-      //\r
-      Status = This->ReadFile (\r
-                      This,\r
-                      FileData[Index1].NameGuid,\r
-                      NULL,\r
-                      &Size,\r
-                      &FileType,\r
-                      &FileAttributes,\r
-                      &AuthenticationStatus\r
-                      );\r
-      if (!EFI_ERROR (Status)) {\r
-        NumDelete++;\r
-      } else {\r
-        return Status;\r
-      }\r
-    }\r
-\r
-    if (FileData[Index1].Type == EFI_FV_FILETYPE_FFS_PAD) {\r
-      //\r
-      // According to PI spec, on EFI_FV_FILETYPE_FFS_PAD:\r
-      // "Standard firmware file system services will not return the handle of any pad files,\r
-      // nor will they permit explicit creation of such files."\r
-      //\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-  }\r
-\r
-  if ((NumDelete != NumberOfFiles) && (NumDelete != 0)) {\r
-    //\r
-    // A delete was request with a multiple file write\r
-    //\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (NumDelete == NumberOfFiles) {\r
-    for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r
-      //\r
-      // Delete Files\r
-      //\r
-      Status = FvDeleteFile (FvDevice, FileData[Index1].NameGuid);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    }\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r
-    Status = This->ReadFile (\r
-                    This,\r
-                    FileData[Index1].NameGuid,\r
-                    NULL,\r
-                    &Size,\r
-                    &FileType,\r
-                    &FileAttributes,\r
-                    &AuthenticationStatus\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      CreateNewFile[Index1] = FALSE;\r
-    } else if (Status == EFI_NOT_FOUND) {\r
-      CreateNewFile[Index1] = TRUE;\r
-    } else {\r
-      return Status;\r
-    }\r
-    //\r
-    // Checking alignment\r
-    //\r
-    if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) {\r
-      UINT8 FFSAlignmentValue;\r
-      UINT8 FvAlignmentValue;\r
-\r
-      FFSAlignmentValue = (UINT8) (FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT);\r
-      FvAlignmentValue = (UINT8) (((UINT32) (FvAttributes & EFI_FV2_ALIGNMENT)) >> 16);\r
-\r
-      if (FFSAlignmentValue > FvAlignmentValue) {\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
-    }\r
-  }\r
-\r
-  if ((WritePolicy != EFI_FV_RELIABLE_WRITE) && (WritePolicy != EFI_FV_UNRELIABLE_WRITE)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  //\r
-  // Checking the reliable write is supported by FV\r
-  //\r
-\r
-  if ((WritePolicy == EFI_FV_RELIABLE_WRITE) && (NumberOfFiles > 1)) {\r
-    //\r
-    // Only for multiple files, reliable write is meaningful\r
-    //\r
-    Status = FvCreateMultipleFiles (\r
-              FvDevice,\r
-              NumberOfFiles,\r
-              FileData,\r
-              CreateNewFile\r
-              );\r
-\r
-    return Status;\r
-  }\r
-\r
-  for (Index1 = 0; Index1 < NumberOfFiles; Index1++) {\r
-    //\r
-    // Making Buffersize QWORD boundary, and add file tail.\r
-    //\r
-    HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
-    ActualSize = FileData[Index1].BufferSize + HeaderSize;\r
-    if (ActualSize > 0x00FFFFFF) {\r
-      HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
-      ActualSize = FileData[Index1].BufferSize + HeaderSize;\r
-    }\r
-    BufferSize  = ActualSize;\r
-\r
-    while ((BufferSize & 0x07) != 0) {\r
-      BufferSize++;\r
-    }\r
-\r
-    FileBuffer = AllocateZeroPool (BufferSize);\r
-    if (FileBuffer == NULL) {\r
-      return Status;\r
-    }\r
-    //\r
-    // Copy File Data into FileBuffer\r
-    //\r
-    CopyMem (\r
-      FileBuffer + HeaderSize,\r
-      FileData[Index1].Buffer,\r
-      FileData[Index1].BufferSize\r
-      );\r
-\r
-    if (ErasePolarity == 1) {\r
-      //\r
-      // Fill the file header and padding byte with Erase Byte\r
-      //\r
-      for (Index2 = 0; Index2 < HeaderSize; Index2++) {\r
-        FileBuffer[Index2] = (UINT8)~FileBuffer[Index2];\r
-      }\r
-\r
-      for (Index2 = ActualSize; Index2 < BufferSize; Index2++) {\r
-        FileBuffer[Index2] = (UINT8)~FileBuffer[Index2];\r
-      }\r
-    }\r
-\r
-    if (CreateNewFile[Index1]) {\r
-      Status = FvCreateNewFile (\r
-                FvDevice,\r
-                FileBuffer,\r
-                BufferSize,\r
-                ActualSize,\r
-                FileData[Index1].NameGuid,\r
-                FileData[Index1].Type,\r
-                FileData[Index1].FileAttributes\r
-                );\r
-    } else {\r
-      Status = FvUpdateFile (\r
-                FvDevice,\r
-                FileBuffer,\r
-                BufferSize,\r
-                ActualSize,\r
-                FileData[Index1].NameGuid,\r
-                FileData[Index1].Type,\r
-                FileData[Index1].FileAttributes\r
-                );\r
-    }\r
-\r
-    FreePool (FileBuffer);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r