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