Home | History | Annotate | Download | only in Common
      1 /** @file
      2 EFI Firmware Volume routines which work on a Fv image in buffers.
      3 
      4 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "FirmwareVolumeBufferLib.h"
     16 #include "BinderFuncs.h"
     17 
     18 //
     19 // Local macros
     20 //
     21 #define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
     22     ( \
     23       (BOOLEAN) ( \
     24           (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
     25         ) \
     26     )
     27 
     28 
     29 //
     30 // Local prototypes
     31 //
     32 
     33 STATIC
     34 UINT32
     35 FvBufGetSecHdrLen(
     36    IN EFI_COMMON_SECTION_HEADER *SectionHeader
     37    )
     38 {
     39   if (SectionHeader == NULL) {
     40     return 0;
     41   }
     42   if (FvBufExpand3ByteSize(SectionHeader->Size) == 0xffffff) {
     43     return sizeof(EFI_COMMON_SECTION_HEADER2);
     44   }
     45   return sizeof(EFI_COMMON_SECTION_HEADER);
     46 }
     47 
     48 STATIC
     49 UINT32
     50 FvBufGetSecFileLen (
     51   IN EFI_COMMON_SECTION_HEADER *SectionHeader
     52   )
     53 {
     54   UINT32 Length;
     55   if (SectionHeader == NULL) {
     56     return 0;
     57   }
     58   Length = FvBufExpand3ByteSize(SectionHeader->Size);
     59   if (Length == 0xffffff) {
     60     Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
     61   }
     62   return Length;
     63 }
     64 
     65 //
     66 // Local prototypes
     67 //
     68 
     69 STATIC
     70 UINT16
     71 FvBufCalculateChecksum16 (
     72   IN UINT16       *Buffer,
     73   IN UINTN        Size
     74   );
     75 
     76 STATIC
     77 UINT8
     78 FvBufCalculateChecksum8 (
     79   IN UINT8        *Buffer,
     80   IN UINTN        Size
     81   );
     82 
     83 //
     84 // Procedures start
     85 //
     86 
     87 EFI_STATUS
     88 FvBufRemoveFileNew (
     89   IN OUT VOID *Fv,
     90   IN EFI_GUID *Name
     91   )
     92 /*++
     93 
     94 Routine Description:
     95 
     96   Clears out all files from the Fv buffer in memory
     97 
     98 Arguments:
     99 
    100   SourceFv - Address of the Fv in memory, this firmware volume volume will
    101              be modified, if SourceFfsFile exists
    102   SourceFfsFile - Input FFS file to replace
    103 
    104 Returns:
    105 
    106   EFI_SUCCESS
    107   EFI_NOT_FOUND
    108 
    109 --*/
    110 {
    111   EFI_STATUS                  Status;
    112   EFI_FFS_FILE_HEADER*        FileToRm;
    113   UINTN                       FileToRmLength;
    114 
    115   Status = FvBufFindFileByName(
    116     Fv,
    117     Name,
    118     (VOID **)&FileToRm
    119     );
    120   if (EFI_ERROR (Status)) {
    121     return Status;
    122   }
    123 
    124   FileToRmLength = FvBufGetFfsFileSize (FileToRm);
    125 
    126   CommonLibBinderSetMem (
    127     FileToRm,
    128     FileToRmLength,
    129     (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY)
    130       ? 0xFF : 0
    131     );
    132 
    133   return EFI_SUCCESS;
    134 }
    135 
    136 
    137 EFI_STATUS
    138 FvBufRemoveFile (
    139   IN OUT VOID *Fv,
    140   IN EFI_GUID *Name
    141   )
    142 /*++
    143 
    144 Routine Description:
    145 
    146   Clears out all files from the Fv buffer in memory
    147 
    148 Arguments:
    149 
    150   SourceFv - Address of the Fv in memory, this firmware volume volume will
    151              be modified, if SourceFfsFile exists
    152   SourceFfsFile - Input FFS file to replace
    153 
    154 Returns:
    155 
    156   EFI_SUCCESS
    157   EFI_NOT_FOUND
    158 
    159 --*/
    160 {
    161   EFI_STATUS                  Status;
    162   EFI_FFS_FILE_HEADER        *NextFile;
    163   EFI_FIRMWARE_VOLUME_HEADER *TempFv;
    164   UINTN                       FileKey;
    165   UINTN                       FvLength;
    166 
    167   Status = FvBufFindFileByName(
    168     Fv,
    169     Name,
    170     NULL
    171     );
    172   if (EFI_ERROR (Status)) {
    173     return Status;
    174   }
    175 
    176   Status = FvBufGetSize (Fv, &FvLength);
    177   if (EFI_ERROR (Status)) {
    178     return Status;
    179   }
    180 
    181   TempFv = NULL;
    182   Status = FvBufDuplicate (Fv, (VOID **)&TempFv);
    183   if (EFI_ERROR (Status)) {
    184     return Status;
    185   }
    186 
    187   Status = FvBufClearAllFiles (TempFv);
    188   if (EFI_ERROR (Status)) {
    189     CommonLibBinderFree (TempFv);
    190     return Status;
    191   }
    192 
    193   // TempFv has been allocated.  It must now be freed
    194   // before returning.
    195 
    196   FileKey = 0;
    197   while (TRUE) {
    198 
    199     Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile);
    200     if (Status == EFI_NOT_FOUND) {
    201       break;
    202     } else if (EFI_ERROR (Status)) {
    203       CommonLibBinderFree (TempFv);
    204       return Status;
    205     }
    206 
    207     if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
    208       continue;
    209     }
    210     else {
    211       Status = FvBufAddFile (TempFv, NextFile);
    212       if (EFI_ERROR (Status)) {
    213         CommonLibBinderFree (TempFv);
    214         return Status;
    215       }
    216     }
    217   }
    218 
    219   CommonLibBinderCopyMem (Fv, TempFv, FvLength);
    220   CommonLibBinderFree (TempFv);
    221 
    222   return EFI_SUCCESS;
    223 }
    224 
    225 
    226 EFI_STATUS
    227 FvBufChecksumFile (
    228   IN OUT VOID *FfsFile
    229   )
    230 /*++
    231 
    232 Routine Description:
    233 
    234   Clears out all files from the Fv buffer in memory
    235 
    236 Arguments:
    237 
    238   SourceFfsFile - Input FFS file to update the checksum for
    239 
    240 Returns:
    241 
    242   EFI_SUCCESS
    243   EFI_NOT_FOUND
    244 
    245 --*/
    246 {
    247   EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile;
    248   EFI_FFS_FILE_STATE StateBackup;
    249   UINT32 FileSize;
    250 
    251   FileSize = FvBufGetFfsFileSize (File);
    252 
    253   //
    254   // Fill in checksums and state, they must be 0 for checksumming.
    255   //
    256   File->IntegrityCheck.Checksum.Header = 0;
    257   File->IntegrityCheck.Checksum.File = 0;
    258   StateBackup = File->State;
    259   File->State = 0;
    260 
    261   File->IntegrityCheck.Checksum.Header =
    262     FvBufCalculateChecksum8 (
    263       (UINT8 *) File,
    264       FvBufGetFfsHeaderSize (File)
    265       );
    266 
    267   if (File->Attributes & FFS_ATTRIB_CHECKSUM) {
    268     File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 (
    269                                                 (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)),
    270                                                 FileSize - FvBufGetFfsHeaderSize (File)
    271                                                 );
    272   } else {
    273     File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
    274   }
    275 
    276   File->State = StateBackup;
    277 
    278   return EFI_SUCCESS;
    279 }
    280 
    281 
    282 EFI_STATUS
    283 FvBufChecksumHeader (
    284   IN OUT VOID *Fv
    285   )
    286 /*++
    287 
    288 Routine Description:
    289 
    290   Clears out all files from the Fv buffer in memory
    291 
    292 Arguments:
    293 
    294   SourceFv - Address of the Fv in memory, this firmware volume volume will
    295              be modified, if SourceFfsFile exists
    296   SourceFfsFile - Input FFS file to replace
    297 
    298 Returns:
    299 
    300   EFI_SUCCESS
    301   EFI_NOT_FOUND
    302 
    303 --*/
    304 {
    305   EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
    306 
    307   FvHeader->Checksum = 0;
    308   FvHeader->Checksum =
    309     FvBufCalculateChecksum16 (
    310       (UINT16*) FvHeader,
    311       FvHeader->HeaderLength / sizeof (UINT16)
    312       );
    313 
    314   return EFI_SUCCESS;
    315 }
    316 
    317 
    318 EFI_STATUS
    319 FvBufDuplicate (
    320   IN VOID *SourceFv,
    321   IN OUT VOID **DestinationFv
    322   )
    323 /*++
    324 
    325 Routine Description:
    326 
    327   Clears out all files from the Fv buffer in memory
    328 
    329 Arguments:
    330 
    331   SourceFv - Address of the Fv in memory
    332   DestinationFv - Output for destination Fv
    333     DestinationFv == NULL - invalid parameter
    334     *DestinationFv == NULL - memory will be allocated
    335     *DestinationFv != NULL - this address will be the destination
    336 
    337 Returns:
    338 
    339   EFI_SUCCESS
    340 
    341 --*/
    342 {
    343   EFI_STATUS Status;
    344   UINTN size;
    345 
    346   if (DestinationFv == NULL) {
    347     return EFI_INVALID_PARAMETER;
    348   }
    349 
    350   Status = FvBufGetSize (SourceFv, &size);
    351   if (EFI_ERROR (Status)) {
    352     return Status;
    353   }
    354 
    355   if (*DestinationFv == NULL) {
    356     *DestinationFv = CommonLibBinderAllocate (size);
    357     if (*DestinationFv == NULL) {
    358       return EFI_OUT_OF_RESOURCES;
    359     }
    360   }
    361 
    362   CommonLibBinderCopyMem (*DestinationFv, SourceFv, size);
    363 
    364   return EFI_SUCCESS;
    365 }
    366 
    367 
    368 EFI_STATUS
    369 FvBufExtend (
    370   IN VOID **Fv,
    371   IN UINTN Size
    372   )
    373 /*++
    374 
    375 Routine Description:
    376 
    377   Extends a firmware volume by the given number of bytes.
    378 
    379   BUGBUG: Does not handle the case where the firmware volume has a
    380           VTF (Volume Top File).  The VTF will not be moved to the
    381           end of the extended FV.
    382 
    383 Arguments:
    384 
    385   Fv - Source and destination firmware volume.
    386        Note: The original firmware volume buffer is freed!
    387 
    388   Size - The minimum size that the firmware volume is to be extended by.
    389          The FV may be extended more than this size.
    390 
    391 Returns:
    392 
    393   EFI_SUCCESS
    394 
    395 --*/
    396 {
    397   EFI_STATUS Status;
    398   UINTN OldSize;
    399   UINTN NewSize;
    400   UINTN BlockCount;
    401   VOID* NewFv;
    402 
    403   EFI_FIRMWARE_VOLUME_HEADER* hdr;
    404   EFI_FV_BLOCK_MAP_ENTRY*     blk;
    405 
    406   Status = FvBufGetSize (*Fv, &OldSize);
    407   if (EFI_ERROR (Status)) {
    408     return Status;
    409   }
    410 
    411   //
    412   // Locate the block map in the fv header
    413   //
    414   hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv;
    415   blk = hdr->BlockMap;
    416 
    417   //
    418   // Calculate the number of blocks needed to achieve the requested
    419   // size extension
    420   //
    421   BlockCount = ((Size + (blk->Length - 1)) / blk->Length);
    422 
    423   //
    424   // Calculate the new size from the number of blocks that will be added
    425   //
    426   NewSize = OldSize + (BlockCount * blk->Length);
    427 
    428   NewFv = CommonLibBinderAllocate (NewSize);
    429   if (NewFv == NULL) {
    430     return EFI_OUT_OF_RESOURCES;
    431   }
    432 
    433   //
    434   // Copy the old data
    435   //
    436   CommonLibBinderCopyMem (NewFv, *Fv, OldSize);
    437 
    438   //
    439   // Free the old fv buffer
    440   //
    441   CommonLibBinderFree (*Fv);
    442 
    443   //
    444   // Locate the block map in the new fv header
    445   //
    446   hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv;
    447   hdr->FvLength = NewSize;
    448   blk = hdr->BlockMap;
    449 
    450   //
    451   // Update the block map for the new fv
    452   //
    453   blk->NumBlocks += (UINT32)BlockCount;
    454 
    455   //
    456   // Update the FV header checksum
    457   //
    458   FvBufChecksumHeader (NewFv);
    459 
    460   //
    461   // Clear out the new area of the FV
    462   //
    463   CommonLibBinderSetMem (
    464     (UINT8*)NewFv + OldSize,
    465     (NewSize - OldSize),
    466     (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
    467     );
    468 
    469   //
    470   // Set output with new fv that was created
    471   //
    472   *Fv = NewFv;
    473 
    474   return EFI_SUCCESS;
    475 
    476 }
    477 
    478 
    479 EFI_STATUS
    480 FvBufClearAllFiles (
    481   IN OUT VOID *Fv
    482   )
    483 /*++
    484 
    485 Routine Description:
    486 
    487   Clears out all files from the Fv buffer in memory
    488 
    489 Arguments:
    490 
    491   Fv - Address of the Fv in memory
    492 
    493 Returns:
    494 
    495   EFI_SUCCESS
    496 
    497 --*/
    498 
    499 {
    500   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
    501   EFI_STATUS Status;
    502   UINTN size = 0;
    503 
    504   Status = FvBufGetSize (Fv, &size);
    505   if (EFI_ERROR (Status)) {
    506     return Status;
    507   }
    508 
    509   CommonLibBinderSetMem(
    510     (UINT8*)hdr + hdr->HeaderLength,
    511     size - hdr->HeaderLength,
    512     (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
    513     );
    514 
    515   return EFI_SUCCESS;
    516 }
    517 
    518 
    519 EFI_STATUS
    520 FvBufGetSize (
    521   IN VOID *Fv,
    522   OUT UINTN *Size
    523   )
    524 /*++
    525 
    526 Routine Description:
    527 
    528   Clears out all files from the Fv buffer in memory
    529 
    530 Arguments:
    531 
    532   Fv - Address of the Fv in memory
    533 
    534 Returns:
    535 
    536   EFI_SUCCESS
    537 
    538 --*/
    539 
    540 {
    541   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
    542   EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
    543 
    544   *Size = 0;
    545 
    546   while (blk->Length != 0 || blk->NumBlocks != 0) {
    547     *Size = *Size + (blk->Length * blk->NumBlocks);
    548     if (*Size >= 0x40000000) {
    549       // If size is greater than 1GB, then assume it is corrupted
    550       return EFI_VOLUME_CORRUPTED;
    551     }
    552     blk++;
    553   }
    554 
    555   if (*Size == 0) {
    556     // If size is 0, then assume the volume is corrupted
    557     return EFI_VOLUME_CORRUPTED;
    558   }
    559 
    560   return EFI_SUCCESS;
    561 }
    562 
    563 
    564 EFI_STATUS
    565 FvBufAddFile (
    566   IN OUT VOID *Fv,
    567   IN VOID *File
    568   )
    569 /*++
    570 
    571 Routine Description:
    572 
    573   Adds a new FFS file
    574 
    575 Arguments:
    576 
    577   Fv - Address of the Fv in memory
    578   File - FFS file to add to Fv
    579 
    580 Returns:
    581 
    582   EFI_SUCCESS
    583 
    584 --*/
    585 {
    586   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
    587 
    588   EFI_FFS_FILE_HEADER *fhdr = NULL;
    589   EFI_FVB_ATTRIBUTES_2 FvbAttributes;
    590   UINTN offset;
    591   UINTN fsize;
    592   UINTN newSize;
    593   UINTN clearLoop;
    594 
    595   EFI_STATUS Status;
    596   UINTN fvSize;
    597 
    598   Status = FvBufGetSize (Fv, &fvSize);
    599   if (EFI_ERROR (Status)) {
    600     return Status;
    601   }
    602 
    603   FvbAttributes = hdr->Attributes;
    604   newSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
    605 
    606   for(
    607       offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8);
    608       offset + newSize <= fvSize;
    609       offset = (UINTN)ALIGN_POINTER (offset, 8)
    610     ) {
    611 
    612     fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset);
    613 
    614     if (EFI_TEST_FFS_ATTRIBUTES_BIT(
    615           FvbAttributes,
    616           fhdr->State,
    617           EFI_FILE_HEADER_VALID
    618         )
    619       ) {
    620       // BUGBUG: Need to make sure that the new file does not already
    621       // exist.
    622 
    623       fsize = FvBufGetFfsFileSize (fhdr);
    624       if (fsize == 0 || (offset + fsize > fvSize)) {
    625         return EFI_VOLUME_CORRUPTED;
    626       }
    627 
    628       offset = offset + fsize;
    629       continue;
    630     }
    631 
    632     clearLoop = 0;
    633     while ((clearLoop < newSize) &&
    634            (((UINT8*)fhdr)[clearLoop] ==
    635              (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0)
    636            )
    637           ) {
    638       clearLoop++;
    639     }
    640 
    641     //
    642     // We found a place in the FV which is empty and big enough for
    643     // the new file
    644     //
    645     if (clearLoop >= newSize) {
    646       break;
    647     }
    648 
    649     offset = offset + 1; // Make some forward progress
    650   }
    651 
    652   if (offset + newSize > fvSize) {
    653     return EFI_OUT_OF_RESOURCES;
    654   }
    655 
    656   CommonLibBinderCopyMem (fhdr, File, newSize);
    657 
    658   return EFI_SUCCESS;
    659 }
    660 
    661 
    662 EFI_STATUS
    663 FvBufAddFileWithExtend (
    664   IN OUT VOID **Fv,
    665   IN VOID *File
    666   )
    667 /*++
    668 
    669 Routine Description:
    670 
    671   Adds a new FFS file.  Extends the firmware volume if needed.
    672 
    673 Arguments:
    674 
    675   Fv - Source and destination firmware volume.
    676        Note: If the FV is extended, then the original firmware volume
    677              buffer is freed!
    678 
    679   Size - The minimum size that the firmware volume is to be extended by.
    680          The FV may be extended more than this size.
    681 
    682 Returns:
    683 
    684   EFI_SUCCESS
    685 
    686 --*/
    687 {
    688   EFI_STATUS Status;
    689   EFI_FFS_FILE_HEADER* NewFile;
    690 
    691   NewFile = (EFI_FFS_FILE_HEADER*)File;
    692 
    693   //
    694   // Try to add to the capsule volume
    695   //
    696   Status = FvBufAddFile (*Fv, NewFile);
    697   if (Status == EFI_OUT_OF_RESOURCES) {
    698     //
    699     // Try to extend the capsule volume by the size of the file
    700     //
    701     Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size));
    702     if (EFI_ERROR (Status)) {
    703       return Status;
    704     }
    705 
    706     //
    707     // Now, try to add the file again
    708     //
    709     Status = FvBufAddFile (*Fv, NewFile);
    710   }
    711 
    712   return Status;
    713 }
    714 
    715 
    716 EFI_STATUS
    717 FvBufAddVtfFile (
    718   IN OUT VOID *Fv,
    719   IN VOID *File
    720   )
    721 /*++
    722 
    723 Routine Description:
    724 
    725   Adds a new FFS VFT (Volume Top File) file.  In other words, adds the
    726   file to the end of the firmware volume.
    727 
    728 Arguments:
    729 
    730   Fv - Address of the Fv in memory
    731   File - FFS file to add to Fv
    732 
    733 Returns:
    734 
    735   EFI_SUCCESS
    736 
    737 --*/
    738 {
    739   EFI_STATUS Status;
    740 
    741   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
    742 
    743   EFI_FFS_FILE_HEADER* NewFile;
    744   UINTN                NewFileSize;
    745 
    746   UINT8 erasedUint8;
    747   UINTN clearLoop;
    748 
    749   EFI_FFS_FILE_HEADER *LastFile;
    750   UINTN LastFileSize;
    751 
    752   UINTN fvSize;
    753   UINTN Key;
    754 
    755   Status = FvBufGetSize (Fv, &fvSize);
    756   if (EFI_ERROR (Status)) {
    757     return Status;
    758   }
    759 
    760   erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0);
    761   NewFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
    762 
    763   if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) {
    764     return EFI_INVALID_PARAMETER;
    765   }
    766 
    767   //
    768   // Find the last file in the FV
    769   //
    770   Key = 0;
    771   LastFile = NULL;
    772   LastFileSize = 0;
    773   do {
    774     Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile);
    775     LastFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
    776   } while (!EFI_ERROR (Status));
    777 
    778   //
    779   // If no files were found, then we start at the beginning of the FV
    780   //
    781   if (LastFile == NULL) {
    782     LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength);
    783   }
    784 
    785   //
    786   // We want to put the new file (VTF) at the end of the FV
    787   //
    788   NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize));
    789 
    790   //
    791   // Check to see if there is enough room for the VTF after the last file
    792   // found in the FV
    793   //
    794   if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) {
    795     return EFI_OUT_OF_RESOURCES;
    796   }
    797 
    798   //
    799   // Loop to determine if the end of the FV is empty
    800   //
    801   clearLoop = 0;
    802   while ((clearLoop < NewFileSize) &&
    803          (((UINT8*)NewFile)[clearLoop] == erasedUint8)
    804         ) {
    805     clearLoop++;
    806   }
    807 
    808   //
    809   // Check to see if there was not enough room for the file
    810   //
    811   if (clearLoop < NewFileSize) {
    812     return EFI_OUT_OF_RESOURCES;
    813   }
    814 
    815   CommonLibBinderCopyMem (NewFile, File, NewFileSize);
    816 
    817   return EFI_SUCCESS;
    818 }
    819 
    820 
    821 VOID
    822 FvBufCompact3ByteSize (
    823   OUT VOID* SizeDest,
    824   IN UINT32 Size
    825   )
    826 /*++
    827 
    828 Routine Description:
    829 
    830   Expands the 3 byte size commonly used in Firmware Volume data structures
    831 
    832 Arguments:
    833 
    834   Size - Address of the 3 byte array representing the size
    835 
    836 Returns:
    837 
    838   UINT32
    839 
    840 --*/
    841 {
    842   ((UINT8*)SizeDest)[0] = (UINT8)Size;
    843   ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8);
    844   ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16);
    845 }
    846 
    847 UINT32
    848 FvBufGetFfsFileSize (
    849   IN EFI_FFS_FILE_HEADER *Ffs
    850   )
    851 /*++
    852 
    853 Routine Description:
    854 
    855   Get the FFS file size.
    856 
    857 Arguments:
    858 
    859   Ffs - Pointer to FFS header
    860 
    861 Returns:
    862 
    863   UINT32
    864 
    865 --*/
    866 {
    867   if (Ffs == NULL) {
    868     return 0;
    869   }
    870   if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
    871     return (UINT32) ((EFI_FFS_FILE_HEADER2 *)Ffs)->ExtendedSize;
    872   }
    873   return FvBufExpand3ByteSize(Ffs->Size);
    874 }
    875 
    876 UINT32
    877 FvBufGetFfsHeaderSize (
    878   IN EFI_FFS_FILE_HEADER *Ffs
    879   )
    880 /*++
    881 
    882 Routine Description:
    883 
    884   Get the FFS header size.
    885 
    886 Arguments:
    887 
    888   Ffs - Pointer to FFS header
    889 
    890 Returns:
    891 
    892   UINT32
    893 
    894 --*/
    895 {
    896   if (Ffs == NULL) {
    897     return 0;
    898   }
    899   if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
    900     return sizeof(EFI_FFS_FILE_HEADER2);
    901   }
    902   return sizeof(EFI_FFS_FILE_HEADER);
    903 }
    904 
    905 UINT32
    906 FvBufExpand3ByteSize (
    907   IN VOID* Size
    908   )
    909 /*++
    910 
    911 Routine Description:
    912 
    913   Expands the 3 byte size commonly used in Firmware Volume data structures
    914 
    915 Arguments:
    916 
    917   Size - Address of the 3 byte array representing the size
    918 
    919 Returns:
    920 
    921   UINT32
    922 
    923 --*/
    924 {
    925   return (((UINT8*)Size)[2] << 16) +
    926          (((UINT8*)Size)[1] << 8) +
    927          ((UINT8*)Size)[0];
    928 }
    929 
    930 EFI_STATUS
    931 FvBufFindNextFile (
    932   IN VOID *Fv,
    933   IN OUT UINTN *Key,
    934   OUT VOID **File
    935   )
    936 /*++
    937 
    938 Routine Description:
    939 
    940   Iterates through the files contained within the firmware volume
    941 
    942 Arguments:
    943 
    944   Fv - Address of the Fv in memory
    945   Key - Should be 0 to get the first file.  After that, it should be
    946         passed back in without modifying it's contents to retrieve
    947         subsequent files.
    948   File - Output file pointer
    949     File == NULL - invalid parameter
    950     otherwise - *File will be update to the location of the file
    951 
    952 Returns:
    953 
    954   EFI_SUCCESS
    955   EFI_NOT_FOUND
    956   EFI_VOLUME_CORRUPTED
    957 
    958 --*/
    959 {
    960   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
    961 
    962   EFI_FFS_FILE_HEADER *fhdr = NULL;
    963   EFI_FVB_ATTRIBUTES_2 FvbAttributes;
    964   UINTN fsize;
    965 
    966   EFI_STATUS Status;
    967   UINTN fvSize;
    968 
    969   if (Fv == NULL) {
    970     return EFI_INVALID_PARAMETER;
    971   }
    972 
    973   Status = FvBufGetSize (Fv, &fvSize);
    974   if (EFI_ERROR (Status)) {
    975     return Status;
    976   }
    977 
    978   if (*Key == 0) {
    979     *Key = hdr->HeaderLength;
    980   }
    981 
    982   FvbAttributes = hdr->Attributes;
    983 
    984   for(
    985       *Key = (UINTN)ALIGN_POINTER (*Key, 8);
    986       (*Key + sizeof (*fhdr)) < fvSize;
    987       *Key = (UINTN)ALIGN_POINTER (*Key, 8)
    988     ) {
    989 
    990     fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key);
    991     fsize = FvBufGetFfsFileSize (fhdr);
    992 
    993     if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
    994           FvbAttributes,
    995           fhdr->State,
    996           EFI_FILE_HEADER_VALID
    997         ) ||
    998         EFI_TEST_FFS_ATTRIBUTES_BIT(
    999           FvbAttributes,
   1000           fhdr->State,
   1001           EFI_FILE_HEADER_INVALID
   1002         )
   1003       ) {
   1004       *Key = *Key + 1; // Make some forward progress
   1005       continue;
   1006     } else if(
   1007         EFI_TEST_FFS_ATTRIBUTES_BIT(
   1008           FvbAttributes,
   1009           fhdr->State,
   1010           EFI_FILE_MARKED_FOR_UPDATE
   1011         ) ||
   1012         EFI_TEST_FFS_ATTRIBUTES_BIT(
   1013           FvbAttributes,
   1014           fhdr->State,
   1015           EFI_FILE_DELETED
   1016         )
   1017       ) {
   1018       *Key = *Key + fsize;
   1019       continue;
   1020     } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
   1021           FvbAttributes,
   1022           fhdr->State,
   1023           EFI_FILE_DATA_VALID
   1024         )
   1025       ) {
   1026       *File = (UINT8*)hdr + *Key;
   1027       *Key = *Key + fsize;
   1028       return EFI_SUCCESS;
   1029     }
   1030 
   1031     *Key = *Key + 1; // Make some forward progress
   1032   }
   1033 
   1034   return EFI_NOT_FOUND;
   1035 }
   1036 
   1037 
   1038 EFI_STATUS
   1039 FvBufFindFileByName (
   1040   IN VOID *Fv,
   1041   IN EFI_GUID *Name,
   1042   OUT VOID **File
   1043   )
   1044 /*++
   1045 
   1046 Routine Description:
   1047 
   1048   Searches the Fv for a file by its name
   1049 
   1050 Arguments:
   1051 
   1052   Fv - Address of the Fv in memory
   1053   Name - Guid filename to search for in the firmware volume
   1054   File - Output file pointer
   1055     File == NULL - Only determine if the file exists, based on return
   1056                    value from the function call.
   1057     otherwise - *File will be update to the location of the file
   1058 
   1059 Returns:
   1060 
   1061   EFI_SUCCESS
   1062   EFI_NOT_FOUND
   1063   EFI_VOLUME_CORRUPTED
   1064 
   1065 --*/
   1066 {
   1067   EFI_STATUS Status;
   1068   UINTN Key;
   1069   EFI_FFS_FILE_HEADER *NextFile;
   1070 
   1071   Key = 0;
   1072   while (TRUE) {
   1073     Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
   1074     if (EFI_ERROR (Status)) {
   1075       return Status;
   1076     }
   1077 
   1078     if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
   1079       if (File != NULL) {
   1080         *File = NextFile;
   1081       }
   1082       return EFI_SUCCESS;
   1083     }
   1084   }
   1085 
   1086   return EFI_NOT_FOUND;
   1087 }
   1088 
   1089 
   1090 EFI_STATUS
   1091 FvBufFindFileByType (
   1092   IN VOID *Fv,
   1093   IN EFI_FV_FILETYPE Type,
   1094   OUT VOID **File
   1095   )
   1096 /*++
   1097 
   1098 Routine Description:
   1099 
   1100   Searches the Fv for a file by its type
   1101 
   1102 Arguments:
   1103 
   1104   Fv - Address of the Fv in memory
   1105   Type - FFS FILE type to search for
   1106   File - Output file pointer
   1107     (File == NULL) -> Only determine if the file exists, based on return
   1108                       value from the function call.
   1109     otherwise -> *File will be update to the location of the file
   1110 
   1111 Returns:
   1112 
   1113   EFI_SUCCESS
   1114   EFI_NOT_FOUND
   1115   EFI_VOLUME_CORRUPTED
   1116 
   1117 --*/
   1118 {
   1119   EFI_STATUS Status;
   1120   UINTN Key;
   1121   EFI_FFS_FILE_HEADER *NextFile;
   1122 
   1123   Key = 0;
   1124   while (TRUE) {
   1125     Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
   1126     if (EFI_ERROR (Status)) {
   1127       return Status;
   1128     }
   1129 
   1130     if (Type == NextFile->Type) {
   1131       if (File != NULL) {
   1132         *File = NextFile;
   1133       }
   1134       return EFI_SUCCESS;
   1135     }
   1136   }
   1137 
   1138   return EFI_NOT_FOUND;
   1139 }
   1140 
   1141 
   1142 EFI_STATUS
   1143 FvBufGetFileRawData (
   1144   IN  VOID*     FfsFile,
   1145   OUT VOID**    RawData,
   1146   OUT UINTN*    RawDataSize
   1147   )
   1148 /*++
   1149 
   1150 Routine Description:
   1151 
   1152   Searches the requested file for raw data.
   1153 
   1154   This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
   1155   or finds the EFI_SECTION_RAW section within the file and returns its data.
   1156 
   1157 Arguments:
   1158 
   1159   FfsFile - Address of the FFS file in memory
   1160   RawData - Pointer to the raw data within the file
   1161             (This is NOT allocated.  It is within the file.)
   1162   RawDataSize - Size of the raw data within the file
   1163 
   1164 Returns:
   1165 
   1166   EFI_STATUS
   1167 
   1168 --*/
   1169 {
   1170   EFI_STATUS Status;
   1171   EFI_FFS_FILE_HEADER* File;
   1172   EFI_RAW_SECTION* Section;
   1173 
   1174   File = (EFI_FFS_FILE_HEADER*)FfsFile;
   1175 
   1176   //
   1177   // Is the file type == EFI_FV_FILETYPE_RAW?
   1178   //
   1179   if (File->Type == EFI_FV_FILETYPE_RAW) {
   1180     //
   1181     // Raw filetypes don't have sections, so we just return the raw data
   1182     //
   1183     *RawData = (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File));
   1184     *RawDataSize = FvBufGetFfsFileSize (File) - FvBufGetFfsHeaderSize (File);
   1185     return EFI_SUCCESS;
   1186   }
   1187 
   1188   //
   1189   // Within the file, we now need to find the EFI_SECTION_RAW section.
   1190   //
   1191   Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section);
   1192   if (EFI_ERROR (Status)) {
   1193     return Status;
   1194   }
   1195 
   1196   *RawData = (VOID*)((UINT8 *)Section + FvBufGetSecHdrLen(Section));
   1197   *RawDataSize =
   1198     FvBufGetSecFileLen (Section) - FvBufGetSecHdrLen(Section);
   1199 
   1200   return EFI_SUCCESS;
   1201 
   1202 }
   1203 
   1204 
   1205 EFI_STATUS
   1206 FvBufPackageFreeformRawFile (
   1207   IN EFI_GUID*  Filename,
   1208   IN VOID*      RawData,
   1209   IN UINTN      RawDataSize,
   1210   OUT VOID**    FfsFile
   1211   )
   1212 /*++
   1213 
   1214 Routine Description:
   1215 
   1216   Packages up a FFS file containing the input raw data.
   1217 
   1218   The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
   1219   contain one EFI_FV_FILETYPE_RAW section.
   1220 
   1221 Arguments:
   1222 
   1223   RawData - Pointer to the raw data to be packed
   1224   RawDataSize - Size of the raw data to be packed
   1225   FfsFile - Address of the packaged FFS file.
   1226             Note: The called must deallocate this memory!
   1227 
   1228 Returns:
   1229 
   1230   EFI_STATUS
   1231 
   1232 --*/
   1233 {
   1234   EFI_FFS_FILE_HEADER* NewFile;
   1235   UINT32 NewFileSize;
   1236   EFI_RAW_SECTION* NewSection;
   1237   UINT32 NewSectionSize;
   1238   UINT32 FfsHdrLen;
   1239   UINT32 SecHdrLen;
   1240 
   1241   //
   1242   // The section size is the DataSize + the size of the section header
   1243   //
   1244   NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize;
   1245   SecHdrLen = sizeof (EFI_RAW_SECTION);
   1246   if (NewSectionSize >= MAX_SECTION_SIZE) {
   1247     NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION2) + (UINT32)RawDataSize;
   1248     SecHdrLen = sizeof (EFI_RAW_SECTION2);
   1249   }
   1250 
   1251   //
   1252   // The file size is the size of the file header + the section size
   1253   //
   1254   NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize;
   1255   FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER);
   1256   if (NewFileSize >= MAX_FFS_SIZE) {
   1257     NewFileSize = sizeof (EFI_FFS_FILE_HEADER2) + NewSectionSize;
   1258     FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER2);
   1259   }
   1260 
   1261   //
   1262   // Try to allocate a buffer to build the new FFS file in
   1263   //
   1264   NewFile = CommonLibBinderAllocate (NewFileSize);
   1265   if (NewFile == NULL) {
   1266     return EFI_OUT_OF_RESOURCES;
   1267   }
   1268   CommonLibBinderSetMem (NewFile, NewFileSize, 0);
   1269 
   1270   //
   1271   // The NewSection follow right after the FFS file header
   1272   //
   1273   NewSection = (EFI_RAW_SECTION*)((UINT8*)NewFile + FfsHdrLen);
   1274   if (NewSectionSize >= MAX_SECTION_SIZE) {
   1275     FvBufCompact3ByteSize (NewSection->Size, 0xffffff);
   1276     ((EFI_RAW_SECTION2 *)NewSection)->ExtendedSize = NewSectionSize;
   1277   } else {
   1278     FvBufCompact3ByteSize (NewSection->Size, NewSectionSize);
   1279   }
   1280   NewSection->Type = EFI_SECTION_RAW;
   1281 
   1282   //
   1283   // Copy the actual file data into the buffer
   1284   //
   1285   CommonLibBinderCopyMem ((UINT8 *)NewSection + SecHdrLen, RawData, RawDataSize);
   1286 
   1287   //
   1288   // Initialize the FFS file header
   1289   //
   1290   CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID));
   1291   NewFile->Attributes = 0;
   1292   if (NewFileSize >= MAX_FFS_SIZE) {
   1293     FvBufCompact3ByteSize (NewFile->Size, 0x0);
   1294     ((EFI_FFS_FILE_HEADER2 *)NewFile)->ExtendedSize = NewFileSize;
   1295     NewFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
   1296   } else {
   1297     FvBufCompact3ByteSize (NewFile->Size, NewFileSize);
   1298   }
   1299   NewFile->Type = EFI_FV_FILETYPE_FREEFORM;
   1300   NewFile->IntegrityCheck.Checksum.Header =
   1301     FvBufCalculateChecksum8 ((UINT8*)NewFile, FfsHdrLen);
   1302   NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
   1303   NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION |
   1304                              EFI_FILE_HEADER_VALID |
   1305                              EFI_FILE_DATA_VALID
   1306                            );
   1307 
   1308   *FfsFile = NewFile;
   1309 
   1310   return EFI_SUCCESS;
   1311 }
   1312 
   1313 
   1314 EFI_STATUS
   1315 FvBufFindNextSection (
   1316   IN VOID *SectionsStart,
   1317   IN UINTN TotalSectionsSize,
   1318   IN OUT UINTN *Key,
   1319   OUT VOID **Section
   1320   )
   1321 /*++
   1322 
   1323 Routine Description:
   1324 
   1325   Iterates through the sections contained within a given array of sections
   1326 
   1327 Arguments:
   1328 
   1329   SectionsStart - Address of the start of the FFS sections array
   1330   TotalSectionsSize - Total size of all the sections
   1331   Key - Should be 0 to get the first section.  After that, it should be
   1332         passed back in without modifying it's contents to retrieve
   1333         subsequent files.
   1334   Section - Output section pointer
   1335     (Section == NULL) -> invalid parameter
   1336     otherwise -> *Section will be update to the location of the file
   1337 
   1338 Returns:
   1339 
   1340   EFI_SUCCESS
   1341   EFI_NOT_FOUND
   1342   EFI_VOLUME_CORRUPTED
   1343 
   1344 --*/
   1345 {
   1346   EFI_COMMON_SECTION_HEADER *sectionHdr;
   1347   UINTN sectionSize;
   1348 
   1349   *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned
   1350 
   1351   if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) {
   1352     return EFI_NOT_FOUND;
   1353   }
   1354 
   1355   sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key);
   1356   sectionSize = FvBufGetSecFileLen (sectionHdr);
   1357 
   1358   if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) {
   1359     return EFI_NOT_FOUND;
   1360   }
   1361 
   1362   if ((*Key + sectionSize) > TotalSectionsSize) {
   1363     return EFI_NOT_FOUND;
   1364   }
   1365 
   1366   *Section = (UINT8*)sectionHdr;
   1367   *Key = *Key + sectionSize;
   1368   return EFI_SUCCESS;
   1369 
   1370 }
   1371 
   1372 
   1373 EFI_STATUS
   1374 FvBufCountSections (
   1375   IN VOID* FfsFile,
   1376   IN UINTN* Count
   1377   )
   1378 /*++
   1379 
   1380 Routine Description:
   1381 
   1382   Searches the FFS file and counts the number of sections found.
   1383   The sections are NOT recursed.
   1384 
   1385 Arguments:
   1386 
   1387   FfsFile - Address of the FFS file in memory
   1388   Count - The location to store the section count in
   1389 
   1390 Returns:
   1391 
   1392   EFI_SUCCESS
   1393   EFI_NOT_FOUND
   1394   EFI_VOLUME_CORRUPTED
   1395 
   1396 --*/
   1397 {
   1398   EFI_STATUS                 Status;
   1399   UINTN                      Key;
   1400   VOID*                      SectionStart;
   1401   UINTN                      TotalSectionsSize;
   1402   EFI_COMMON_SECTION_HEADER* NextSection;
   1403 
   1404   SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));
   1405   TotalSectionsSize =
   1406     FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
   1407     FvBufGetFfsHeaderSize(FfsFile);
   1408   Key = 0;
   1409   *Count = 0;
   1410   while (TRUE) {
   1411     Status = FvBufFindNextSection (
   1412                SectionStart,
   1413                TotalSectionsSize,
   1414                &Key,
   1415                (VOID **)&NextSection
   1416                );
   1417     if (Status == EFI_NOT_FOUND) {
   1418       return EFI_SUCCESS;
   1419     } else if (EFI_ERROR (Status)) {
   1420       return Status;
   1421     }
   1422 
   1423     //
   1424     // Increment the section counter
   1425     //
   1426     *Count += 1;
   1427 
   1428   }
   1429 
   1430   return EFI_NOT_FOUND;
   1431 }
   1432 
   1433 
   1434 EFI_STATUS
   1435 FvBufFindSectionByType (
   1436   IN VOID *FfsFile,
   1437   IN UINT8 Type,
   1438   OUT VOID **Section
   1439   )
   1440 /*++
   1441 
   1442 Routine Description:
   1443 
   1444   Searches the FFS file for a section by its type
   1445 
   1446 Arguments:
   1447 
   1448   FfsFile - Address of the FFS file in memory
   1449   Type - FFS FILE section type to search for
   1450   Section - Output section pointer
   1451     (Section == NULL) -> Only determine if the section exists, based on return
   1452                          value from the function call.
   1453     otherwise -> *Section will be update to the location of the file
   1454 
   1455 Returns:
   1456 
   1457   EFI_SUCCESS
   1458   EFI_NOT_FOUND
   1459   EFI_VOLUME_CORRUPTED
   1460 
   1461 --*/
   1462 {
   1463   EFI_STATUS Status;
   1464   UINTN Key;
   1465   VOID*                      SectionStart;
   1466   UINTN                      TotalSectionsSize;
   1467   EFI_COMMON_SECTION_HEADER* NextSection;
   1468 
   1469   SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));
   1470   TotalSectionsSize =
   1471     FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
   1472     FvBufGetFfsHeaderSize(FfsFile);
   1473   Key = 0;
   1474   while (TRUE) {
   1475     Status = FvBufFindNextSection (
   1476                SectionStart,
   1477                TotalSectionsSize,
   1478                &Key,
   1479                (VOID **)&NextSection
   1480                );
   1481     if (EFI_ERROR (Status)) {
   1482       return Status;
   1483     }
   1484 
   1485     if (Type == NextSection->Type) {
   1486       if (Section != NULL) {
   1487         *Section = NextSection;
   1488       }
   1489       return EFI_SUCCESS;
   1490     }
   1491   }
   1492 
   1493   return EFI_NOT_FOUND;
   1494 }
   1495 
   1496 
   1497 EFI_STATUS
   1498 FvBufShrinkWrap (
   1499   IN VOID *Fv
   1500   )
   1501 /*++
   1502 
   1503 Routine Description:
   1504 
   1505   Shrinks a firmware volume (in place) to provide a minimal FV.
   1506 
   1507   BUGBUG: Does not handle the case where the firmware volume has a
   1508           VTF (Volume Top File).  The VTF will not be moved to the
   1509           end of the extended FV.
   1510 
   1511 Arguments:
   1512 
   1513   Fv - Firmware volume.
   1514 
   1515 Returns:
   1516 
   1517   EFI_SUCCESS
   1518 
   1519 --*/
   1520 {
   1521   EFI_STATUS Status;
   1522   UINTN OldSize;
   1523   UINT32 BlockCount;
   1524   UINT32 NewBlockSize = 128;
   1525   UINTN Key;
   1526   EFI_FFS_FILE_HEADER* FileIt;
   1527   VOID* EndOfLastFile;
   1528 
   1529   EFI_FIRMWARE_VOLUME_HEADER* FvHdr;
   1530 
   1531   Status = FvBufGetSize (Fv, &OldSize);
   1532   if (EFI_ERROR (Status)) {
   1533     return Status;
   1534   }
   1535 
   1536   Status = FvBufUnifyBlockSizes (Fv, NewBlockSize);
   1537   if (EFI_ERROR (Status)) {
   1538     return Status;
   1539   }
   1540 
   1541   //
   1542   // Locate the block map in the fv header
   1543   //
   1544   FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
   1545 
   1546   //
   1547   // Find the end of the last file
   1548   //
   1549   Key = 0;
   1550   EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength;
   1551   while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) {
   1552     EndOfLastFile =
   1553       (VOID*)((UINT8*)FileIt + FvBufGetFfsFileSize (FileIt));
   1554   }
   1555 
   1556   //
   1557   // Set the BlockCount to have the minimal number of blocks for the Fv.
   1558   //
   1559   BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv);
   1560   BlockCount = BlockCount + NewBlockSize - 1;
   1561   BlockCount = BlockCount / NewBlockSize;
   1562 
   1563   //
   1564   // Adjust the block count to shrink the Fv in place.
   1565   //
   1566   FvHdr->BlockMap[0].NumBlocks = BlockCount;
   1567   FvHdr->FvLength = BlockCount * NewBlockSize;
   1568 
   1569   //
   1570   // Update the FV header checksum
   1571   //
   1572   FvBufChecksumHeader (Fv);
   1573 
   1574   return EFI_SUCCESS;
   1575 
   1576 }
   1577 
   1578 
   1579 EFI_STATUS
   1580 FvBufUnifyBlockSizes (
   1581   IN OUT VOID *Fv,
   1582   IN UINTN BlockSize
   1583   )
   1584 /*++
   1585 
   1586 Routine Description:
   1587 
   1588   Searches the FFS file for a section by its type
   1589 
   1590 Arguments:
   1591 
   1592   Fv - Address of the Fv in memory
   1593   BlockSize - The size of the blocks to convert the Fv to.  If the total size
   1594               of the Fv is not evenly divisible by this size, then
   1595               EFI_INVALID_PARAMETER will be returned.
   1596 
   1597 Returns:
   1598 
   1599   EFI_SUCCESS
   1600   EFI_NOT_FOUND
   1601   EFI_VOLUME_CORRUPTED
   1602 
   1603 --*/
   1604 {
   1605   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
   1606   EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
   1607   UINT32 Size;
   1608 
   1609   Size = 0;
   1610 
   1611   //
   1612   // Scan through the block map list, performing error checking, and adding
   1613   // up the total Fv size.
   1614   //
   1615   while( blk->Length != 0 ||
   1616          blk->NumBlocks != 0
   1617        ) {
   1618     Size = Size + (blk->Length * blk->NumBlocks);
   1619     blk++;
   1620     if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) {
   1621       return EFI_VOLUME_CORRUPTED;
   1622     }
   1623   }
   1624 
   1625   //
   1626   // Make sure that the Fv size is a multiple of the new block size.
   1627   //
   1628   if ((Size % BlockSize) != 0) {
   1629     return EFI_INVALID_PARAMETER;
   1630   }
   1631 
   1632   //
   1633   // Zero out the entire block map.
   1634   //
   1635   CommonLibBinderSetMem (
   1636     &hdr->BlockMap,
   1637     (UINTN)blk - (UINTN)&hdr->BlockMap,
   1638     0
   1639     );
   1640 
   1641   //
   1642   // Write out the single block map entry.
   1643   //
   1644   hdr->BlockMap[0].Length = (UINT32)BlockSize;
   1645   hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize;
   1646 
   1647   return EFI_SUCCESS;
   1648 }
   1649 
   1650 STATIC
   1651 UINT16
   1652 FvBufCalculateSum16 (
   1653   IN UINT16       *Buffer,
   1654   IN UINTN        Size
   1655   )
   1656 /*++
   1657 
   1658 Routine Description:
   1659 
   1660   This function calculates the UINT16 sum for the requested region.
   1661 
   1662 Arguments:
   1663 
   1664   Buffer      Pointer to buffer containing byte data of component.
   1665   Size        Size of the buffer
   1666 
   1667 Returns:
   1668 
   1669   The 16 bit checksum
   1670 
   1671 --*/
   1672 {
   1673   UINTN   Index;
   1674   UINT16  Sum;
   1675 
   1676   Sum = 0;
   1677 
   1678   //
   1679   // Perform the word sum for buffer
   1680   //
   1681   for (Index = 0; Index < Size; Index++) {
   1682     Sum = (UINT16) (Sum + Buffer[Index]);
   1683   }
   1684 
   1685   return (UINT16) Sum;
   1686 }
   1687 
   1688 
   1689 STATIC
   1690 UINT16
   1691 FvBufCalculateChecksum16 (
   1692   IN UINT16       *Buffer,
   1693   IN UINTN        Size
   1694   )
   1695 /*++
   1696 
   1697 Routine Description::
   1698 
   1699   This function calculates the value needed for a valid UINT16 checksum
   1700 
   1701 Arguments:
   1702 
   1703   Buffer      Pointer to buffer containing byte data of component.
   1704   Size        Size of the buffer
   1705 
   1706 Returns:
   1707 
   1708   The 16 bit checksum value needed.
   1709 
   1710 --*/
   1711 {
   1712   return (UINT16)(0x10000 - FvBufCalculateSum16 (Buffer, Size));
   1713 }
   1714 
   1715 
   1716 STATIC
   1717 UINT8
   1718 FvBufCalculateSum8 (
   1719   IN UINT8  *Buffer,
   1720   IN UINTN  Size
   1721   )
   1722 /*++
   1723 
   1724 Description:
   1725 
   1726   This function calculates the UINT8 sum for the requested region.
   1727 
   1728 Input:
   1729 
   1730   Buffer      Pointer to buffer containing byte data of component.
   1731   Size        Size of the buffer
   1732 
   1733 Return:
   1734 
   1735   The 8 bit checksum value needed.
   1736 
   1737 --*/
   1738 {
   1739   UINTN   Index;
   1740   UINT8   Sum;
   1741 
   1742   Sum = 0;
   1743 
   1744   //
   1745   // Perform the byte sum for buffer
   1746   //
   1747   for (Index = 0; Index < Size; Index++) {
   1748     Sum = (UINT8) (Sum + Buffer[Index]);
   1749   }
   1750 
   1751   return Sum;
   1752 }
   1753 
   1754 
   1755 STATIC
   1756 UINT8
   1757 FvBufCalculateChecksum8 (
   1758   IN UINT8        *Buffer,
   1759   IN UINTN        Size
   1760   )
   1761 /*++
   1762 
   1763 Description:
   1764 
   1765   This function calculates the value needed for a valid UINT8 checksum
   1766 
   1767 Input:
   1768 
   1769   Buffer      Pointer to buffer containing byte data of component.
   1770   Size        Size of the buffer
   1771 
   1772 Return:
   1773 
   1774   The 8 bit checksum value needed.
   1775 
   1776 --*/
   1777 {
   1778   return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size));
   1779 }
   1780 
   1781 
   1782