Home | History | Annotate | Download | only in FwVolDxe
      1 /** @file
      2   Implements functions to pad firmware file.
      3 
      4   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions
      8   of the BSD License which accompanies this distribution.  The
      9   full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "FwVolDriver.h"
     18 
     19 /**
     20   Calculate the checksum for a PAD file.
     21 
     22   @param PadFileHeader   The Pad File to be caculeted the checksum.
     23 
     24 **/
     25 VOID
     26 SetPadFileChecksum (
     27   IN EFI_FFS_FILE_HEADER *PadFileHeader
     28   )
     29 {
     30   if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
     31 
     32     if (IS_FFS_FILE2 (PadFileHeader)) {
     33       //
     34       // Calculate checksum of Pad File Data
     35       //
     36       PadFileHeader->IntegrityCheck.Checksum.File =
     37         CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2));
     38 
     39       } else {
     40       //
     41       // Calculate checksum of Pad File Data
     42       //
     43       PadFileHeader->IntegrityCheck.Checksum.File =
     44         CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER));
     45     }
     46 
     47   } else {
     48 
     49     PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
     50 
     51   }
     52 
     53   return ;
     54 }
     55 
     56 /**
     57   Create a PAD File in the Free Space.
     58 
     59   @param FvDevice        Firmware Volume Device.
     60   @param FreeSpaceEntry  Indicating in which Free Space(Cache) the Pad file will be inserted.
     61   @param Size            Pad file Size, not include the header.
     62   @param PadFileEntry    The Ffs File Entry that points to this Pad File.
     63 
     64   @retval EFI_SUCCESS            Successfully create a PAD file.
     65   @retval EFI_OUT_OF_RESOURCES   No enough free space to create a PAD file.
     66   @retval EFI_INVALID_PARAMETER  Size is not 8 byte alignment.
     67   @retval EFI_DEVICE_ERROR       Free space is not erased.
     68 **/
     69 EFI_STATUS
     70 FvCreatePadFileInFreeSpace (
     71   IN  FV_DEVICE           *FvDevice,
     72   IN  FREE_SPACE_ENTRY    *FreeSpaceEntry,
     73   IN  UINTN               Size,
     74   OUT FFS_FILE_LIST_ENTRY **PadFileEntry
     75   )
     76 {
     77   EFI_STATUS                          Status;
     78   EFI_FFS_FILE_HEADER                 *PadFileHeader;
     79   UINTN                               Offset;
     80   UINTN                               NumBytesWritten;
     81   UINTN                               StateOffset;
     82   UINT8                               *StartPos;
     83   FFS_FILE_LIST_ENTRY                 *FfsFileEntry;
     84   UINTN                               HeaderSize;
     85   UINTN                               FileSize;
     86 
     87   HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
     88   FileSize = Size + HeaderSize;
     89   if (FileSize > 0x00FFFFFF) {
     90     HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
     91     FileSize = Size + HeaderSize;
     92   }
     93 
     94   if (FreeSpaceEntry->Length < FileSize) {
     95     return EFI_OUT_OF_RESOURCES;
     96   }
     97 
     98   if ((Size & 0x07) != 0) {
     99     return EFI_INVALID_PARAMETER;
    100   }
    101 
    102   StartPos = FreeSpaceEntry->StartingAddress;
    103 
    104   //
    105   // First double check the space
    106   //
    107   if (!IsBufferErased (
    108         FvDevice->ErasePolarity,
    109         StartPos,
    110         FileSize
    111         )) {
    112     return EFI_DEVICE_ERROR;
    113   }
    114 
    115   PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
    116 
    117   //
    118   // Create File Step 1
    119   //
    120   SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
    121 
    122   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    123   StateOffset     = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
    124 
    125   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
    126   Status = FvcWrite (
    127             FvDevice,
    128             StateOffset,
    129             &NumBytesWritten,
    130             &PadFileHeader->State
    131             );
    132   if (EFI_ERROR (Status)) {
    133     SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
    134     return Status;
    135   }
    136   //
    137   // Update Free Space Entry, since header is allocated
    138   //
    139   FreeSpaceEntry->Length -= HeaderSize;
    140   FreeSpaceEntry->StartingAddress += HeaderSize;
    141 
    142   //
    143   // Fill File Name Guid, here we assign a NULL-GUID to Pad files
    144   //
    145   ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
    146 
    147   //
    148   // Fill File Type, checksum(0), Attributes(0), Size
    149   //
    150   PadFileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;
    151   PadFileHeader->Attributes = 0;
    152   if ((FileSize) > 0x00FFFFFF) {
    153     ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) FileSize;
    154     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    155     PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
    156   } else {
    157     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    158     *(UINT32 *) PadFileHeader->Size |= FileSize;
    159   }
    160 
    161   SetHeaderChecksum (PadFileHeader);
    162   SetPadFileChecksum (PadFileHeader);
    163 
    164   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    165 
    166   NumBytesWritten = HeaderSize;
    167   Status = FvcWrite (
    168             FvDevice,
    169             Offset,
    170             &NumBytesWritten,
    171             (UINT8 *) PadFileHeader
    172             );
    173   if (EFI_ERROR (Status)) {
    174     return Status;
    175   }
    176 
    177   //
    178   // Step 2, then Mark header valid, since no data write,
    179   // mark the data valid at the same time.
    180   //
    181   SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
    182   SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
    183 
    184   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    185   StateOffset     = Offset + (UINT8 *) &PadFileHeader->State - (UINT8 *) PadFileHeader;
    186 
    187   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
    188   Status = FvcWrite (
    189             FvDevice,
    190             StateOffset,
    191             &NumBytesWritten,
    192             &PadFileHeader->State
    193             );
    194   if (EFI_ERROR (Status)) {
    195     SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
    196     SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
    197     return Status;
    198   }
    199   //
    200   // Update Free Space Entry, since header is allocated
    201   //
    202   FreeSpaceEntry->Length -= Size;
    203   FreeSpaceEntry->StartingAddress += Size;
    204 
    205   //
    206   // If successfully, insert an FfsFileEntry at the end of ffs file list
    207   //
    208   FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
    209   ASSERT (FfsFileEntry != NULL);
    210 
    211   FfsFileEntry->FfsHeader = (UINT8 *) (UINTN) StartPos;
    212   InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
    213 
    214   *PadFileEntry             = FfsFileEntry;
    215   FvDevice->CurrentFfsFile  = FfsFileEntry;
    216 
    217   return EFI_SUCCESS;
    218 }
    219 
    220 /**
    221   Fill pad file header within firmware cache.
    222 
    223   @param PadFileHeader    The start of the Pad File Buffer.
    224   @param PadFileLength    The length of the pad file including the header.
    225 
    226 **/
    227 VOID
    228 FvFillPadFile (
    229   IN EFI_FFS_FILE_HEADER  *PadFileHeader,
    230   IN UINTN                PadFileLength
    231   )
    232 {
    233   //
    234   // Fill File Name Guid, here we assign a NULL-GUID to Pad files
    235   //
    236   ZeroMem (&PadFileHeader->Name, sizeof (EFI_GUID));
    237 
    238   //
    239   // Fill File Type, checksum(0), Attributes(0), Size
    240   //
    241   PadFileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;
    242   PadFileHeader->Attributes = 0;
    243   if (PadFileLength > 0x00FFFFFF) {
    244     ((EFI_FFS_FILE_HEADER2 *) PadFileHeader)->ExtendedSize = (UINT32) PadFileLength;
    245     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    246     PadFileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
    247   } else {
    248     *(UINT32 *) PadFileHeader->Size &= 0xFF000000;
    249     *(UINT32 *) PadFileHeader->Size |= PadFileLength;
    250   }
    251 
    252   SetHeaderChecksum (PadFileHeader);
    253   SetPadFileChecksum (PadFileHeader);
    254 
    255   //
    256   // Set File State to 0x00000111
    257   //
    258   SetFileState (EFI_FILE_HEADER_CONSTRUCTION, PadFileHeader);
    259   SetFileState (EFI_FILE_HEADER_VALID, PadFileHeader);
    260   SetFileState (EFI_FILE_DATA_VALID, PadFileHeader);
    261 
    262   return ;
    263 }
    264 
    265 /**
    266   Create entire FFS file.
    267 
    268   @param FileHeader      Starting Address of a Buffer that hold the FFS File image.
    269   @param FfsFileBuffer   The source buffer that contains the File Data.
    270   @param BufferSize      The length of FfsFileBuffer.
    271   @param ActualFileSize  Size of FFS file.
    272   @param FileName        The Guid of Ffs File.
    273   @param FileType        The type of the written Ffs File.
    274   @param FileAttributes  The attributes of the written Ffs File.
    275 
    276   @retval EFI_INVALID_PARAMETER  File type is not valid.
    277   @retval EFI_SUCCESS            FFS file is successfully created.
    278 
    279 **/
    280 EFI_STATUS
    281 FvFillFfsFile (
    282   OUT EFI_FFS_FILE_HEADER   *FileHeader,
    283   IN UINT8                  *FfsFileBuffer,
    284   IN UINTN                  BufferSize,
    285   IN UINTN                  ActualFileSize,
    286   IN EFI_GUID               *FileName,
    287   IN EFI_FV_FILETYPE        FileType,
    288   IN EFI_FV_FILE_ATTRIBUTES FileAttributes
    289   )
    290 {
    291   EFI_FFS_FILE_ATTRIBUTES TmpFileAttribute;
    292   EFI_FFS_FILE_HEADER     *TmpFileHeader;
    293 
    294   //
    295   // File Type value 0x0E~0xE0 are reserved
    296   //
    297   if ((FileType > EFI_FV_FILETYPE_SMM_CORE) && (FileType < 0xE0)) {
    298     return EFI_INVALID_PARAMETER;
    299   }
    300 
    301   TmpFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileBuffer;
    302   //
    303   // First fill all fields ready in FfsFileBuffer
    304   //
    305   CopyGuid (&TmpFileHeader->Name, FileName);
    306   TmpFileHeader->Type = FileType;
    307 
    308   //
    309   // Convert the FileAttributes to FFSFileAttributes
    310   //
    311   FvFileAttrib2FfsFileAttrib (FileAttributes, &TmpFileAttribute);
    312 
    313   TmpFileHeader->Attributes = TmpFileAttribute;
    314 
    315   if (ActualFileSize > 0x00FFFFFF) {
    316     ((EFI_FFS_FILE_HEADER2 *) FileHeader)->ExtendedSize = (UINT32) ActualFileSize;
    317     *(UINT32 *) FileHeader->Size &= 0xFF000000;
    318     FileHeader->Attributes |= FFS_ATTRIB_LARGE_FILE;
    319   } else {
    320     *(UINT32 *) FileHeader->Size &= 0xFF000000;
    321     *(UINT32 *) FileHeader->Size |= ActualFileSize;
    322   }
    323 
    324   SetHeaderChecksum (TmpFileHeader);
    325   SetFileChecksum (TmpFileHeader, ActualFileSize);
    326 
    327   SetFileState (EFI_FILE_HEADER_CONSTRUCTION, TmpFileHeader);
    328   SetFileState (EFI_FILE_HEADER_VALID, TmpFileHeader);
    329   SetFileState (EFI_FILE_DATA_VALID, TmpFileHeader);
    330 
    331   //
    332   // Copy data from FfsFileBuffer to FileHeader(cache)
    333   //
    334   CopyMem (FileHeader, FfsFileBuffer, BufferSize);
    335 
    336   return EFI_SUCCESS;
    337 }
    338 
    339 /**
    340   Fill some other extra space using 0xFF(Erase Value).
    341 
    342   @param  ErasePolarity  Fv erase value.
    343   @param  FileHeader     Point to the start of FFS File.
    344   @param  ExtraLength    The pading length.
    345 
    346 **/
    347 VOID
    348 FvAdjustFfsFile (
    349   IN  UINT8                 ErasePolarity,
    350   IN  EFI_FFS_FILE_HEADER   *FileHeader,
    351   IN  UINTN                 ExtraLength
    352   )
    353 {
    354   UINT8 *Ptr;
    355   UINT8 PadingByte;
    356 
    357   if (IS_FFS_FILE2 (FileHeader)) {
    358     Ptr         = (UINT8 *) FileHeader + FFS_FILE2_SIZE (FileHeader);
    359   } else {
    360     Ptr         = (UINT8 *) FileHeader + FFS_FILE_SIZE (FileHeader);
    361   }
    362 
    363   if (ErasePolarity == 0) {
    364     PadingByte = 0;
    365   } else {
    366     PadingByte = 0xFF;
    367   }
    368   //
    369   // Fill the non-used space with Padding Byte
    370   //
    371   SetMem (Ptr, ExtraLength, PadingByte);
    372 
    373   return ;
    374 }
    375 
    376 /**
    377   Free File List entry pointed by FileListHead.
    378 
    379   @param FileListHeader   FileListEntry Header.
    380 
    381 **/
    382 VOID
    383 FreeFileList (
    384   IN  LIST_ENTRY  *FileListHead
    385   )
    386 {
    387   FFS_FILE_LIST_ENTRY *FfsFileEntry;
    388   LIST_ENTRY      *NextEntry;
    389 
    390   FfsFileEntry = (FFS_FILE_LIST_ENTRY *) (FileListHead->ForwardLink);
    391 
    392   //
    393   // Loop the whole list entry to free resources
    394   //
    395   while (&FfsFileEntry->Link != FileListHead) {
    396     NextEntry = (&FfsFileEntry->Link)->ForwardLink;
    397     FreePool (FfsFileEntry);
    398     FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
    399   }
    400 
    401   return ;
    402 }
    403 
    404 /**
    405   Create a new file within a PAD file area.
    406 
    407   @param FvDevice        Firmware Volume Device.
    408   @param FfsFileBuffer   A buffer that holds an FFS file,(it contains a File Header which is in init state).
    409   @param BufferSize      The size of FfsFileBuffer.
    410   @param ActualFileSize  The actual file length, it may not be multiples of 8.
    411   @param FileName        The FFS File Name.
    412   @param FileType        The FFS File Type.
    413   @param FileAttributes  The Attributes of the FFS File to be created.
    414 
    415   @retval EFI_SUCCESS           Successfully create a new file within the found PAD file area.
    416   @retval EFI_OUT_OF_RESOURCES  No suitable PAD file is found.
    417   @retval other errors          New file is created failed.
    418 
    419 **/
    420 EFI_STATUS
    421 FvCreateNewFileInsidePadFile (
    422   IN  FV_DEVICE               *FvDevice,
    423   IN  UINT8                   *FfsFileBuffer,
    424   IN  UINTN                   BufferSize,
    425   IN  UINTN                   ActualFileSize,
    426   IN  EFI_GUID                *FileName,
    427   IN  EFI_FV_FILETYPE         FileType,
    428   IN  EFI_FV_FILE_ATTRIBUTES  FileAttributes
    429   )
    430 {
    431   UINTN                               RequiredAlignment;
    432   FFS_FILE_LIST_ENTRY                 *PadFileEntry;
    433   EFI_STATUS                          Status;
    434   UINTN                               PadAreaLength;
    435   UINTN                               PadSize;
    436   EFI_FFS_FILE_HEADER                 *FileHeader;
    437   EFI_FFS_FILE_HEADER                 *OldPadFileHeader;
    438   EFI_FFS_FILE_HEADER                 *PadFileHeader;
    439   EFI_FFS_FILE_HEADER                 *TailPadFileHeader;
    440   UINTN                               StateOffset;
    441   UINTN                               Offset;
    442   UINTN                               NumBytesWritten;
    443   UINT8                               *StartPos;
    444   LIST_ENTRY                          NewFileList;
    445   FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
    446   FFS_FILE_LIST_ENTRY                 *FfsEntry;
    447   FFS_FILE_LIST_ENTRY                 *NextFfsEntry;
    448 
    449   //
    450   // First get the required alignment from the File Attributes
    451   //
    452   RequiredAlignment = GetRequiredAlignment (FileAttributes);
    453 
    454   //
    455   // Find a suitable PAD File
    456   //
    457   Status = FvLocatePadFile (
    458             FvDevice,
    459             BufferSize,
    460             RequiredAlignment,
    461             &PadSize,
    462             &PadFileEntry
    463             );
    464 
    465   if (EFI_ERROR (Status)) {
    466     return EFI_OUT_OF_RESOURCES;
    467   }
    468 
    469   OldPadFileHeader = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
    470 
    471   //
    472   // Step 1: Update Pad File Header
    473   //
    474   SetFileState (EFI_FILE_MARKED_FOR_UPDATE, OldPadFileHeader);
    475 
    476   StartPos = PadFileEntry->FfsHeader;
    477 
    478   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    479   StateOffset     = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
    480 
    481   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
    482   Status = FvcWrite (
    483             FvDevice,
    484             StateOffset,
    485             &NumBytesWritten,
    486             &OldPadFileHeader->State
    487             );
    488   if (EFI_ERROR (Status)) {
    489     SetFileState (EFI_FILE_HEADER_CONSTRUCTION, OldPadFileHeader);
    490     return Status;
    491   }
    492 
    493   //
    494   // Step 2: Update Pad area
    495   //
    496   InitializeListHead (&NewFileList);
    497 
    498   if (IS_FFS_FILE2 (OldPadFileHeader)) {
    499     PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
    500     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
    501   } else {
    502     PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
    503     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
    504   }
    505 
    506   if (PadSize != 0) {
    507     //
    508     // Insert a PAD file before to achieve required alignment
    509     //
    510     FvFillPadFile (PadFileHeader, PadSize);
    511     NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    512     ASSERT (NewFileListEntry   != NULL);
    513     NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
    514     InsertTailList (&NewFileList, &NewFileListEntry->Link);
    515   }
    516 
    517   FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize);
    518 
    519   Status = FvFillFfsFile (
    520             FileHeader,
    521             FfsFileBuffer,
    522             BufferSize,
    523             ActualFileSize,
    524             FileName,
    525             FileType,
    526             FileAttributes
    527             );
    528   if (EFI_ERROR (Status)) {
    529     FreeFileList (&NewFileList);
    530     return Status;
    531   }
    532 
    533   NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    534   ASSERT (NewFileListEntry   != NULL);
    535 
    536   NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
    537   InsertTailList (&NewFileList, &NewFileListEntry->Link);
    538 
    539   FvDevice->CurrentFfsFile = NewFileListEntry;
    540 
    541   if (PadAreaLength > (BufferSize + PadSize)) {
    542     if ((PadAreaLength - BufferSize - PadSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
    543       //
    544       // we can insert another PAD file
    545       //
    546       TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize);
    547       FvFillPadFile (TailPadFileHeader, PadAreaLength - BufferSize - PadSize);
    548 
    549       NewFileListEntry            = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    550       ASSERT (NewFileListEntry   != NULL);
    551 
    552       NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
    553       InsertTailList (&NewFileList, &NewFileListEntry->Link);
    554     } else {
    555       //
    556       // because left size cannot hold another PAD file header,
    557       // adjust the writing file size (just in cache)
    558       //
    559       FvAdjustFfsFile (
    560         FvDevice->ErasePolarity,
    561         FileHeader,
    562         PadAreaLength - BufferSize - PadSize
    563         );
    564     }
    565   }
    566   //
    567   // Start writing to FV
    568   //
    569   if (IS_FFS_FILE2 (OldPadFileHeader)) {
    570     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
    571   } else {
    572     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
    573   }
    574 
    575   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    576 
    577   NumBytesWritten = PadAreaLength;
    578   Status = FvcWrite (
    579             FvDevice,
    580             Offset,
    581             &NumBytesWritten,
    582             StartPos
    583             );
    584   if (EFI_ERROR (Status)) {
    585     FreeFileList (&NewFileList);
    586     FvDevice->CurrentFfsFile = NULL;
    587     return Status;
    588   }
    589 
    590   //
    591   // Step 3: Mark Pad file header as EFI_FILE_HEADER_INVALID
    592   //
    593   SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
    594 
    595   StartPos = PadFileEntry->FfsHeader;
    596 
    597   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    598   StateOffset     = Offset + (UINT8 *) &OldPadFileHeader->State - (UINT8 *) OldPadFileHeader;
    599 
    600   NumBytesWritten = sizeof (EFI_FFS_FILE_STATE);
    601   Status = FvcWrite (
    602             FvDevice,
    603             StateOffset,
    604             &NumBytesWritten,
    605             &OldPadFileHeader->State
    606             );
    607   if (EFI_ERROR (Status)) {
    608     SetFileState (EFI_FILE_HEADER_INVALID, OldPadFileHeader);
    609     FreeFileList (&NewFileList);
    610     FvDevice->CurrentFfsFile = NULL;
    611     return Status;
    612   }
    613 
    614   //
    615   // If all successfully, update FFS_FILE_LIST
    616   //
    617 
    618   //
    619   // Delete old pad file entry
    620   //
    621   FfsEntry      = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
    622   NextFfsEntry  = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
    623 
    624   FreePool (PadFileEntry);
    625 
    626   FfsEntry->Link.ForwardLink          = NewFileList.ForwardLink;
    627   (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
    628   NextFfsEntry->Link.BackLink         = NewFileList.BackLink;
    629   (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
    630 
    631   return EFI_SUCCESS;
    632 }
    633 
    634 /**
    635   Free all FfsBuffer.
    636 
    637   @param NumOfFiles      Number of FfsBuffer.
    638   @param FfsBuffer       An array of pointer to an FFS File Buffer
    639 
    640 **/
    641 VOID
    642 FreeFfsBuffer (
    643   IN UINTN    NumOfFiles,
    644   IN UINT8    **FfsBuffer
    645   )
    646 {
    647   UINTN Index;
    648   for (Index = 0; Index < NumOfFiles; Index++) {
    649     if (FfsBuffer[Index] != NULL) {
    650       FreePool (FfsBuffer[Index]);
    651     }
    652   }
    653 }
    654 
    655 /**
    656   Create multiple files within a PAD File area.
    657 
    658   @param FvDevice        Firmware Volume Device.
    659   @param PadFileEntry    The pad file entry to be written in.
    660   @param NumOfFiles      Total File number to be written.
    661   @param BufferSize      The array of buffer size of each FfsBuffer.
    662   @param ActualFileSize  The array of actual file size.
    663   @param PadSize         The array of leading pad file size for each FFS File
    664   @param FfsBuffer       The array of Ffs Buffer pointer.
    665   @param FileData        The array of EFI_FV_WRITE_FILE_DATA structure,
    666                          used to get name, attributes, type, etc.
    667 
    668   @retval EFI_SUCCESS           Add the input multiple files into PAD file area.
    669   @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
    670   @retval other error           Files can't be added into PAD file area.
    671 
    672 **/
    673 EFI_STATUS
    674 FvCreateMultipleFilesInsidePadFile (
    675   IN FV_DEVICE              *FvDevice,
    676   IN FFS_FILE_LIST_ENTRY    *PadFileEntry,
    677   IN UINTN                  NumOfFiles,
    678   IN UINTN                  *BufferSize,
    679   IN UINTN                  *ActualFileSize,
    680   IN UINTN                  *PadSize,
    681   IN UINT8                  **FfsBuffer,
    682   IN EFI_FV_WRITE_FILE_DATA *FileData
    683   )
    684 {
    685   EFI_STATUS                          Status;
    686   EFI_FFS_FILE_HEADER                 *OldPadFileHeader;
    687   UINTN                               Index;
    688   EFI_FFS_FILE_HEADER                 *PadFileHeader;
    689   EFI_FFS_FILE_HEADER                 *FileHeader;
    690   EFI_FFS_FILE_HEADER                 *TailPadFileHeader;
    691   UINTN                               TotalSize;
    692   UINTN                               PadAreaLength;
    693   LIST_ENTRY                          NewFileList;
    694   FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
    695   UINTN                               Offset;
    696   UINTN                               NumBytesWritten;
    697   UINT8                               *StartPos;
    698   FFS_FILE_LIST_ENTRY                 *FfsEntry;
    699   FFS_FILE_LIST_ENTRY                 *NextFfsEntry;
    700 
    701   InitializeListHead (&NewFileList);
    702 
    703   NewFileListEntry  = NULL;
    704 
    705   OldPadFileHeader  = (EFI_FFS_FILE_HEADER *) PadFileEntry->FfsHeader;
    706   if (IS_FFS_FILE2 (OldPadFileHeader)) {
    707     PadAreaLength = FFS_FILE2_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
    708   } else {
    709     PadAreaLength = FFS_FILE_SIZE (OldPadFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
    710   }
    711 
    712   Status = UpdateHeaderBit (
    713             FvDevice,
    714             OldPadFileHeader,
    715             EFI_FILE_MARKED_FOR_UPDATE
    716             );
    717   if (EFI_ERROR (Status)) {
    718     return Status;
    719   }
    720   //
    721   // Update PAD area
    722   //
    723   TotalSize     = 0;
    724   if (IS_FFS_FILE2 (OldPadFileHeader)) {
    725     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
    726   } else {
    727     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER));
    728   }
    729   FileHeader    = PadFileHeader;
    730 
    731   for (Index = 0; Index < NumOfFiles; Index++) {
    732     if (PadSize[Index] != 0) {
    733       FvFillPadFile (PadFileHeader, PadSize[Index]);
    734       NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    735       if (NewFileListEntry == NULL) {
    736         FreeFileList (&NewFileList);
    737         return EFI_OUT_OF_RESOURCES;
    738       }
    739 
    740       NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
    741       InsertTailList (&NewFileList, &NewFileListEntry->Link);
    742     }
    743 
    744     FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
    745     Status = FvFillFfsFile (
    746               FileHeader,
    747               FfsBuffer[Index],
    748               BufferSize[Index],
    749               ActualFileSize[Index],
    750               FileData[Index].NameGuid,
    751               FileData[Index].Type,
    752               FileData[Index].FileAttributes
    753               );
    754     if (EFI_ERROR (Status)) {
    755       FreeFileList (&NewFileList);
    756       return Status;
    757     }
    758 
    759     NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    760     if (NewFileListEntry == NULL) {
    761       FreeFileList (&NewFileList);
    762       return EFI_OUT_OF_RESOURCES;
    763     }
    764 
    765     NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
    766     InsertTailList (&NewFileList, &NewFileListEntry->Link);
    767 
    768     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
    769     TotalSize += PadSize[Index];
    770     TotalSize += BufferSize[Index];
    771   }
    772 
    773   FvDevice->CurrentFfsFile = NewFileListEntry;
    774   //
    775   // Maybe we need a tail pad file
    776   //
    777   if (PadAreaLength > TotalSize) {
    778     if ((PadAreaLength - TotalSize) >= sizeof (EFI_FFS_FILE_HEADER)) {
    779       //
    780       // we can insert another PAD file
    781       //
    782       TailPadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[NumOfFiles - 1]);
    783       FvFillPadFile (TailPadFileHeader, PadAreaLength - TotalSize);
    784 
    785       NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    786       if (NewFileListEntry == NULL) {
    787         FreeFileList (&NewFileList);
    788         FvDevice->CurrentFfsFile = NULL;
    789         return EFI_OUT_OF_RESOURCES;
    790       }
    791 
    792       NewFileListEntry->FfsHeader = (UINT8 *) TailPadFileHeader;
    793       InsertTailList (&NewFileList, &NewFileListEntry->Link);
    794     } else {
    795       //
    796       // because left size cannot hold another PAD file header,
    797       // adjust the writing file size (just in cache)
    798       //
    799       FvAdjustFfsFile (
    800         FvDevice->ErasePolarity,
    801         FileHeader,
    802         PadAreaLength - TotalSize
    803         );
    804     }
    805   }
    806   //
    807   // Start writing to FV
    808   //
    809   if (IS_FFS_FILE2 (OldPadFileHeader)) {
    810     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER2);
    811   } else {
    812     StartPos = (UINT8 *) OldPadFileHeader + sizeof (EFI_FFS_FILE_HEADER);
    813   }
    814 
    815   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    816 
    817   NumBytesWritten = PadAreaLength;
    818   Status = FvcWrite (
    819             FvDevice,
    820             Offset,
    821             &NumBytesWritten,
    822             StartPos
    823             );
    824   if (EFI_ERROR (Status)) {
    825     FreeFileList (&NewFileList);
    826     FvDevice->CurrentFfsFile = NULL;
    827     return Status;
    828   }
    829 
    830   Status = UpdateHeaderBit (
    831             FvDevice,
    832             OldPadFileHeader,
    833             EFI_FILE_HEADER_INVALID
    834             );
    835   if (EFI_ERROR (Status)) {
    836     FreeFileList (&NewFileList);
    837     FvDevice->CurrentFfsFile = NULL;
    838     return Status;
    839   }
    840 
    841   //
    842   // Update File List Link
    843   //
    844 
    845   //
    846   // First delete old pad file entry
    847   //
    848   FfsEntry      = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.BackLink;
    849   NextFfsEntry  = (FFS_FILE_LIST_ENTRY *) PadFileEntry->Link.ForwardLink;
    850 
    851   FreePool (PadFileEntry);
    852 
    853   FfsEntry->Link.ForwardLink          = NewFileList.ForwardLink;
    854   (NewFileList.ForwardLink)->BackLink = &FfsEntry->Link;
    855   NextFfsEntry->Link.BackLink         = NewFileList.BackLink;
    856   (NewFileList.BackLink)->ForwardLink = &NextFfsEntry->Link;
    857 
    858   return EFI_SUCCESS;
    859 }
    860 
    861 /**
    862   Create multiple files within the Free Space.
    863 
    864   @param FvDevice        Firmware Volume Device.
    865   @param FreeSpaceEntry  Indicating in which Free Space(Cache) the multiple files will be inserted.
    866   @param NumOfFiles      Total File number to be written.
    867   @param BufferSize      The array of buffer size of each FfsBuffer.
    868   @param ActualFileSize  The array of actual file size.
    869   @param PadSize         The array of leading pad file size for each FFS File
    870   @param FfsBuffer       The array of Ffs Buffer pointer.
    871   @param FileData        The array of EFI_FV_WRITE_FILE_DATA structure,
    872                          used to get name, attributes, type, etc.
    873 
    874   @retval EFI_SUCCESS           Add the input multiple files into PAD file area.
    875   @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
    876   @retval other error           Files can't be added into PAD file area.
    877 
    878 **/
    879 EFI_STATUS
    880 FvCreateMultipleFilesInsideFreeSpace (
    881   IN FV_DEVICE              *FvDevice,
    882   IN FREE_SPACE_ENTRY       *FreeSpaceEntry,
    883   IN UINTN                  NumOfFiles,
    884   IN UINTN                  *BufferSize,
    885   IN UINTN                  *ActualFileSize,
    886   IN UINTN                  *PadSize,
    887   IN UINT8                  **FfsBuffer,
    888   IN EFI_FV_WRITE_FILE_DATA *FileData
    889   )
    890 {
    891   EFI_STATUS                          Status;
    892   UINTN                               Index;
    893   EFI_FFS_FILE_HEADER                 *PadFileHeader;
    894   EFI_FFS_FILE_HEADER                 *FileHeader;
    895   UINTN                               TotalSize;
    896   LIST_ENTRY                          NewFileList;
    897   FFS_FILE_LIST_ENTRY                 *NewFileListEntry;
    898   UINTN                               Offset;
    899   UINTN                               NumBytesWritten;
    900   UINT8                               *StartPos;
    901 
    902   InitializeListHead (&NewFileList);
    903 
    904   NewFileListEntry  = NULL;
    905 
    906   TotalSize     = 0;
    907   StartPos      = FreeSpaceEntry->StartingAddress;
    908   PadFileHeader = (EFI_FFS_FILE_HEADER *) StartPos;
    909   FileHeader    = PadFileHeader;
    910 
    911   for (Index = 0; Index < NumOfFiles; Index++) {
    912     if (PadSize[Index] != 0) {
    913       FvFillPadFile (PadFileHeader, PadSize[Index]);
    914       NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    915       if (NewFileListEntry == NULL) {
    916         FreeFileList (&NewFileList);
    917         return EFI_OUT_OF_RESOURCES;
    918       }
    919 
    920       NewFileListEntry->FfsHeader = (UINT8 *) PadFileHeader;
    921       InsertTailList (&NewFileList, &NewFileListEntry->Link);
    922     }
    923 
    924     FileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) PadFileHeader + PadSize[Index]);
    925     Status = FvFillFfsFile (
    926               FileHeader,
    927               FfsBuffer[Index],
    928               BufferSize[Index],
    929               ActualFileSize[Index],
    930               FileData[Index].NameGuid,
    931               FileData[Index].Type,
    932               FileData[Index].FileAttributes
    933               );
    934     if (EFI_ERROR (Status)) {
    935       FreeFileList (&NewFileList);
    936       return Status;
    937     }
    938 
    939     NewFileListEntry = AllocatePool (sizeof (FFS_FILE_LIST_ENTRY));
    940     if (NewFileListEntry == NULL) {
    941       FreeFileList (&NewFileList);
    942       return EFI_OUT_OF_RESOURCES;
    943     }
    944 
    945     NewFileListEntry->FfsHeader = (UINT8 *) FileHeader;
    946     InsertTailList (&NewFileList, &NewFileListEntry->Link);
    947 
    948     PadFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FileHeader + BufferSize[Index]);
    949     TotalSize += PadSize[Index];
    950     TotalSize += BufferSize[Index];
    951   }
    952 
    953   if (FreeSpaceEntry->Length < TotalSize) {
    954     FreeFileList (&NewFileList);
    955     return EFI_OUT_OF_RESOURCES;
    956   }
    957 
    958   FvDevice->CurrentFfsFile = NewFileListEntry;
    959 
    960   //
    961   // Start writing to FV
    962   //
    963   Offset          = (UINTN) (StartPos - FvDevice->CachedFv);
    964 
    965   NumBytesWritten = TotalSize;
    966   Status = FvcWrite (
    967             FvDevice,
    968             Offset,
    969             &NumBytesWritten,
    970             StartPos
    971             );
    972   if (EFI_ERROR (Status)) {
    973     FreeFileList (&NewFileList);
    974     FvDevice->CurrentFfsFile = NULL;
    975     return Status;
    976   }
    977 
    978   FreeSpaceEntry->Length -= TotalSize;
    979   FreeSpaceEntry->StartingAddress += TotalSize;
    980 
    981   NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileList.ForwardLink);
    982 
    983   while (NewFileListEntry != (FFS_FILE_LIST_ENTRY *) &NewFileList) {
    984     InsertTailList (&FvDevice->FfsFileListHeader, &NewFileListEntry->Link);
    985     NewFileListEntry = (FFS_FILE_LIST_ENTRY *) (NewFileListEntry->Link.ForwardLink);
    986   }
    987 
    988   return EFI_SUCCESS;
    989 }
    990 
    991 /**
    992   Write multiple files into FV in reliable method.
    993 
    994   @param FvDevice        Firmware Volume Device.
    995   @param NumOfFiles      Total File number to be written.
    996   @param FileData        The array of EFI_FV_WRITE_FILE_DATA structure,
    997                          used to get name, attributes, type, etc
    998   @param FileOperation   The array of operation for each file.
    999 
   1000   @retval EFI_SUCCESS            Files are added into FV.
   1001   @retval EFI_OUT_OF_RESOURCES   No enough free PAD files to add the input files.
   1002   @retval EFI_INVALID_PARAMETER  File number is less than or equal to 1.
   1003   @retval EFI_UNSUPPORTED        File number exceeds the supported max numbers of files.
   1004 
   1005 **/
   1006 EFI_STATUS
   1007 FvCreateMultipleFiles (
   1008   IN  FV_DEVICE               *FvDevice,
   1009   IN  UINTN                   NumOfFiles,
   1010   IN  EFI_FV_WRITE_FILE_DATA  *FileData,
   1011   IN  BOOLEAN                 *FileOperation
   1012   )
   1013 {
   1014   EFI_STATUS                    Status;
   1015   UINT8                         *FfsBuffer[MAX_FILES];
   1016   UINTN                         Index1;
   1017   UINTN                         Index2;
   1018   UINTN                         BufferSize[MAX_FILES];
   1019   UINTN                         ActualFileSize[MAX_FILES];
   1020   UINTN                         RequiredAlignment[MAX_FILES];
   1021   UINTN                         PadSize[MAX_FILES];
   1022   FFS_FILE_LIST_ENTRY           *PadFileEntry;
   1023   UINTN                         TotalSizeNeeded;
   1024   FREE_SPACE_ENTRY              *FreeSpaceEntry;
   1025   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
   1026   UINTN                         Key;
   1027   EFI_GUID                      FileNameGuid;
   1028   EFI_FV_FILETYPE               OldFileType;
   1029   EFI_FV_FILE_ATTRIBUTES        OldFileAttributes;
   1030   UINTN                         OldFileSize;
   1031   FFS_FILE_LIST_ENTRY           *OldFfsFileEntry[MAX_FILES];
   1032   EFI_FFS_FILE_HEADER           *OldFileHeader[MAX_FILES];
   1033   BOOLEAN                       IsCreateFile;
   1034   UINTN                         HeaderSize;
   1035 
   1036   //
   1037   // To use this function, we must ensure that the NumOfFiles is great
   1038   // than 1
   1039   //
   1040   if (NumOfFiles <= 1) {
   1041     return EFI_INVALID_PARAMETER;
   1042   }
   1043 
   1044   if (NumOfFiles > MAX_FILES) {
   1045     return EFI_UNSUPPORTED;
   1046   }
   1047 
   1048   Fv = &FvDevice->Fv;
   1049 
   1050   SetMem (FfsBuffer, NumOfFiles, 0);
   1051   SetMem (RequiredAlignment, NumOfFiles, 8);
   1052   SetMem (PadSize, NumOfFiles, 0);
   1053   ZeroMem (OldFfsFileEntry, sizeof (OldFfsFileEntry));
   1054   ZeroMem (OldFileHeader, sizeof (OldFileHeader));
   1055 
   1056   //
   1057   // Adjust file size
   1058   //
   1059   for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
   1060     HeaderSize = sizeof (EFI_FFS_FILE_HEADER);
   1061     ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
   1062     if (ActualFileSize[Index1] > 0x00FFFFFF) {
   1063       HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
   1064       ActualFileSize[Index1] = FileData[Index1].BufferSize + HeaderSize;
   1065     }
   1066     BufferSize[Index1]     = ActualFileSize[Index1];
   1067 
   1068     if (BufferSize[Index1] == HeaderSize) {
   1069       //
   1070       // clear file attributes, zero-length file does not have any attributes
   1071       //
   1072       FileData[Index1].FileAttributes = 0;
   1073     }
   1074 
   1075     while ((BufferSize[Index1] & 0x07) != 0) {
   1076       BufferSize[Index1]++;
   1077     }
   1078 
   1079     FfsBuffer[Index1] = AllocateZeroPool (BufferSize[Index1]);
   1080 
   1081     //
   1082     // Copy File Data into FileBuffer
   1083     //
   1084     CopyMem (
   1085       FfsBuffer[Index1] + HeaderSize,
   1086       FileData[Index1].Buffer,
   1087       FileData[Index1].BufferSize
   1088       );
   1089 
   1090     if (FvDevice->ErasePolarity == 1) {
   1091       for (Index2 = 0; Index2 < HeaderSize; Index2++) {
   1092         FfsBuffer[Index1][Index2] = (UINT8)~FfsBuffer[Index1][Index2];
   1093       }
   1094     }
   1095 
   1096     if ((FileData[Index1].FileAttributes & EFI_FV_FILE_ATTRIB_ALIGNMENT) != 0) {
   1097       RequiredAlignment[Index1] = GetRequiredAlignment (FileData[Index1].FileAttributes);
   1098     }
   1099     //
   1100     // If update file, mark the original file header to
   1101     // EFI_FILE_MARKED_FOR_UPDATE
   1102     //
   1103     IsCreateFile = FileOperation[Index1];
   1104     if (!IsCreateFile) {
   1105 
   1106       Key = 0;
   1107       do {
   1108         OldFileType = 0;
   1109         Status = Fv->GetNextFile (
   1110                       Fv,
   1111                       &Key,
   1112                       &OldFileType,
   1113                       &FileNameGuid,
   1114                       &OldFileAttributes,
   1115                       &OldFileSize
   1116                       );
   1117         if (EFI_ERROR (Status)) {
   1118           FreeFfsBuffer (NumOfFiles, FfsBuffer);
   1119           return Status;
   1120         }
   1121       } while (!CompareGuid (&FileNameGuid, FileData[Index1].NameGuid));
   1122 
   1123       //
   1124       // Get FfsFileEntry from the search key
   1125       //
   1126       OldFfsFileEntry[Index1]  = (FFS_FILE_LIST_ENTRY *) Key;
   1127       OldFileHeader[Index1]    = (EFI_FFS_FILE_HEADER *) OldFfsFileEntry[Index1]->FfsHeader;
   1128       Status = UpdateHeaderBit (
   1129                 FvDevice,
   1130                 OldFileHeader[Index1],
   1131                 EFI_FILE_MARKED_FOR_UPDATE
   1132                 );
   1133       if (EFI_ERROR (Status)) {
   1134         FreeFfsBuffer (NumOfFiles, FfsBuffer);
   1135         return Status;
   1136       }
   1137     }
   1138   }
   1139   //
   1140   // First to search a suitable pad file that can hold so
   1141   // many files
   1142   //
   1143   Status = FvSearchSuitablePadFile (
   1144             FvDevice,
   1145             NumOfFiles,
   1146             BufferSize,
   1147             RequiredAlignment,
   1148             PadSize,
   1149             &TotalSizeNeeded,
   1150             &PadFileEntry
   1151             );
   1152 
   1153   if (Status == EFI_NOT_FOUND) {
   1154     //
   1155     // Try to find a free space that can hold these files
   1156     //
   1157     Status = FvSearchSuitableFreeSpace (
   1158               FvDevice,
   1159               NumOfFiles,
   1160               BufferSize,
   1161               RequiredAlignment,
   1162               PadSize,
   1163               &TotalSizeNeeded,
   1164               &FreeSpaceEntry
   1165               );
   1166     if (EFI_ERROR (Status)) {
   1167       FreeFfsBuffer (NumOfFiles, FfsBuffer);
   1168       return EFI_OUT_OF_RESOURCES;
   1169     }
   1170     Status = FvCreateMultipleFilesInsideFreeSpace (
   1171               FvDevice,
   1172               FreeSpaceEntry,
   1173               NumOfFiles,
   1174               BufferSize,
   1175               ActualFileSize,
   1176               PadSize,
   1177               FfsBuffer,
   1178               FileData
   1179               );
   1180 
   1181   } else {
   1182     //
   1183     // Create multiple files inside such a pad file
   1184     // to achieve lock-step update
   1185     //
   1186     Status = FvCreateMultipleFilesInsidePadFile (
   1187               FvDevice,
   1188               PadFileEntry,
   1189               NumOfFiles,
   1190               BufferSize,
   1191               ActualFileSize,
   1192               PadSize,
   1193               FfsBuffer,
   1194               FileData
   1195               );
   1196   }
   1197 
   1198   FreeFfsBuffer (NumOfFiles, FfsBuffer);
   1199 
   1200   if (EFI_ERROR (Status)) {
   1201     return Status;
   1202   }
   1203   //
   1204   // Delete those updated files
   1205   //
   1206   for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
   1207     IsCreateFile = FileOperation[Index1];
   1208     if (!IsCreateFile && OldFfsFileEntry[Index1] != NULL) {
   1209       (OldFfsFileEntry[Index1]->Link.BackLink)->ForwardLink  = OldFfsFileEntry[Index1]->Link.ForwardLink;
   1210       (OldFfsFileEntry[Index1]->Link.ForwardLink)->BackLink  = OldFfsFileEntry[Index1]->Link.BackLink;
   1211       FreePool (OldFfsFileEntry[Index1]);
   1212     }
   1213   }
   1214   //
   1215   // Set those files' state to EFI_FILE_DELETED
   1216   //
   1217   for (Index1 = 0; Index1 < NumOfFiles; Index1++) {
   1218     IsCreateFile = FileOperation[Index1];
   1219     if (!IsCreateFile && OldFileHeader[Index1] != NULL) {
   1220       Status = UpdateHeaderBit (FvDevice, OldFileHeader[Index1], EFI_FILE_DELETED);
   1221       if (EFI_ERROR (Status)) {
   1222         return Status;
   1223       }
   1224     }
   1225   }
   1226 
   1227   return EFI_SUCCESS;
   1228 }
   1229