]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/Library/PrePiLib/FwVol.c
ARM Packages: Fixed line endings
[mirror_edk2.git] / EmbeddedPkg / Library / PrePiLib / FwVol.c
index 75d28a725732d0a0e3bc95b38f6bf064cb6c80ff..9e4cdd002ec6143df77120186e95aa732d8ee225 100644 (file)
-/** @file
-  Implementation of the 6 PEI Ffs (FV) APIs in library form.
-  
-  This code only knows about a FV if it has a EFI_HOB_TYPE_FV entry in the HOB list
-
-  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-  
-  This program and the accompanying materials
-  are licensed and made available under the terms and conditions of the BSD License
-  which accompanies this distribution.  The full text of the license may be found at
-  http://opensource.org/licenses/bsd-license.php
-
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <PrePi.h>
-#include <Library/ExtractGuidedSectionLib.h>
-
-
-#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
-  (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
-
-
-/**
-  Returns the highest bit set of the State field
-  
-  @param ErasePolarity   Erase Polarity  as defined by EFI_FVB2_ERASE_POLARITY
-                         in the Attributes field.
-  @param FfsHeader       Pointer to FFS File Header
-                      
-
-  @retval the highest bit in the State field
-
-**/
-STATIC
-EFI_FFS_FILE_STATE
-GetFileState(
-  IN UINT8                ErasePolarity,
-  IN EFI_FFS_FILE_HEADER  *FfsHeader
-  )
-{
-  EFI_FFS_FILE_STATE  FileState;
-  EFI_FFS_FILE_STATE  HighestBit;
-
-  FileState = FfsHeader->State;
-
-  if (ErasePolarity != 0) {
-    FileState = (EFI_FFS_FILE_STATE)~FileState;
-  }
-
-  HighestBit = 0x80;
-  while (HighestBit != 0 && (HighestBit & FileState) == 0) {
-    HighestBit >>= 1;
-  }
-
-  return HighestBit;
-} 
-
-
-/**
-  Calculates the checksum of the header of a file.
-  The header is a zero byte checksum, so zero means header is good
-  
-  @param FfsHeader       Pointer to FFS File Header
-                      
-  @retval Checksum of the header
-
-**/
-STATIC
-UINT8
-CalculateHeaderChecksum (
-  IN EFI_FFS_FILE_HEADER  *FileHeader
-  )
-{
-  UINT8   *Ptr;
-  UINTN   Index;
-  UINT8   Sum;
-  
-  Sum = 0;
-  Ptr = (UINT8 *)FileHeader;
-
-  for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {
-    Sum = (UINT8)(Sum + Ptr[Index]);
-    Sum = (UINT8)(Sum + Ptr[Index+1]);
-    Sum = (UINT8)(Sum + Ptr[Index+2]);
-    Sum = (UINT8)(Sum + Ptr[Index+3]);
-  }
-
-  for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
-    Sum = (UINT8)(Sum + Ptr[Index]);
-  }
-  
-  //
-  // State field (since this indicates the different state of file). 
-  //
-  Sum = (UINT8)(Sum - FileHeader->State);
-  //
-  // Checksum field of the file is not part of the header checksum.
-  //
-  Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);
-
-  return Sum;
-}
-
-
-/**
-  Given a FileHandle return the VolumeHandle
-  
-  @param FileHandle   File handle to look up
-  @param VolumeHandle Match for FileHandle
-                      
-  @retval TRUE  VolumeHandle is valid
-
-**/
-STATIC
-BOOLEAN
-EFIAPI
-FileHandleToVolume (
-  IN   EFI_PEI_FILE_HANDLE     FileHandle,
-  OUT  EFI_PEI_FV_HANDLE       *VolumeHandle
-  )
-{
-  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader;
-  EFI_PEI_HOB_POINTERS        Hob;
-
-  Hob.Raw = GetHobList ();
-  if (Hob.Raw == NULL) {
-    return FALSE;
-  }
-  
-  do {
-    Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);
-    if (Hob.Raw != NULL) {
-      FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(Hob.FirmwareVolume->BaseAddress);
-      if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) &&   \
-          ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {
-        *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader;
-        return TRUE;
-      }
-
-      Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));
-    }
-  } while (Hob.Raw != NULL);
-    
-  return FALSE;
-}
-
-
-
-/**
-  Given the input file pointer, search for the next matching file in the
-  FFS volume as defined by SearchType. The search starts from FileHeader inside
-  the Firmware Volume defined by FwVolHeader.
-  
-  @param FileHandle   File handle to look up
-  @param VolumeHandle Match for FileHandle
-                      
-
-**/
-EFI_STATUS
-FindFileEx (
-  IN  CONST EFI_PEI_FV_HANDLE        FvHandle,
-  IN  CONST EFI_GUID                 *FileName,   OPTIONAL
-  IN        EFI_FV_FILETYPE          SearchType,
-  IN OUT    EFI_PEI_FILE_HANDLE      *FileHandle
-  )
-{
-  EFI_FIRMWARE_VOLUME_HEADER           *FwVolHeader;
-  EFI_FFS_FILE_HEADER                   **FileHeader;
-  EFI_FFS_FILE_HEADER                   *FfsFileHeader;
-  EFI_FIRMWARE_VOLUME_EXT_HEADER        *FwVolExHeaderInfo;
-  UINT32                                FileLength;
-  UINT32                                FileOccupiedSize;
-  UINT32                                FileOffset;
-  UINT64                                FvLength;
-  UINT8                                 ErasePolarity;
-  UINT8                                 FileState;
-
-  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;
-  FileHeader  = (EFI_FFS_FILE_HEADER **)FileHandle;
-
-  FvLength = FwVolHeader->FvLength;
-  if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
-    ErasePolarity = 1;
-  } else {
-    ErasePolarity = 0;
-  }
-
-  //
-  // If FileHeader is not specified (NULL) or FileName is not NULL,
-  // start with the first file in the firmware volume.  Otherwise,
-  // start from the FileHeader.
-  //
-  if ((*FileHeader == NULL) || (FileName != NULL)) {
-    FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
-    if (FwVolHeader->ExtHeaderOffset != 0) {
-      FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);
-      FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize);
-    }
-  } else {
-    //
-    // Length is 24 bits wide so mask upper 8 bits
-    // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
-    //
-    FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;
-    FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
-    FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
-  }
-  
-  FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
-  ASSERT (FileOffset <= 0xFFFFFFFF);
-
-  while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
-    //
-    // Get FileState which is the highest bit of the State 
-    //
-    FileState = GetFileState (ErasePolarity, FfsFileHeader);
-
-    switch (FileState) {
-
-    case EFI_FILE_HEADER_INVALID:
-      FileOffset += sizeof(EFI_FFS_FILE_HEADER);
-      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
-      break;
-        
-    case EFI_FILE_DATA_VALID:
-    case EFI_FILE_MARKED_FOR_UPDATE:
-      if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
-        ASSERT (FALSE);
-        *FileHeader = NULL;
-        return EFI_NOT_FOUND;
-      }
-
-      FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
-      FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
-
-      if (FileName != NULL) {
-        if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {
-          *FileHeader = FfsFileHeader;
-          return EFI_SUCCESS;
-        }
-      } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) && 
-                 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) { 
-        *FileHeader = FfsFileHeader;
-        return EFI_SUCCESS;
-      }
-
-      FileOffset += FileOccupiedSize; 
-      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
-      break;
-    
-    case EFI_FILE_DELETED:
-      FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
-      FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
-      FileOffset += FileOccupiedSize;
-      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
-      break;
-
-    default:
-      *FileHeader = NULL;
-      return EFI_NOT_FOUND;
-    } 
-  }
-
-  
-  *FileHeader = NULL;
-  return EFI_NOT_FOUND;  
-}
-
-
-/**
-  Go through the file to search SectionType section,
-  when meeting an encapsuled section. 
-  
-  @param  SectionType  - Filter to find only section of this type.
-  @param  Section      - From where to search.
-  @param  SectionSize  - The file size to search.
-  @param  OutputBuffer - Pointer to the section to search.
-                      
-  @retval EFI_SUCCESS
-**/
-EFI_STATUS
-FfsProcessSection (
-  IN EFI_SECTION_TYPE           SectionType,
-  IN EFI_COMMON_SECTION_HEADER  *Section,
-  IN UINTN                      SectionSize,
-  OUT VOID                      **OutputBuffer
-  )
-{
-  EFI_STATUS                              Status;
-  UINT32                                  SectionLength;
-  UINT32                                  ParsedLength;
-  EFI_COMPRESSION_SECTION                 *CompressionSection;
-  UINTN                                   DstBufferSize;
-  VOID                                    *ScratchBuffer;
-  UINT32                                  ScratchBufferSize;
-  VOID                                    *DstBuffer;
-  UINT16                                  SectionAttribute;
-  UINT32                                  AuthenticationStatus;
-
-
-  *OutputBuffer = NULL;
-  ParsedLength  = 0;
-  Status        = EFI_NOT_FOUND;
-  while (ParsedLength < SectionSize) {
-    if (Section->Type == SectionType) {
-      *OutputBuffer = (VOID *)(Section + 1);
-
-      return EFI_SUCCESS;
-    } else if ((Section->Type == EFI_SECTION_COMPRESSION) || (Section->Type == EFI_SECTION_GUID_DEFINED)) {
-    
-      if (Section->Type == EFI_SECTION_COMPRESSION) {
-        CompressionSection  = (EFI_COMPRESSION_SECTION *) Section;
-        SectionLength       = *(UINT32 *)Section->Size & 0x00FFFFFF;
-        
-        if (CompressionSection->CompressionType != EFI_STANDARD_COMPRESSION) {
-          return EFI_UNSUPPORTED;
-        }
-
-        Status = UefiDecompressGetInfo (
-                   (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
-                   (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
-                   (UINT32 *) &DstBufferSize,
-                   &ScratchBufferSize
-                   );
-      } else if (Section->Type == EFI_SECTION_GUID_DEFINED) {
-        Status = ExtractGuidedSectionGetInfo (
-                   Section,
-                   (UINT32 *) &DstBufferSize,
-                   &ScratchBufferSize,
-                   &SectionAttribute
-                   );
-      }
-      
-      if (EFI_ERROR (Status)) {
-        //
-        // GetInfo failed
-        //
-        DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));
-        return EFI_NOT_FOUND;
-      }
-      //
-      // Allocate scratch buffer
-      //
-      ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
-      if (ScratchBuffer == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
-      //
-      // Allocate destination buffer, extra one page for adjustment 
-      //
-      DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
-      if (DstBuffer == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
-      //
-      // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
-      // to make section data at page alignment.
-      //
-      DstBuffer = (UINT8 *)DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
-      //
-      // Call decompress function
-      //
-      if (Section->Type == EFI_SECTION_COMPRESSION) {
-        Status = UefiDecompress (
-                    (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
-                    DstBuffer,
-                    ScratchBuffer
-                    );
-      } else if (Section->Type == EFI_SECTION_GUID_DEFINED) {
-        Status = ExtractGuidedSectionDecode (
-                    Section,
-                    &DstBuffer,
-                    ScratchBuffer,
-                    &AuthenticationStatus
-                    );
-      }
-      
-      if (EFI_ERROR (Status)) {
-        //
-        // Decompress failed
-        //
-        DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));
-        return EFI_NOT_FOUND;
-      } else {
-        return FfsProcessSection (
-                SectionType, 
-                DstBuffer, 
-                DstBufferSize, 
-                OutputBuffer 
-                );
-       }        
-    }
-
-    //
-    // Size is 24 bits wide so mask upper 8 bits. 
-    // SectionLength is adjusted it is 4 byte aligned.
-    // Go to the next section
-    //
-    SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
-    SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
-    ASSERT (SectionLength != 0);
-    ParsedLength += SectionLength;
-    Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
-  }
-  
-  return EFI_NOT_FOUND;
-}
-
-
-
-/**
-  This service enables discovery sections of a given type within a valid FFS file.
-
-  @param  SearchType            The value of the section type to find.
-  @param  FfsFileHeader         A pointer to the file header that contains the set of sections to
-                                be searched.
-  @param  SectionData           A pointer to the discovered section, if successful.
-
-  @retval EFI_SUCCESS           The section was found.
-  @retval EFI_NOT_FOUND         The section was not found.
-
-**/
-EFI_STATUS
-EFIAPI
-FfsFindSectionData (
-  IN EFI_SECTION_TYPE           SectionType,
-  IN EFI_PEI_FILE_HANDLE        FileHandle,
-  OUT VOID                      **SectionData
-  )
-{
-  EFI_FFS_FILE_HEADER                     *FfsFileHeader;
-  UINT32                                  FileSize;
-  EFI_COMMON_SECTION_HEADER               *Section;
-
-  FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
-
-  //
-  // Size is 24 bits wide so mask upper 8 bits. 
-  // Does not include FfsFileHeader header size
-  // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
-  //
-  Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);
-  FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
-  FileSize -= sizeof (EFI_FFS_FILE_HEADER);
-
-  return FfsProcessSection (
-          SectionType, 
-          Section, 
-          FileSize, 
-          SectionData
-          );
-}
-
-
-
-
-
-
-/**
-  This service enables discovery of additional firmware files.
-
-  @param  SearchType            A filter to find files only of this type.
-  @param  FwVolHeader           Pointer to the firmware volume header of the volume to search.
-                                This parameter must point to a valid FFS volume.
-  @param  FileHeader            Pointer to the current file from which to begin searching.
-
-  @retval EFI_SUCCESS           The file was found.
-  @retval EFI_NOT_FOUND         The file was not found.
-  @retval EFI_NOT_FOUND         The header checksum was not zero.
-
-**/
-EFI_STATUS
-EFIAPI
-FfsFindNextFile (
-  IN UINT8                       SearchType,
-  IN EFI_PEI_FV_HANDLE           VolumeHandle,
-  IN OUT EFI_PEI_FILE_HANDLE     *FileHandle
-  )
-{
-  return FindFileEx (VolumeHandle, NULL, SearchType, FileHandle);
-}
-
-
-/**
-  This service enables discovery of additional firmware volumes.
-
-  @param  Instance              This instance of the firmware volume to find.  The value 0 is the
-                                Boot Firmware Volume (BFV).
-  @param  FwVolHeader           Pointer to the firmware volume header of the volume to return.
-
-  @retval EFI_SUCCESS           The volume was found.
-  @retval EFI_NOT_FOUND         The volume was not found.
-
-**/
-EFI_STATUS
-EFIAPI
-FfsFindNextVolume (
-  IN UINTN                          Instance,
-  IN OUT EFI_PEI_FV_HANDLE          *VolumeHandle
-  )
-{
-  EFI_PEI_HOB_POINTERS        Hob;
-  
-
-  Hob.Raw = GetHobList ();
-  if (Hob.Raw == NULL) {
-    return EFI_NOT_FOUND;
-  }
-  
-  do {
-    Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);
-    if (Hob.Raw != NULL) {
-      if (Instance-- == 0) {
-        *VolumeHandle = (EFI_PEI_FV_HANDLE)(UINTN)(Hob.FirmwareVolume->BaseAddress);
-        return EFI_SUCCESS;
-      }
-
-      Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));
-    }
-  } while (Hob.Raw != NULL);
-    
-  return EFI_NOT_FOUND;
-
-}
-
-
-/**
-  Find a file in the volume by name
-  
-  @param FileName       A pointer to the name of the file to
-                        find within the firmware volume.
-
-  @param VolumeHandle   The firmware volume to search FileHandle
-                        Upon exit, points to the found file's
-                        handle or NULL if it could not be found.
-
-  @retval EFI_SUCCESS             File was found.
-
-  @retval EFI_NOT_FOUND           File was not found.
-
-  @retval EFI_INVALID_PARAMETER   VolumeHandle or FileHandle or
-                                  FileName was NULL.
-
-**/
-EFI_STATUS
-EFIAPI 
-FfsFindFileByName (
-  IN  CONST EFI_GUID        *FileName,
-  IN  EFI_PEI_FV_HANDLE     VolumeHandle,
-  OUT EFI_PEI_FILE_HANDLE   *FileHandle
-  )
-{
-  EFI_STATUS  Status;
-  if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-  Status = FindFileEx (VolumeHandle, FileName, 0, FileHandle);
-  if (Status == EFI_NOT_FOUND) {
-    *FileHandle = NULL;
-  }
-  return Status;
-}
-
-
-
-
-/**
-  Get information about the file by name.
-
-  @param FileHandle   Handle of the file.
-
-  @param FileInfo     Upon exit, points to the file's
-                      information.
-
-  @retval EFI_SUCCESS             File information returned.
-  
-  @retval EFI_INVALID_PARAMETER   If FileHandle does not
-                                  represent a valid file.
-  
-  @retval EFI_INVALID_PARAMETER   If FileInfo is NULL.
-  
-**/
-EFI_STATUS
-EFIAPI 
-FfsGetFileInfo (
-  IN EFI_PEI_FILE_HANDLE  FileHandle,
-  OUT EFI_FV_FILE_INFO    *FileInfo
-  )
-{
-  UINT8                       FileState;
-  UINT8                       ErasePolarity;
-  EFI_FFS_FILE_HEADER         *FileHeader;
-  EFI_PEI_FV_HANDLE           VolumeHandle;
-
-  if ((FileHandle == NULL) || (FileInfo == NULL)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  VolumeHandle = 0;
-  //
-  // Retrieve the FirmwareVolume which the file resides in.
-  //
-  if (!FileHandleToVolume(FileHandle, &VolumeHandle)) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) {
-    ErasePolarity = 1;
-  } else {
-    ErasePolarity = 0;
-  }
-
-  //
-  // Get FileState which is the highest bit of the State 
-  //
-  FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);
-
-  switch (FileState) {
-    case EFI_FILE_DATA_VALID:
-    case EFI_FILE_MARKED_FOR_UPDATE:
-      break;  
-    default:
-      return EFI_INVALID_PARAMETER;
-    }
-
-  FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
-  CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));
-  FileInfo->FileType = FileHeader->Type;
-  FileInfo->FileAttributes = FileHeader->Attributes;
-  FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) -  sizeof (EFI_FFS_FILE_HEADER);
-  FileInfo->Buffer = (FileHeader + 1);
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Get Information about the volume by name
-
-  @param VolumeHandle   Handle of the volume.
-
-  @param VolumeInfo     Upon exit, points to the volume's
-                        information.
-
-  @retval EFI_SUCCESS             File information returned.
-  
-  @retval EFI_INVALID_PARAMETER   If FileHandle does not
-                                  represent a valid file.
-  
-  @retval EFI_INVALID_PARAMETER   If FileInfo is NULL.
-
-**/
-EFI_STATUS
-EFIAPI 
-FfsGetVolumeInfo (
-  IN EFI_PEI_FV_HANDLE  VolumeHandle,
-  OUT EFI_FV_INFO       *VolumeInfo
-  )
-{
-  EFI_FIRMWARE_VOLUME_HEADER             FwVolHeader;
-  EFI_FIRMWARE_VOLUME_EXT_HEADER         *FwVolExHeaderInfo;
-
-  if (VolumeInfo == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-  
-  //
-  // VolumeHandle may not align at 8 byte, 
-  // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. 
-  // So, Copy FvHeader into the local FvHeader structure.
-  //
-  CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
-  //
-  // Check Fv Image Signature
-  //
-  if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
-    return EFI_INVALID_PARAMETER;
-  }
-  VolumeInfo->FvAttributes = FwVolHeader.Attributes;
-  VolumeInfo->FvStart = (VOID *) VolumeHandle;
-  VolumeInfo->FvSize = FwVolHeader.FvLength;
-  CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));
-
-  if (FwVolHeader.ExtHeaderOffset != 0) {
-    FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);
-    CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));
-  }
-  return EFI_SUCCESS;
-}
-
-
-
-/**
-  Search through every FV until you find a file of type FileType
-
-       @param FileType             File handle of a Fv type file.
-  @param Volumehandle   On succes Volume Handle of the match
-  @param FileHandle     On success File Handle of the match
-  
-  @retval EFI_NOT_FOUND                                FV image can't be found.
-  @retval EFI_SUCCESS                                          Successfully found FileType
-
-**/
-EFI_STATUS
-EFIAPI
-FfsAnyFvFindFirstFile (
-  IN  EFI_FV_FILETYPE       FileType,
-  OUT EFI_PEI_FV_HANDLE     *VolumeHandle,
-  OUT EFI_PEI_FILE_HANDLE   *FileHandle
-  )
-{
-  EFI_STATUS        Status;
-  UINTN             Instance;
-
-  //
-  // Search every FV for the DXE Core
-  //
-  Instance    = 0;
-  *FileHandle = NULL;
-
-  while (1)
-  {
-    Status = FfsFindNextVolume (Instance++, VolumeHandle);
-    if (EFI_ERROR (Status))
-    {
-      break;
-    }
-
-    Status = FfsFindNextFile (FileType, *VolumeHandle, FileHandle);
-    if (!EFI_ERROR (Status))
-    {
-      break;
-    }
-  }
-  
-  return Status;
-}
-
-
-
-/**
-  Get Fv image from the FV type file, then add FV & FV2 Hob.
-
-       @param FileHandle               File handle of a Fv type file.
-
-
-  @retval EFI_NOT_FOUND                                FV image can't be found.
-  @retval EFI_SUCCESS                                          Successfully to process it.
-
-**/
-EFI_STATUS
-EFIAPI
-FfsProcessFvFile (
-  IN  EFI_PEI_FILE_HANDLE   FvFileHandle
-  )
-{
-  EFI_STATUS            Status;
-  EFI_PEI_FV_HANDLE     FvImageHandle;
-  EFI_FV_INFO           FvImageInfo;
-  UINT32                FvAlignment;
-  VOID                  *FvBuffer;
-  EFI_PEI_HOB_POINTERS  HobFv2;
-
-  FvBuffer             = NULL;
-
-
-  //
-  // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
-  // been extracted.
-  //
-  HobFv2.Raw = GetHobList ();
-  while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {
-    if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) {
-      //
-      // this FILE has been dispatched, it will not be dispatched again.
-      //
-      return EFI_SUCCESS;
-    }
-    HobFv2.Raw = GET_NEXT_HOB (HobFv2);
-  }
-
-  //
-  // Find FvImage in FvFile
-  //
-  Status = FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, FvFileHandle, (VOID **)&FvImageHandle);
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-  
-  //
-  // Collect FvImage Info.
-  //
-  ZeroMem (&FvImageInfo, sizeof (FvImageInfo));
-  Status = FfsGetVolumeInfo (FvImageHandle, &FvImageInfo);
-  ASSERT_EFI_ERROR (Status);
-  
-  //
-  // FvAlignment must be more than 8 bytes required by FvHeader structure.
-  //
-  FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);
-  if (FvAlignment < 8) {
-    FvAlignment = 8;
-  }
-  
-  //
-  // Check FvImage
-  //
-  if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {
-    FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);
-    if (FvBuffer == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-    CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);
-    //
-    // Update FvImageInfo after reload FvImage to new aligned memory
-    //
-    FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);
-  }
-
-
-  //
-  // Inform HOB consumer phase, i.e. DXE core, the existance of this FV
-  //
-  BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, FvImageInfo.FvSize);
-  
-  //
-  // Makes the encapsulated volume show up in DXE phase to skip processing of
-  // encapsulated file again.
-  //
-  BuildFv2Hob (
-    (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,
-    FvImageInfo.FvSize,
-    &FvImageInfo.FvName,
-    &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)
-    );
-
-  return EFI_SUCCESS;
-}
-
-
+/** @file\r
+  Implementation of the 6 PEI Ffs (FV) APIs in library form.\r
+  \r
+  This code only knows about a FV if it has a EFI_HOB_TYPE_FV entry in the HOB list\r
+\r
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+  \r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PrePi.h>\r
+#include <Library/ExtractGuidedSectionLib.h>\r
+\r
+\r
+#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \\r
+  (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))\r
+\r
+\r
+/**\r
+  Returns the highest bit set of the State field\r
+  \r
+  @param ErasePolarity   Erase Polarity  as defined by EFI_FVB2_ERASE_POLARITY\r
+                         in the Attributes field.\r
+  @param FfsHeader       Pointer to FFS File Header\r
+                      \r
+\r
+  @retval the highest bit in the State field\r
+\r
+**/\r
+STATIC\r
+EFI_FFS_FILE_STATE\r
+GetFileState(\r
+  IN UINT8                ErasePolarity,\r
+  IN EFI_FFS_FILE_HEADER  *FfsHeader\r
+  )\r
+{\r
+  EFI_FFS_FILE_STATE  FileState;\r
+  EFI_FFS_FILE_STATE  HighestBit;\r
+\r
+  FileState = FfsHeader->State;\r
+\r
+  if (ErasePolarity != 0) {\r
+    FileState = (EFI_FFS_FILE_STATE)~FileState;\r
+  }\r
+\r
+  HighestBit = 0x80;\r
+  while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
+    HighestBit >>= 1;\r
+  }\r
+\r
+  return HighestBit;\r
+} \r
+\r
+\r
+/**\r
+  Calculates the checksum of the header of a file.\r
+  The header is a zero byte checksum, so zero means header is good\r
+  \r
+  @param FfsHeader       Pointer to FFS File Header\r
+                      \r
+  @retval Checksum of the header\r
+\r
+**/\r
+STATIC\r
+UINT8\r
+CalculateHeaderChecksum (\r
+  IN EFI_FFS_FILE_HEADER  *FileHeader\r
+  )\r
+{\r
+  UINT8   *Ptr;\r
+  UINTN   Index;\r
+  UINT8   Sum;\r
+  \r
+  Sum = 0;\r
+  Ptr = (UINT8 *)FileHeader;\r
+\r
+  for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {\r
+    Sum = (UINT8)(Sum + Ptr[Index]);\r
+    Sum = (UINT8)(Sum + Ptr[Index+1]);\r
+    Sum = (UINT8)(Sum + Ptr[Index+2]);\r
+    Sum = (UINT8)(Sum + Ptr[Index+3]);\r
+  }\r
+\r
+  for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {\r
+    Sum = (UINT8)(Sum + Ptr[Index]);\r
+  }\r
+  \r
+  //\r
+  // State field (since this indicates the different state of file). \r
+  //\r
+  Sum = (UINT8)(Sum - FileHeader->State);\r
+  //\r
+  // Checksum field of the file is not part of the header checksum.\r
+  //\r
+  Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);\r
+\r
+  return Sum;\r
+}\r
+\r
+\r
+/**\r
+  Given a FileHandle return the VolumeHandle\r
+  \r
+  @param FileHandle   File handle to look up\r
+  @param VolumeHandle Match for FileHandle\r
+                      \r
+  @retval TRUE  VolumeHandle is valid\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+EFIAPI\r
+FileHandleToVolume (\r
+  IN   EFI_PEI_FILE_HANDLE     FileHandle,\r
+  OUT  EFI_PEI_FV_HANDLE       *VolumeHandle\r
+  )\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader;\r
+  EFI_PEI_HOB_POINTERS        Hob;\r
+\r
+  Hob.Raw = GetHobList ();\r
+  if (Hob.Raw == NULL) {\r
+    return FALSE;\r
+  }\r
+  \r
+  do {\r
+    Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);\r
+    if (Hob.Raw != NULL) {\r
+      FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(Hob.FirmwareVolume->BaseAddress);\r
+      if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) &&   \\r
+          ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {\r
+        *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader;\r
+        return TRUE;\r
+      }\r
+\r
+      Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));\r
+    }\r
+  } while (Hob.Raw != NULL);\r
+    \r
+  return FALSE;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Given the input file pointer, search for the next matching file in the\r
+  FFS volume as defined by SearchType. The search starts from FileHeader inside\r
+  the Firmware Volume defined by FwVolHeader.\r
+  \r
+  @param FileHandle   File handle to look up\r
+  @param VolumeHandle Match for FileHandle\r
+                      \r
+\r
+**/\r
+EFI_STATUS\r
+FindFileEx (\r
+  IN  CONST EFI_PEI_FV_HANDLE        FvHandle,\r
+  IN  CONST EFI_GUID                 *FileName,   OPTIONAL\r
+  IN        EFI_FV_FILETYPE          SearchType,\r
+  IN OUT    EFI_PEI_FILE_HANDLE      *FileHandle\r
+  )\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER           *FwVolHeader;\r
+  EFI_FFS_FILE_HEADER                   **FileHeader;\r
+  EFI_FFS_FILE_HEADER                   *FfsFileHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER        *FwVolExHeaderInfo;\r
+  UINT32                                FileLength;\r
+  UINT32                                FileOccupiedSize;\r
+  UINT32                                FileOffset;\r
+  UINT64                                FvLength;\r
+  UINT8                                 ErasePolarity;\r
+  UINT8                                 FileState;\r
+\r
+  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;\r
+  FileHeader  = (EFI_FFS_FILE_HEADER **)FileHandle;\r
+\r
+  FvLength = FwVolHeader->FvLength;\r
+  if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+    ErasePolarity = 1;\r
+  } else {\r
+    ErasePolarity = 0;\r
+  }\r
+\r
+  //\r
+  // If FileHeader is not specified (NULL) or FileName is not NULL,\r
+  // start with the first file in the firmware volume.  Otherwise,\r
+  // start from the FileHeader.\r
+  //\r
+  if ((*FileHeader == NULL) || (FileName != NULL)) {\r
+    FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);\r
+    if (FwVolHeader->ExtHeaderOffset != 0) {\r
+      FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);\r
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize);\r
+    }\r
+  } else {\r
+    //\r
+    // Length is 24 bits wide so mask upper 8 bits\r
+    // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
+    //\r
+    FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;\r
+    FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);\r
+    FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);\r
+  }\r
+  \r
+  FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);\r
+  ASSERT (FileOffset <= 0xFFFFFFFF);\r
+\r
+  while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {\r
+    //\r
+    // Get FileState which is the highest bit of the State \r
+    //\r
+    FileState = GetFileState (ErasePolarity, FfsFileHeader);\r
+\r
+    switch (FileState) {\r
+\r
+    case EFI_FILE_HEADER_INVALID:\r
+      FileOffset += sizeof(EFI_FFS_FILE_HEADER);\r
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
+      break;\r
+        \r
+    case EFI_FILE_DATA_VALID:\r
+    case EFI_FILE_MARKED_FOR_UPDATE:\r
+      if (CalculateHeaderChecksum (FfsFileHeader) != 0) {\r
+        ASSERT (FALSE);\r
+        *FileHeader = NULL;\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
+      FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
+\r
+      if (FileName != NULL) {\r
+        if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {\r
+          *FileHeader = FfsFileHeader;\r
+          return EFI_SUCCESS;\r
+        }\r
+      } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) && \r
+                 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) { \r
+        *FileHeader = FfsFileHeader;\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      FileOffset += FileOccupiedSize; \r
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
+      break;\r
+    \r
+    case EFI_FILE_DELETED:\r
+      FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
+      FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);\r
+      FileOffset += FileOccupiedSize;\r
+      FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);\r
+      break;\r
+\r
+    default:\r
+      *FileHeader = NULL;\r
+      return EFI_NOT_FOUND;\r
+    } \r
+  }\r
+\r
+  \r
+  *FileHeader = NULL;\r
+  return EFI_NOT_FOUND;  \r
+}\r
+\r
+\r
+/**\r
+  Go through the file to search SectionType section,\r
+  when meeting an encapsuled section. \r
+  \r
+  @param  SectionType  - Filter to find only section of this type.\r
+  @param  Section      - From where to search.\r
+  @param  SectionSize  - The file size to search.\r
+  @param  OutputBuffer - Pointer to the section to search.\r
+                      \r
+  @retval EFI_SUCCESS\r
+**/\r
+EFI_STATUS\r
+FfsProcessSection (\r
+  IN EFI_SECTION_TYPE           SectionType,\r
+  IN EFI_COMMON_SECTION_HEADER  *Section,\r
+  IN UINTN                      SectionSize,\r
+  OUT VOID                      **OutputBuffer\r
+  )\r
+{\r
+  EFI_STATUS                              Status;\r
+  UINT32                                  SectionLength;\r
+  UINT32                                  ParsedLength;\r
+  EFI_COMPRESSION_SECTION                 *CompressionSection;\r
+  UINTN                                   DstBufferSize;\r
+  VOID                                    *ScratchBuffer;\r
+  UINT32                                  ScratchBufferSize;\r
+  VOID                                    *DstBuffer;\r
+  UINT16                                  SectionAttribute;\r
+  UINT32                                  AuthenticationStatus;\r
+\r
+\r
+  *OutputBuffer = NULL;\r
+  ParsedLength  = 0;\r
+  Status        = EFI_NOT_FOUND;\r
+  while (ParsedLength < SectionSize) {\r
+    if (Section->Type == SectionType) {\r
+      *OutputBuffer = (VOID *)(Section + 1);\r
+\r
+      return EFI_SUCCESS;\r
+    } else if ((Section->Type == EFI_SECTION_COMPRESSION) || (Section->Type == EFI_SECTION_GUID_DEFINED)) {\r
+    \r
+      if (Section->Type == EFI_SECTION_COMPRESSION) {\r
+        CompressionSection  = (EFI_COMPRESSION_SECTION *) Section;\r
+        SectionLength       = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
+        \r
+        if (CompressionSection->CompressionType != EFI_STANDARD_COMPRESSION) {\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+\r
+        Status = UefiDecompressGetInfo (\r
+                   (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
+                   (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
+                   (UINT32 *) &DstBufferSize,\r
+                   &ScratchBufferSize\r
+                   );\r
+      } else if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
+        Status = ExtractGuidedSectionGetInfo (\r
+                   Section,\r
+                   (UINT32 *) &DstBufferSize,\r
+                   &ScratchBufferSize,\r
+                   &SectionAttribute\r
+                   );\r
+      }\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // GetInfo failed\r
+        //\r
+        DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
+        return EFI_NOT_FOUND;\r
+      }\r
+      //\r
+      // Allocate scratch buffer\r
+      //\r
+      ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
+      if (ScratchBuffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // Allocate destination buffer, extra one page for adjustment \r
+      //\r
+      DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
+      if (DstBuffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
+      // to make section data at page alignment.\r
+      //\r
+      DstBuffer = (UINT8 *)DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
+      //\r
+      // Call decompress function\r
+      //\r
+      if (Section->Type == EFI_SECTION_COMPRESSION) {\r
+        Status = UefiDecompress (\r
+                    (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
+                    DstBuffer,\r
+                    ScratchBuffer\r
+                    );\r
+      } else if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
+        Status = ExtractGuidedSectionDecode (\r
+                    Section,\r
+                    &DstBuffer,\r
+                    ScratchBuffer,\r
+                    &AuthenticationStatus\r
+                    );\r
+      }\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Decompress failed\r
+        //\r
+        DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));\r
+        return EFI_NOT_FOUND;\r
+      } else {\r
+        return FfsProcessSection (\r
+                SectionType, \r
+                DstBuffer, \r
+                DstBufferSize, \r
+                OutputBuffer \r
+                );\r
+       }        \r
+    }\r
+\r
+    //\r
+    // Size is 24 bits wide so mask upper 8 bits. \r
+    // SectionLength is adjusted it is 4 byte aligned.\r
+    // Go to the next section\r
+    //\r
+    SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;\r
+    SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
+    ASSERT (SectionLength != 0);\r
+    ParsedLength += SectionLength;\r
+    Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);\r
+  }\r
+  \r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+\r
+/**\r
+  This service enables discovery sections of a given type within a valid FFS file.\r
+\r
+  @param  SearchType            The value of the section type to find.\r
+  @param  FfsFileHeader         A pointer to the file header that contains the set of sections to\r
+                                be searched.\r
+  @param  SectionData           A pointer to the discovered section, if successful.\r
+\r
+  @retval EFI_SUCCESS           The section was found.\r
+  @retval EFI_NOT_FOUND         The section was not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FfsFindSectionData (\r
+  IN EFI_SECTION_TYPE           SectionType,\r
+  IN EFI_PEI_FILE_HANDLE        FileHandle,\r
+  OUT VOID                      **SectionData\r
+  )\r
+{\r
+  EFI_FFS_FILE_HEADER                     *FfsFileHeader;\r
+  UINT32                                  FileSize;\r
+  EFI_COMMON_SECTION_HEADER               *Section;\r
+\r
+  FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);\r
+\r
+  //\r
+  // Size is 24 bits wide so mask upper 8 bits. \r
+  // Does not include FfsFileHeader header size\r
+  // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.\r
+  //\r
+  Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);\r
+  FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;\r
+  FileSize -= sizeof (EFI_FFS_FILE_HEADER);\r
+\r
+  return FfsProcessSection (\r
+          SectionType, \r
+          Section, \r
+          FileSize, \r
+          SectionData\r
+          );\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+  This service enables discovery of additional firmware files.\r
+\r
+  @param  SearchType            A filter to find files only of this type.\r
+  @param  FwVolHeader           Pointer to the firmware volume header of the volume to search.\r
+                                This parameter must point to a valid FFS volume.\r
+  @param  FileHeader            Pointer to the current file from which to begin searching.\r
+\r
+  @retval EFI_SUCCESS           The file was found.\r
+  @retval EFI_NOT_FOUND         The file was not found.\r
+  @retval EFI_NOT_FOUND         The header checksum was not zero.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FfsFindNextFile (\r
+  IN UINT8                       SearchType,\r
+  IN EFI_PEI_FV_HANDLE           VolumeHandle,\r
+  IN OUT EFI_PEI_FILE_HANDLE     *FileHandle\r
+  )\r
+{\r
+  return FindFileEx (VolumeHandle, NULL, SearchType, FileHandle);\r
+}\r
+\r
+\r
+/**\r
+  This service enables discovery of additional firmware volumes.\r
+\r
+  @param  Instance              This instance of the firmware volume to find.  The value 0 is the\r
+                                Boot Firmware Volume (BFV).\r
+  @param  FwVolHeader           Pointer to the firmware volume header of the volume to return.\r
+\r
+  @retval EFI_SUCCESS           The volume was found.\r
+  @retval EFI_NOT_FOUND         The volume was not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FfsFindNextVolume (\r
+  IN UINTN                          Instance,\r
+  IN OUT EFI_PEI_FV_HANDLE          *VolumeHandle\r
+  )\r
+{\r
+  EFI_PEI_HOB_POINTERS        Hob;\r
+  \r
+\r
+  Hob.Raw = GetHobList ();\r
+  if (Hob.Raw == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  do {\r
+    Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);\r
+    if (Hob.Raw != NULL) {\r
+      if (Instance-- == 0) {\r
+        *VolumeHandle = (EFI_PEI_FV_HANDLE)(UINTN)(Hob.FirmwareVolume->BaseAddress);\r
+        return EFI_SUCCESS;\r
+      }\r
+\r
+      Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));\r
+    }\r
+  } while (Hob.Raw != NULL);\r
+    \r
+  return EFI_NOT_FOUND;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Find a file in the volume by name\r
+  \r
+  @param FileName       A pointer to the name of the file to\r
+                        find within the firmware volume.\r
+\r
+  @param VolumeHandle   The firmware volume to search FileHandle\r
+                        Upon exit, points to the found file's\r
+                        handle or NULL if it could not be found.\r
+\r
+  @retval EFI_SUCCESS             File was found.\r
+\r
+  @retval EFI_NOT_FOUND           File was not found.\r
+\r
+  @retval EFI_INVALID_PARAMETER   VolumeHandle or FileHandle or\r
+                                  FileName was NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+FfsFindFileByName (\r
+  IN  CONST EFI_GUID        *FileName,\r
+  IN  EFI_PEI_FV_HANDLE     VolumeHandle,\r
+  OUT EFI_PEI_FILE_HANDLE   *FileHandle\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  Status = FindFileEx (VolumeHandle, FileName, 0, FileHandle);\r
+  if (Status == EFI_NOT_FOUND) {\r
+    *FileHandle = NULL;\r
+  }\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+  Get information about the file by name.\r
+\r
+  @param FileHandle   Handle of the file.\r
+\r
+  @param FileInfo     Upon exit, points to the file's\r
+                      information.\r
+\r
+  @retval EFI_SUCCESS             File information returned.\r
+  \r
+  @retval EFI_INVALID_PARAMETER   If FileHandle does not\r
+                                  represent a valid file.\r
+  \r
+  @retval EFI_INVALID_PARAMETER   If FileInfo is NULL.\r
+  \r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+FfsGetFileInfo (\r
+  IN EFI_PEI_FILE_HANDLE  FileHandle,\r
+  OUT EFI_FV_FILE_INFO    *FileInfo\r
+  )\r
+{\r
+  UINT8                       FileState;\r
+  UINT8                       ErasePolarity;\r
+  EFI_FFS_FILE_HEADER         *FileHeader;\r
+  EFI_PEI_FV_HANDLE           VolumeHandle;\r
+\r
+  if ((FileHandle == NULL) || (FileInfo == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  VolumeHandle = 0;\r
+  //\r
+  // Retrieve the FirmwareVolume which the file resides in.\r
+  //\r
+  if (!FileHandleToVolume(FileHandle, &VolumeHandle)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
+    ErasePolarity = 1;\r
+  } else {\r
+    ErasePolarity = 0;\r
+  }\r
+\r
+  //\r
+  // Get FileState which is the highest bit of the State \r
+  //\r
+  FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);\r
+\r
+  switch (FileState) {\r
+    case EFI_FILE_DATA_VALID:\r
+    case EFI_FILE_MARKED_FOR_UPDATE:\r
+      break;  \r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+  FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;\r
+  CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));\r
+  FileInfo->FileType = FileHeader->Type;\r
+  FileInfo->FileAttributes = FileHeader->Attributes;\r
+  FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) -  sizeof (EFI_FFS_FILE_HEADER);\r
+  FileInfo->Buffer = (FileHeader + 1);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Get Information about the volume by name\r
+\r
+  @param VolumeHandle   Handle of the volume.\r
+\r
+  @param VolumeInfo     Upon exit, points to the volume's\r
+                        information.\r
+\r
+  @retval EFI_SUCCESS             File information returned.\r
+  \r
+  @retval EFI_INVALID_PARAMETER   If FileHandle does not\r
+                                  represent a valid file.\r
+  \r
+  @retval EFI_INVALID_PARAMETER   If FileInfo is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+FfsGetVolumeInfo (\r
+  IN EFI_PEI_FV_HANDLE  VolumeHandle,\r
+  OUT EFI_FV_INFO       *VolumeInfo\r
+  )\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER             FwVolHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER         *FwVolExHeaderInfo;\r
+\r
+  if (VolumeInfo == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // VolumeHandle may not align at 8 byte, \r
+  // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte. \r
+  // So, Copy FvHeader into the local FvHeader structure.\r
+  //\r
+  CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+  //\r
+  // Check Fv Image Signature\r
+  //\r
+  if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  VolumeInfo->FvAttributes = FwVolHeader.Attributes;\r
+  VolumeInfo->FvStart = (VOID *) VolumeHandle;\r
+  VolumeInfo->FvSize = FwVolHeader.FvLength;\r
+  CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));\r
+\r
+  if (FwVolHeader.ExtHeaderOffset != 0) {\r
+    FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);\r
+    CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Search through every FV until you find a file of type FileType\r
+\r
+       @param FileType             File handle of a Fv type file.\r
+  @param Volumehandle   On succes Volume Handle of the match\r
+  @param FileHandle     On success File Handle of the match\r
+  \r
+  @retval EFI_NOT_FOUND                                FV image can't be found.\r
+  @retval EFI_SUCCESS                                          Successfully found FileType\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FfsAnyFvFindFirstFile (\r
+  IN  EFI_FV_FILETYPE       FileType,\r
+  OUT EFI_PEI_FV_HANDLE     *VolumeHandle,\r
+  OUT EFI_PEI_FILE_HANDLE   *FileHandle\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINTN             Instance;\r
+\r
+  //\r
+  // Search every FV for the DXE Core\r
+  //\r
+  Instance    = 0;\r
+  *FileHandle = NULL;\r
+\r
+  while (1)\r
+  {\r
+    Status = FfsFindNextVolume (Instance++, VolumeHandle);\r
+    if (EFI_ERROR (Status))\r
+    {\r
+      break;\r
+    }\r
+\r
+    Status = FfsFindNextFile (FileType, *VolumeHandle, FileHandle);\r
+    if (!EFI_ERROR (Status))\r
+    {\r
+      break;\r
+    }\r
+  }\r
+  \r
+  return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Get Fv image from the FV type file, then add FV & FV2 Hob.\r
+\r
+       @param FileHandle               File handle of a Fv type file.\r
+\r
+\r
+  @retval EFI_NOT_FOUND                                FV image can't be found.\r
+  @retval EFI_SUCCESS                                          Successfully to process it.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FfsProcessFvFile (\r
+  IN  EFI_PEI_FILE_HANDLE   FvFileHandle\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_PEI_FV_HANDLE     FvImageHandle;\r
+  EFI_FV_INFO           FvImageInfo;\r
+  UINT32                FvAlignment;\r
+  VOID                  *FvBuffer;\r
+  EFI_PEI_HOB_POINTERS  HobFv2;\r
+\r
+  FvBuffer             = NULL;\r
+\r
+\r
+  //\r
+  // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
+  // been extracted.\r
+  //\r
+  HobFv2.Raw = GetHobList ();\r
+  while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {\r
+    if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) {\r
+      //\r
+      // this FILE has been dispatched, it will not be dispatched again.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+    HobFv2.Raw = GET_NEXT_HOB (HobFv2);\r
+  }\r
+\r
+  //\r
+  // Find FvImage in FvFile\r
+  //\r
+  Status = FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, FvFileHandle, (VOID **)&FvImageHandle);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Collect FvImage Info.\r
+  //\r
+  ZeroMem (&FvImageInfo, sizeof (FvImageInfo));\r
+  Status = FfsGetVolumeInfo (FvImageHandle, &FvImageInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  //\r
+  // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
+  //\r
+  FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);\r
+  if (FvAlignment < 8) {\r
+    FvAlignment = 8;\r
+  }\r
+  \r
+  //\r
+  // Check FvImage\r
+  //\r
+  if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {\r
+    FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);\r
+    if (FvBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);\r
+    //\r
+    // Update FvImageInfo after reload FvImage to new aligned memory\r
+    //\r
+    FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);\r
+  }\r
+\r
+\r
+  //\r
+  // Inform HOB consumer phase, i.e. DXE core, the existance of this FV\r
+  //\r
+  BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, FvImageInfo.FvSize);\r
+  \r
+  //\r
+  // Makes the encapsulated volume show up in DXE phase to skip processing of\r
+  // encapsulated file again.\r
+  //\r
+  BuildFv2Hob (\r
+    (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
+    FvImageInfo.FvSize,\r
+    &FvImageInfo.FvName,\r
+    &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r