summaryrefslogtreecommitdiff
path: root/EmbeddedPkg/Library/PrePiLib/FwVol.c
diff options
context:
space:
mode:
Diffstat (limited to 'EmbeddedPkg/Library/PrePiLib/FwVol.c')
-rw-r--r--EmbeddedPkg/Library/PrePiLib/FwVol.c1684
1 files changed, 842 insertions, 842 deletions
diff --git a/EmbeddedPkg/Library/PrePiLib/FwVol.c b/EmbeddedPkg/Library/PrePiLib/FwVol.c
index 75d28a72..9e4cdd00 100644
--- a/EmbeddedPkg/Library/PrePiLib/FwVol.c
+++ b/EmbeddedPkg/Library/PrePiLib/FwVol.c
@@ -1,842 +1,842 @@
-/** @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
+ 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;
+}
+
+