Home | History | Annotate | Download | only in FwVolDxe
      1 /** @file
      2 
      3   Firmware File System driver that produce full Firmware Volume2 protocol.
      4   Layers on top of Firmware Block protocol to produce a file abstraction
      5   of FV based files.
      6 
      7   Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
      8 
      9   This program and the accompanying materials
     10   are licensed and made available under the terms and conditions
     11   of the BSD License which accompanies this distribution.  The
     12   full text of the license may be found at
     13   http://opensource.org/licenses/bsd-license.php
     14 
     15   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     16   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     17 
     18 **/
     19 
     20 #include "FwVolDriver.h"
     21 
     22 #define KEYSIZE sizeof (UINTN)
     23 
     24 /**
     25   Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and
     26   copy the real length volume header into it.
     27 
     28   @param  Fvb                   The FW_VOL_BLOCK_PROTOCOL instance from which to
     29                                 read the volume header
     30   @param  FwVolHeader           Pointer to pointer to allocated buffer in which
     31                                 the volume header is returned.
     32 
     33   @retval EFI_OUT_OF_RESOURCES  No enough buffer could be allocated.
     34   @retval EFI_SUCCESS           Successfully read volume header to the allocated
     35                                 buffer.
     36   @retval EFI_ACCESS_DENIED     Read status of FV is not enabled.
     37   @retval EFI_INVALID_PARAMETER The FV Header signature is not as expected or
     38                                 the file system could not be understood.
     39 **/
     40 EFI_STATUS
     41 GetFwVolHeader (
     42   IN     EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *Fvb,
     43   OUT EFI_FIRMWARE_VOLUME_HEADER                **FwVolHeader
     44   )
     45 {
     46   EFI_STATUS                  Status;
     47   EFI_FIRMWARE_VOLUME_HEADER  TempFvh;
     48   EFI_FVB_ATTRIBUTES_2        FvbAttributes;
     49   UINTN                       FvhLength;
     50   EFI_PHYSICAL_ADDRESS        BaseAddress;
     51 
     52   //
     53   // Determine the real length of FV header
     54   //
     55   Status = Fvb->GetAttributes (
     56                   Fvb,
     57                   &FvbAttributes
     58                   );
     59   if (EFI_ERROR (Status)) {
     60     return Status;
     61   }
     62 
     63   if ((FvbAttributes & EFI_FVB2_READ_STATUS) == 0) {
     64     return EFI_ACCESS_DENIED;
     65   }
     66 
     67   //
     68   // Just avoid compiling warning
     69   //
     70   BaseAddress = 0;
     71   FvhLength   = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
     72 
     73   //
     74   // memory-mapped FV and non memory-mapped has different ways to read
     75   //
     76   if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
     77     Status = Fvb->GetPhysicalAddress (
     78                     Fvb,
     79                     &BaseAddress
     80                     );
     81     if (EFI_ERROR (Status)) {
     82       return Status;
     83     }
     84     CopyMem (&TempFvh, (VOID *) (UINTN) BaseAddress, FvhLength);
     85   } else {
     86     Status = Fvb->Read (
     87                     Fvb,
     88                     0,
     89                     0,
     90                     &FvhLength,
     91                     (UINT8 *) &TempFvh
     92                     );
     93   }
     94 
     95   //
     96   // Validate FV Header signature, if not as expected, continue.
     97   //
     98   if (TempFvh.Signature != EFI_FVH_SIGNATURE) {
     99     return EFI_INVALID_PARAMETER;
    100   }
    101 
    102   //
    103   // Check to see that the file system is indeed formatted in a way we can
    104   // understand it...
    105   //
    106   if ((!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem2Guid)) &&
    107       (!CompareGuid (&TempFvh.FileSystemGuid, &gEfiFirmwareFileSystem3Guid))) {
    108     return EFI_INVALID_PARAMETER;
    109   }
    110 
    111   *FwVolHeader = AllocatePool (TempFvh.HeaderLength);
    112   if (*FwVolHeader == NULL) {
    113     return EFI_OUT_OF_RESOURCES;
    114   }
    115   //
    116   // Read the whole header
    117   //
    118   if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
    119     CopyMem (*FwVolHeader, (VOID *) (UINTN) BaseAddress, TempFvh.HeaderLength);
    120   } else {
    121     //
    122     // Assumed the first block is bigger than the length of Fv headder
    123     //
    124     FvhLength = TempFvh.HeaderLength;
    125     Status = Fvb->Read (
    126                     Fvb,
    127                     0,
    128                     0,
    129                     &FvhLength,
    130                     (UINT8 *) *FwVolHeader
    131                     );
    132     //
    133     // Check whether Read successes.
    134     //
    135     if (EFI_ERROR (Status)) {
    136       FreePool (*FwVolHeader);
    137       *FwVolHeader = NULL;
    138       return Status;
    139     }
    140   }
    141 
    142   return EFI_SUCCESS;
    143 }
    144 
    145 /**
    146   Free FvDevice resource when error happens.
    147 
    148   @param FvDevice   Pointer to the FvDevice to be freed.
    149 **/
    150 VOID
    151 FreeFvDeviceResource (
    152   IN FV_DEVICE  *FvDevice
    153   )
    154 {
    155   LBA_ENTRY           *LbaEntry;
    156   FREE_SPACE_ENTRY    *FreeSpaceEntry;
    157   FFS_FILE_LIST_ENTRY *FfsFileEntry;
    158   LIST_ENTRY      *NextEntry;
    159 
    160   //
    161   // Free LAB Entry
    162   //
    163   LbaEntry = (LBA_ENTRY *) FvDevice->LbaHeader.ForwardLink;
    164   while (&LbaEntry->Link != &FvDevice->LbaHeader) {
    165     NextEntry = (&LbaEntry->Link)->ForwardLink;
    166     FreePool (LbaEntry);
    167     LbaEntry = (LBA_ENTRY *) NextEntry;
    168   }
    169   //
    170   // Free File List Entry
    171   //
    172   FfsFileEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->FfsFileListHeader.ForwardLink;
    173   while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) {
    174     NextEntry = (&FfsFileEntry->Link)->ForwardLink;
    175     FreePool (FfsFileEntry);
    176     FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;
    177   }
    178   //
    179   // Free Space Entry
    180   //
    181   FreeSpaceEntry = (FREE_SPACE_ENTRY *) FvDevice->FreeSpaceHeader.ForwardLink;
    182   while (&FreeSpaceEntry->Link != &FvDevice->FreeSpaceHeader) {
    183     NextEntry = (&FreeSpaceEntry->Link)->ForwardLink;
    184     FreePool (FreeSpaceEntry);
    185     FreeSpaceEntry = (FREE_SPACE_ENTRY *) NextEntry;
    186   }
    187   //
    188   // Free the cache
    189   //
    190   FreePool ((UINT8 *) (UINTN) FvDevice->CachedFv);
    191 
    192   return ;
    193 }
    194 
    195 /**
    196 
    197   Firmware volume inherits authentication status from the FV image file and section(in another firmware volume)
    198   where it came from.
    199 
    200   @param  FvDevice              A pointer to the FvDevice.
    201 
    202 **/
    203 VOID
    204 FwVolInheritAuthenticationStatus (
    205   IN FV_DEVICE  *FvDevice
    206   )
    207 {
    208   EFI_STATUS                        Status;
    209   EFI_FIRMWARE_VOLUME_HEADER        *CachedFvHeader;
    210   EFI_FIRMWARE_VOLUME_EXT_HEADER    *CachedFvExtHeader;
    211   EFI_FIRMWARE_VOLUME2_PROTOCOL     *ParentFvProtocol;
    212   UINTN                             Key;
    213   EFI_GUID                          FileNameGuid;
    214   EFI_FV_FILETYPE                   FileType;
    215   EFI_FV_FILE_ATTRIBUTES            FileAttributes;
    216   UINTN                             FileSize;
    217   EFI_SECTION_TYPE                  SectionType;
    218   UINT32                            AuthenticationStatus;
    219   EFI_FIRMWARE_VOLUME_HEADER        *FvHeader;
    220   EFI_FIRMWARE_VOLUME_EXT_HEADER    *FvExtHeader;
    221   UINTN                             BufferSize;
    222 
    223   CachedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FvDevice->CachedFv;
    224 
    225   if (FvDevice->Fv.ParentHandle != NULL) {
    226     //
    227     // By Parent Handle, find out the FV image file and section(in another firmware volume) where the firmware volume came from
    228     //
    229     Status = gBS->HandleProtocol (FvDevice->Fv.ParentHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &ParentFvProtocol);
    230     if (!EFI_ERROR (Status) && (ParentFvProtocol != NULL)) {
    231       Key = 0;
    232       do {
    233         FileType = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;
    234         Status = ParentFvProtocol->GetNextFile (
    235                                      ParentFvProtocol,
    236                                      &Key,
    237                                      &FileType,
    238                                      &FileNameGuid,
    239                                      &FileAttributes,
    240                                      &FileSize
    241                                      );
    242         if (EFI_ERROR (Status)) {
    243           return;
    244         }
    245 
    246         SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
    247         FvHeader = NULL;
    248         BufferSize = 0;
    249         Status = ParentFvProtocol->ReadSection (
    250                                      ParentFvProtocol,
    251                                      &FileNameGuid,
    252                                      SectionType,
    253                                      0,
    254                                      (VOID **) &FvHeader,
    255                                      &BufferSize,
    256                                      &AuthenticationStatus
    257                                      );
    258         if (!EFI_ERROR (Status)) {
    259           if ((FvHeader->FvLength == CachedFvHeader->FvLength) &&
    260               (FvHeader->ExtHeaderOffset == CachedFvHeader->ExtHeaderOffset)) {
    261             if (FvHeader->ExtHeaderOffset !=0) {
    262               //
    263               // Both FVs contain extension header, then compare their FV Name GUID
    264               //
    265               FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) FvHeader + FvHeader->ExtHeaderOffset);
    266               CachedFvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINTN) CachedFvHeader + CachedFvHeader->ExtHeaderOffset);
    267               if (CompareGuid (&FvExtHeader->FvName, &CachedFvExtHeader->FvName)) {
    268                 //
    269                 // Found the FV image section where the firmware volume came from,
    270                 // and then inherit authentication status from it.
    271                 //
    272                 FvDevice->AuthenticationStatus = AuthenticationStatus;
    273                 FreePool ((VOID *) FvHeader);
    274                 return;
    275               }
    276             } else {
    277               //
    278               // Both FVs don't contain extension header, then compare their whole FV Image.
    279               //
    280               if (CompareMem ((VOID *) FvHeader, (VOID *) CachedFvHeader, (UINTN) FvHeader->FvLength) == 0) {
    281                 //
    282                 // Found the FV image section where the firmware volume came from
    283                 // and then inherit authentication status from it.
    284                 //
    285                 FvDevice->AuthenticationStatus = AuthenticationStatus;
    286                 FreePool ((VOID *) FvHeader);
    287                 return;
    288               }
    289             }
    290           }
    291           FreePool ((VOID *) FvHeader);
    292         }
    293       } while (TRUE);
    294     }
    295   }
    296 }
    297 
    298 /**
    299   Check if an FV is consistent and allocate cache for it.
    300 
    301   @param  FvDevice              A pointer to the FvDevice to be checked.
    302 
    303   @retval EFI_OUT_OF_RESOURCES  No enough buffer could be allocated.
    304   @retval EFI_VOLUME_CORRUPTED  File system is corrupted.
    305   @retval EFI_SUCCESS           FV is consistent and cache is allocated.
    306 
    307 **/
    308 EFI_STATUS
    309 FvCheck (
    310   IN FV_DEVICE  *FvDevice
    311   )
    312 {
    313   EFI_STATUS                          Status;
    314   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
    315   EFI_FVB_ATTRIBUTES_2                FvbAttributes;
    316   EFI_FV_BLOCK_MAP_ENTRY              *BlockMap;
    317   EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;
    318   EFI_FIRMWARE_VOLUME_EXT_HEADER      *FwVolExtHeader;
    319   UINT8                               *FwCache;
    320   LBA_ENTRY                           *LbaEntry;
    321   FREE_SPACE_ENTRY                    *FreeSpaceEntry;
    322   FFS_FILE_LIST_ENTRY                 *FfsFileEntry;
    323   UINT8                               *LbaStart;
    324   UINTN                               Index;
    325   EFI_LBA                             LbaIndex;
    326   UINT8                               *Ptr;
    327   UINTN                               Size;
    328   UINT8                               *FreeStart;
    329   UINTN                               FreeSize;
    330   UINT8                               ErasePolarity;
    331   EFI_FFS_FILE_STATE                  FileState;
    332   UINT8                               *TopFvAddress;
    333   UINTN                               TestLength;
    334   EFI_PHYSICAL_ADDRESS                BaseAddress;
    335 
    336   Fvb     = FvDevice->Fvb;
    337 
    338   Status  = Fvb->GetAttributes (Fvb, &FvbAttributes);
    339   if (EFI_ERROR (Status)) {
    340     return Status;
    341   }
    342 
    343   InitializeListHead (&FvDevice->LbaHeader);
    344   InitializeListHead (&FvDevice->FreeSpaceHeader);
    345   InitializeListHead (&FvDevice->FfsFileListHeader);
    346 
    347   FwVolHeader = NULL;
    348   Status = GetFwVolHeader (Fvb, &FwVolHeader);
    349   if (EFI_ERROR (Status)) {
    350     return Status;
    351   }
    352   ASSERT (FwVolHeader != NULL);
    353 
    354   FvDevice->IsFfs3Fv = CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
    355 
    356   //
    357   // Double Check firmware volume header here
    358   //
    359   if (!VerifyFvHeaderChecksum (FwVolHeader)) {
    360     FreePool (FwVolHeader);
    361     return EFI_VOLUME_CORRUPTED;
    362   }
    363 
    364   BlockMap = FwVolHeader->BlockMap;
    365 
    366   //
    367   // FwVolHeader->FvLength is the whole FV length including FV header
    368   //
    369   FwCache = AllocateZeroPool ((UINTN) FwVolHeader->FvLength);
    370   if (FwCache == NULL) {
    371     FreePool (FwVolHeader);
    372     return EFI_OUT_OF_RESOURCES;
    373   }
    374 
    375   FvDevice->CachedFv = (EFI_PHYSICAL_ADDRESS) (UINTN) FwCache;
    376 
    377   //
    378   // Copy to memory
    379   //
    380   LbaStart  = FwCache;
    381   LbaIndex  = 0;
    382   Ptr       = NULL;
    383 
    384   if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
    385     //
    386     // Get volume base address
    387     //
    388     Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);
    389     if (EFI_ERROR (Status)) {
    390       FreePool (FwVolHeader);
    391       return Status;
    392     }
    393 
    394     Ptr = (UINT8 *) ((UINTN) BaseAddress);
    395 
    396     DEBUG((EFI_D_INFO, "Fv Base Address is 0x%LX\n", BaseAddress));
    397   }
    398   //
    399   // Copy whole FV into the memory
    400   //
    401   while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {
    402 
    403     for (Index = 0; Index < BlockMap->NumBlocks; Index++) {
    404       LbaEntry = AllocatePool (sizeof (LBA_ENTRY));
    405       if (LbaEntry == NULL) {
    406         FreePool (FwVolHeader);
    407         FreeFvDeviceResource (FvDevice);
    408         return EFI_OUT_OF_RESOURCES;
    409       }
    410 
    411       LbaEntry->LbaIndex        = LbaIndex;
    412       LbaEntry->StartingAddress = LbaStart;
    413       LbaEntry->BlockLength     = BlockMap->Length;
    414 
    415       //
    416       // Copy each LBA into memory
    417       //
    418       if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
    419 
    420         CopyMem (LbaStart, Ptr, BlockMap->Length);
    421         Ptr += BlockMap->Length;
    422 
    423       } else {
    424 
    425         Size = BlockMap->Length;
    426         Status = Fvb->Read (
    427                         Fvb,
    428                         LbaIndex,
    429                         0,
    430                         &Size,
    431                         LbaStart
    432                         );
    433         //
    434         // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length
    435         //
    436         if (EFI_ERROR (Status)) {
    437           FreePool (FwVolHeader);
    438           FreeFvDeviceResource (FvDevice);
    439           return Status;
    440         }
    441 
    442       }
    443 
    444       LbaIndex++;
    445       LbaStart += BlockMap->Length;
    446 
    447       InsertTailList (&FvDevice->LbaHeader, &LbaEntry->Link);
    448     }
    449 
    450     BlockMap++;
    451   }
    452 
    453   FvDevice->FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FwCache;
    454 
    455   //
    456   // it is not used any more, so free FwVolHeader
    457   //
    458   FreePool (FwVolHeader);
    459 
    460   //
    461   // Scan to check the free space & File list
    462   //
    463   if ((FvbAttributes & EFI_FVB2_ERASE_POLARITY) != 0) {
    464     ErasePolarity = 1;
    465   } else {
    466     ErasePolarity = 0;
    467   }
    468 
    469   FvDevice->ErasePolarity = ErasePolarity;
    470 
    471   //
    472   // go through the whole FV cache, check the consistence of the FV
    473   //
    474   if (FvDevice->FwVolHeader->ExtHeaderOffset != 0) {
    475     //
    476     // Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
    477     //
    478     FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->ExtHeaderOffset);
    479     Ptr = (UINT8 *) FwVolExtHeader + FwVolExtHeader->ExtHeaderSize;
    480     Ptr = (UINT8 *) ALIGN_POINTER (Ptr, 8);
    481   } else {
    482     Ptr = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->HeaderLength);
    483   }
    484   TopFvAddress = (UINT8 *) (UINTN) (FvDevice->CachedFv + FvDevice->FwVolHeader->FvLength);
    485 
    486   //
    487   // Build FFS list & Free Space List here
    488   //
    489   while (Ptr < TopFvAddress) {
    490     TestLength = TopFvAddress - Ptr;
    491 
    492     if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
    493       TestLength = sizeof (EFI_FFS_FILE_HEADER);
    494     }
    495 
    496     if (IsBufferErased (ErasePolarity, Ptr, TestLength)) {
    497       //
    498       // We found free space
    499       //
    500       FreeStart = Ptr;
    501       FreeSize  = 0;
    502 
    503       do {
    504         TestLength = TopFvAddress - Ptr;
    505 
    506         if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) {
    507           TestLength = sizeof (EFI_FFS_FILE_HEADER);
    508         }
    509 
    510         if (!IsBufferErased (ErasePolarity, Ptr, TestLength)) {
    511           break;
    512         }
    513 
    514         FreeSize += TestLength;
    515         Ptr += TestLength;
    516       } while (Ptr < TopFvAddress);
    517 
    518       FreeSpaceEntry = AllocateZeroPool (sizeof (FREE_SPACE_ENTRY));
    519       if (FreeSpaceEntry == NULL) {
    520         FreeFvDeviceResource (FvDevice);
    521         return EFI_OUT_OF_RESOURCES;
    522       }
    523       //
    524       // Create a Free space entry
    525       //
    526       FreeSpaceEntry->StartingAddress = FreeStart;
    527       FreeSpaceEntry->Length          = FreeSize;
    528       InsertTailList (&FvDevice->FreeSpaceHeader, &FreeSpaceEntry->Link);
    529       continue;
    530     }
    531     //
    532     // double check boundry
    533     //
    534     if (TestLength < sizeof (EFI_FFS_FILE_HEADER)) {
    535       break;
    536     }
    537 
    538     if (!IsValidFFSHeader (
    539           FvDevice->ErasePolarity,
    540           (EFI_FFS_FILE_HEADER *) Ptr
    541           )) {
    542       FileState = GetFileState (
    543                     FvDevice->ErasePolarity,
    544                     (EFI_FFS_FILE_HEADER *) Ptr
    545                     );
    546       if ((FileState == EFI_FILE_HEADER_INVALID) || (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
    547         if (IS_FFS_FILE2 (Ptr)) {
    548           if (!FvDevice->IsFfs3Fv) {
    549             DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));
    550           }
    551           Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER2);
    552         } else {
    553           Ptr = Ptr + sizeof (EFI_FFS_FILE_HEADER);
    554         }
    555 
    556         continue;
    557 
    558       } else {
    559         //
    560         // File system is corrputed, return
    561         //
    562         FreeFvDeviceResource (FvDevice);
    563         return EFI_VOLUME_CORRUPTED;
    564       }
    565     }
    566 
    567     if (IS_FFS_FILE2 (Ptr)) {
    568       ASSERT (FFS_FILE2_SIZE (Ptr) > 0x00FFFFFF);
    569       if (!FvDevice->IsFfs3Fv) {
    570         DEBUG ((EFI_D_ERROR, "Found a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &((EFI_FFS_FILE_HEADER *) Ptr)->Name));
    571         Ptr = Ptr + FFS_FILE2_SIZE (Ptr);
    572         //
    573         // Adjust Ptr to the next 8-byte aligned boundry.
    574         //
    575         while (((UINTN) Ptr & 0x07) != 0) {
    576           Ptr++;
    577         }
    578         continue;
    579       }
    580     }
    581 
    582     if (IsValidFFSFile (FvDevice, (EFI_FFS_FILE_HEADER *) Ptr)) {
    583       FileState = GetFileState (
    584                     FvDevice->ErasePolarity,
    585                     (EFI_FFS_FILE_HEADER *) Ptr
    586                     );
    587 
    588       //
    589       // check for non-deleted file
    590       //
    591       if (FileState != EFI_FILE_DELETED) {
    592         //
    593         // Create a FFS list entry for each non-deleted file
    594         //
    595         FfsFileEntry = AllocateZeroPool (sizeof (FFS_FILE_LIST_ENTRY));
    596         if (FfsFileEntry == NULL) {
    597           FreeFvDeviceResource (FvDevice);
    598           return EFI_OUT_OF_RESOURCES;
    599         }
    600 
    601         FfsFileEntry->FfsHeader = Ptr;
    602         InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link);
    603       }
    604 
    605       if (IS_FFS_FILE2 (Ptr)) {
    606         Ptr = Ptr + FFS_FILE2_SIZE (Ptr);
    607       } else {
    608         Ptr = Ptr + FFS_FILE_SIZE (Ptr);
    609       }
    610 
    611       //
    612       // Adjust Ptr to the next 8-byte aligned boundry.
    613       //
    614       while (((UINTN) Ptr & 0x07) != 0) {
    615         Ptr++;
    616       }
    617     } else {
    618       //
    619       // File system is corrupted, return
    620       //
    621       FreeFvDeviceResource (FvDevice);
    622       return EFI_VOLUME_CORRUPTED;
    623     }
    624   }
    625 
    626   FvDevice->CurrentFfsFile = NULL;
    627 
    628   return EFI_SUCCESS;
    629 }
    630 
    631 /**
    632   Entry point function does install/reinstall FV2 protocol with full functionality.
    633 
    634   @param ImageHandle   A handle for the image that is initializing this driver
    635   @param SystemTable   A pointer to the EFI system table
    636 
    637   @retval EFI_SUCCESS    At least one Fv protocol install/reinstall successfully.
    638   @retval EFI_NOT_FOUND  No FV protocol install/reinstall successfully.
    639 **/
    640 EFI_STATUS
    641 EFIAPI
    642 FwVolDriverInit (
    643   IN EFI_HANDLE                   ImageHandle,
    644   IN EFI_SYSTEM_TABLE             *SystemTable
    645   )
    646 {
    647   EFI_STATUS                          Status;
    648   EFI_HANDLE                          *HandleBuffer;
    649   UINTN                               HandleCount;
    650   UINTN                               Index;
    651   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
    652   EFI_FIRMWARE_VOLUME2_PROTOCOL       *Fv;
    653   FV_DEVICE                           *FvDevice;
    654   EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;
    655   BOOLEAN                             Reinstall;
    656   BOOLEAN                             InstallFlag;
    657 
    658   DEBUG ((EFI_D_INFO, "=========FwVol writable driver installed\n"));
    659   InstallFlag   =  FALSE;
    660   //
    661   // Locate all handles of Fvb protocol
    662   //
    663   Status = gBS->LocateHandleBuffer (
    664                   ByProtocol,
    665                   &gEfiFirmwareVolumeBlockProtocolGuid,
    666                   NULL,
    667                   &HandleCount,
    668                   &HandleBuffer
    669                   );
    670   if (EFI_ERROR (Status)) {
    671     return EFI_NOT_FOUND;
    672   }
    673 
    674   for (Index = 0; Index < HandleCount; Index += 1) {
    675     Status = gBS->HandleProtocol (
    676                     HandleBuffer[Index],
    677                     &gEfiFirmwareVolumeBlockProtocolGuid,
    678                     (VOID **) &Fvb
    679                     );
    680     if (EFI_ERROR (Status)) {
    681       continue;
    682     }
    683 
    684     FwVolHeader = NULL;
    685     Status = GetFwVolHeader (Fvb, &FwVolHeader);
    686     if (EFI_ERROR (Status)) {
    687       continue;
    688     }
    689     ASSERT (FwVolHeader != NULL);
    690     FreePool (FwVolHeader);
    691 
    692     Reinstall = FALSE;
    693     //
    694     // Check if there is an FV protocol already installed in that handle
    695     //
    696     Status = gBS->HandleProtocol (
    697                     HandleBuffer[Index],
    698                     &gEfiFirmwareVolume2ProtocolGuid,
    699                     (VOID **) &Fv
    700                     );
    701     if (!EFI_ERROR (Status)) {
    702       Reinstall = TRUE;
    703     }
    704     //
    705     // FwVol protocol on the handle so create a new one
    706     //
    707     FvDevice = AllocateZeroPool (sizeof (FV_DEVICE));
    708     if (FvDevice == NULL) {
    709       goto Done;
    710     }
    711 
    712     FvDevice->Signature = FV_DEVICE_SIGNATURE;
    713     FvDevice->Fvb       = Fvb;
    714 
    715     //
    716     // Firmware Volume Protocol interface
    717     //
    718     FvDevice->Fv.GetVolumeAttributes  = FvGetVolumeAttributes;
    719     FvDevice->Fv.SetVolumeAttributes  = FvSetVolumeAttributes;
    720     FvDevice->Fv.ReadFile             = FvReadFile;
    721     FvDevice->Fv.ReadSection          = FvReadFileSection;
    722     FvDevice->Fv.WriteFile            = FvWriteFile;
    723     FvDevice->Fv.GetNextFile          = FvGetNextFile;
    724     FvDevice->Fv.KeySize              = KEYSIZE;
    725     FvDevice->Fv.GetInfo              = FvGetVolumeInfo;
    726     FvDevice->Fv.SetInfo              = FvSetVolumeInfo;
    727     FvDevice->Fv.ParentHandle         = Fvb->ParentHandle;
    728 
    729     Status = FvCheck (FvDevice);
    730     if (EFI_ERROR (Status)) {
    731       //
    732       // The file system is not consistence
    733       //
    734       FreePool (FvDevice);
    735       continue;
    736     }
    737 
    738     FwVolInheritAuthenticationStatus (FvDevice);
    739 
    740     if (Reinstall) {
    741       //
    742       // Reinstall an New FV protocol
    743       //
    744       // FvDevice = FV_DEVICE_FROM_THIS (Fv);
    745       // FvDevice->Fvb = Fvb;
    746       // FreeFvDeviceResource (FvDevice);
    747       //
    748       Status = gBS->ReinstallProtocolInterface (
    749                       HandleBuffer[Index],
    750                       &gEfiFirmwareVolume2ProtocolGuid,
    751                       Fv,
    752                       &FvDevice->Fv
    753                       );
    754       if (!EFI_ERROR (Status)) {
    755         InstallFlag = TRUE;
    756       } else {
    757         FreePool (FvDevice);
    758       }
    759 
    760       DEBUG ((EFI_D_INFO, "Reinstall FV protocol as writable - %r\n", Status));
    761       ASSERT_EFI_ERROR (Status);
    762     } else {
    763       //
    764       // Install an New FV protocol
    765       //
    766       Status = gBS->InstallProtocolInterface (
    767                       &FvDevice->Handle,
    768                       &gEfiFirmwareVolume2ProtocolGuid,
    769                       EFI_NATIVE_INTERFACE,
    770                       &FvDevice->Fv
    771                       );
    772       if (!EFI_ERROR (Status)) {
    773         InstallFlag = TRUE;
    774       } else {
    775         FreePool (FvDevice);
    776       }
    777 
    778       DEBUG ((EFI_D_INFO, "Install FV protocol as writable - %r\n", Status));
    779       ASSERT_EFI_ERROR (Status);
    780     }
    781   }
    782 
    783 Done:
    784   //
    785   // As long as one Fv protocol install/reinstall successfully,
    786   // success should return to ensure this image will be not unloaded.
    787   // Otherwise, new Fv protocols are corrupted by other loaded driver.
    788   //
    789   if (InstallFlag) {
    790     return EFI_SUCCESS;
    791   }
    792 
    793   //
    794   // No FV protocol install/reinstall successfully.
    795   // EFI_NOT_FOUND should return to ensure this image will be unloaded.
    796   //
    797   return EFI_NOT_FOUND;
    798 }
    799