diff options
Diffstat (limited to 'MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c')
| -rw-r--r-- | MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c | 1426 |
1 files changed, 713 insertions, 713 deletions
diff --git a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c index 9f5f40e5cd..575ab601d8 100644 --- a/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c +++ b/MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c @@ -1,713 +1,713 @@ -/** @file
- Implementations for Firmware Volume Block protocol.
-
- It consumes FV HOBs and creates read-only Firmare Volume Block protocol
- instances for each of them.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-#include "FwVolBlock.h"
-
-FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {
- {
- {
- HARDWARE_DEVICE_PATH,
- HW_MEMMAP_DP,
- {
- (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
- (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
- }
- },
- EfiMemoryMappedIO,
- (EFI_PHYSICAL_ADDRESS)0,
- (EFI_PHYSICAL_ADDRESS)0,
- },
- {
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- END_DEVICE_PATH_LENGTH,
- 0
- }
- }
-};
-
-FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {
- {
- {
- MEDIA_DEVICE_PATH,
- MEDIA_PIWG_FW_VOL_DP,
- {
- (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
- (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
- }
- },
- { 0 }
- },
- {
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- END_DEVICE_PATH_LENGTH,
- 0
- }
- }
-};
-
-EFI_FW_VOL_BLOCK_DEVICE mFwVolBlock = {
- FVB_DEVICE_SIGNATURE,
- NULL,
- NULL,
- {
- FwVolBlockGetAttributes,
- (EFI_FVB_SET_ATTRIBUTES)FwVolBlockSetAttributes,
- FwVolBlockGetPhysicalAddress,
- FwVolBlockGetBlockSize,
- FwVolBlockReadBlock,
- (EFI_FVB_WRITE)FwVolBlockWriteBlock,
- (EFI_FVB_ERASE_BLOCKS)FwVolBlockEraseBlock,
- NULL
- },
- 0,
- NULL,
- 0,
- 0,
- 0
-};
-
-/**
- Retrieves Volume attributes. No polarity translations are done.
-
- @param This Calling context
- @param Attributes output buffer which contains attributes
-
- @retval EFI_SUCCESS The firmware volume attributes were returned.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockGetAttributes (
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
- OUT EFI_FVB_ATTRIBUTES_2 *Attributes
- )
-{
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
-
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
-
- //
- // Since we are read only, it's safe to get attributes data from our in-memory copy.
- //
- *Attributes = FvbDevice->FvbAttributes & ~EFI_FVB2_WRITE_STATUS;
-
- return EFI_SUCCESS;
-}
-
-/**
- Modifies the current settings of the firmware volume according to the input parameter.
-
- @param This Calling context
- @param Attributes input buffer which contains attributes
-
- @retval EFI_SUCCESS The firmware volume attributes were returned.
- @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with
- the capabilities as declared in the firmware
- volume header.
- @retval EFI_UNSUPPORTED Not supported.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockSetAttributes (
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
- IN CONST EFI_FVB_ATTRIBUTES_2 *Attributes
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- The EraseBlock() function erases one or more blocks as denoted by the
- variable argument list. The entire parameter list of blocks must be verified
- prior to erasing any blocks. If a block is requested that does not exist
- within the associated firmware volume (it has a larger index than the last
- block of the firmware volume), the EraseBlock() function must return
- EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
-
- @param This Calling context
- @param ... Starting LBA followed by Number of Lba to erase.
- a -1 to terminate the list.
-
- @retval EFI_SUCCESS The erase request was successfully completed.
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled
- state.
- @retval EFI_DEVICE_ERROR The block device is not functioning correctly
- and could not be written. The firmware device
- may have been partially erased.
- @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable
- argument list do
- @retval EFI_UNSUPPORTED Not supported.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockEraseBlock (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
- ...
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Read the specified number of bytes from the block to the input buffer.
-
- @param This Indicates the calling context.
- @param Lba The starting logical block index to read.
- @param Offset Offset into the block at which to begin reading.
- @param NumBytes Pointer to a UINT32. At entry, *NumBytes
- contains the total size of the buffer. At exit,
- *NumBytes contains the total number of bytes
- actually read.
- @param Buffer Pinter to a caller-allocated buffer that
- contains the destine for the read.
-
- @retval EFI_SUCCESS The firmware volume was read successfully.
- @retval EFI_BAD_BUFFER_SIZE The read was attempted across an LBA boundary.
- @retval EFI_ACCESS_DENIED Access denied.
- @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not
- be read.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockReadBlock (
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
- IN CONST EFI_LBA Lba,
- IN CONST UINTN Offset,
- IN OUT UINTN *NumBytes,
- IN OUT UINT8 *Buffer
- )
-{
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
- UINT8 *LbaOffset;
- UINTN LbaStart;
- UINTN NumOfBytesRead;
- UINTN LbaIndex;
-
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
-
- //
- // Check if This FW can be read
- //
- if ((FvbDevice->FvbAttributes & EFI_FVB2_READ_STATUS) == 0) {
- return EFI_ACCESS_DENIED;
- }
-
- LbaIndex = (UINTN)Lba;
- if (LbaIndex >= FvbDevice->NumBlocks) {
- //
- // Invalid Lba, read nothing.
- //
- *NumBytes = 0;
- return EFI_BAD_BUFFER_SIZE;
- }
-
- if (Offset > FvbDevice->LbaCache[LbaIndex].Length) {
- //
- // all exceed boundary, read nothing.
- //
- *NumBytes = 0;
- return EFI_BAD_BUFFER_SIZE;
- }
-
- NumOfBytesRead = *NumBytes;
- if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) {
- //
- // partial exceed boundary, read data from current postion to end.
- //
- NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset;
- }
-
- LbaStart = FvbDevice->LbaCache[LbaIndex].Base;
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
- LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset;
-
- //
- // Perform read operation
- //
- CopyMem (Buffer, LbaOffset, NumOfBytesRead);
-
- if (NumOfBytesRead == *NumBytes) {
- return EFI_SUCCESS;
- }
-
- *NumBytes = NumOfBytesRead;
- return EFI_BAD_BUFFER_SIZE;
-}
-
-/**
- Writes the specified number of bytes from the input buffer to the block.
-
- @param This Indicates the calling context.
- @param Lba The starting logical block index to write to.
- @param Offset Offset into the block at which to begin writing.
- @param NumBytes Pointer to a UINT32. At entry, *NumBytes
- contains the total size of the buffer. At exit,
- *NumBytes contains the total number of bytes
- actually written.
- @param Buffer Pinter to a caller-allocated buffer that
- contains the source for the write.
-
- @retval EFI_SUCCESS The firmware volume was written successfully.
- @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
- On output, NumBytes contains the total number of
- bytes actually written.
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled
- state.
- @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not
- be written.
- @retval EFI_UNSUPPORTED Not supported.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockWriteBlock (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN OUT UINTN *NumBytes,
- IN UINT8 *Buffer
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Get Fvb's base address.
-
- @param This Indicates the calling context.
- @param Address Fvb device base address.
-
- @retval EFI_SUCCESS Successfully got Fvb's base address.
- @retval EFI_UNSUPPORTED Not supported.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockGetPhysicalAddress (
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
- OUT EFI_PHYSICAL_ADDRESS *Address
- )
-{
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
-
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
-
- if ((FvbDevice->FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
- *Address = FvbDevice->BaseAddress;
- return EFI_SUCCESS;
- }
-
- return EFI_UNSUPPORTED;
-}
-
-/**
- Retrieves the size in bytes of a specific block within a firmware volume.
-
- @param This Indicates the calling context.
- @param Lba Indicates the block for which to return the
- size.
- @param BlockSize Pointer to a caller-allocated UINTN in which the
- size of the block is returned.
- @param NumberOfBlocks Pointer to a caller-allocated UINTN in which the
- number of consecutive blocks starting with Lba
- is returned. All blocks in this range have a
- size of BlockSize.
-
- @retval EFI_SUCCESS The firmware volume base address is returned.
- @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockGetBlockSize (
- IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
- IN CONST EFI_LBA Lba,
- IN OUT UINTN *BlockSize,
- IN OUT UINTN *NumberOfBlocks
- )
-{
- UINTN TotalBlocks;
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
- EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
-
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
-
- //
- // Do parameter checking
- //
- if (Lba >= FvbDevice->NumBlocks) {
- return EFI_INVALID_PARAMETER;
- }
-
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
-
- PtrBlockMapEntry = FwVolHeader->BlockMap;
-
- //
- // Search the block map for the given block
- //
- TotalBlocks = 0;
- while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->Length != 0)) {
- TotalBlocks += PtrBlockMapEntry->NumBlocks;
- if (Lba < TotalBlocks) {
- //
- // We find the range
- //
- break;
- }
-
- PtrBlockMapEntry++;
- }
-
- *BlockSize = PtrBlockMapEntry->Length;
- *NumberOfBlocks = TotalBlocks - (UINTN)Lba;
-
- return EFI_SUCCESS;
-}
-
-/**
-
- Get FVB authentication status
-
- @param FvbProtocol FVB protocol.
-
- @return Authentication status.
-
-**/
-UINT32
-GetFvbAuthenticationStatus (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol
- )
-{
- EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
- UINT32 AuthenticationStatus;
-
- AuthenticationStatus = 0;
- FvbDevice = BASE_CR (FvbProtocol, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance);
- if (FvbDevice->Signature == FVB_DEVICE_SIGNATURE) {
- AuthenticationStatus = FvbDevice->AuthenticationStatus;
- }
-
- return AuthenticationStatus;
-}
-
-/**
- This routine produces a firmware volume block protocol on a given
- buffer.
-
- @param BaseAddress base address of the firmware volume image
- @param Length length of the firmware volume image
- @param ParentHandle handle of parent firmware volume, if this image
- came from an FV image file and section in another firmware
- volume (ala capsules)
- @param AuthenticationStatus Authentication status inherited, if this image
- came from an FV image file and section in another firmware volume.
- @param FvProtocol Firmware volume block protocol produced.
-
- @retval EFI_VOLUME_CORRUPTED Volume corrupted.
- @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated.
- @retval EFI_SUCCESS Successfully produced a FVB protocol on given
- buffer.
-
-**/
-EFI_STATUS
-ProduceFVBProtocolOnBuffer (
- IN EFI_PHYSICAL_ADDRESS BaseAddress,
- IN UINT64 Length,
- IN EFI_HANDLE ParentHandle,
- IN UINT32 AuthenticationStatus,
- OUT EFI_HANDLE *FvProtocol OPTIONAL
- )
-{
- EFI_STATUS Status;
- EFI_FW_VOL_BLOCK_DEVICE *FvbDev;
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
- UINTN BlockIndex;
- UINTN BlockIndex2;
- UINTN LinearOffset;
- UINT32 FvAlignment;
- EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
-
- FvAlignment = 0;
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
- //
- // Validate FV Header, if not as expected, return
- //
- if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- //
- // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
- // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
- // its initial linked location and maintain its alignment.
- //
- if ((FwVolHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
- //
- // Get FvHeader alignment
- //
- FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
- //
- // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
- //
- if (FvAlignment < 8) {
- FvAlignment = 8;
- }
-
- if ((UINTN)BaseAddress % FvAlignment != 0) {
- //
- // FvImage buffer is not at its required alignment.
- //
- DEBUG ((
- DEBUG_ERROR,
- "Unaligned FvImage found at 0x%lx:0x%lx, the required alignment is 0x%x\n",
- BaseAddress,
- Length,
- FvAlignment
- ));
- return EFI_VOLUME_CORRUPTED;
- }
- }
-
- //
- // Allocate EFI_FW_VOL_BLOCK_DEVICE
- //
- FvbDev = AllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);
- if (FvbDev == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- FvbDev->BaseAddress = BaseAddress;
- FvbDev->FvbAttributes = FwVolHeader->Attributes;
- FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle;
- FvbDev->AuthenticationStatus = AuthenticationStatus;
-
- //
- // Init the block caching fields of the device
- // First, count the number of blocks
- //
- FvbDev->NumBlocks = 0;
- for (PtrBlockMapEntry = FwVolHeader->BlockMap;
- PtrBlockMapEntry->NumBlocks != 0;
- PtrBlockMapEntry++)
- {
- FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks;
- }
-
- //
- // Second, allocate the cache
- //
- if (FvbDev->NumBlocks >= (MAX_ADDRESS / sizeof (LBA_CACHE))) {
- CoreFreePool (FvbDev);
- return EFI_OUT_OF_RESOURCES;
- }
-
- FvbDev->LbaCache = AllocatePool (FvbDev->NumBlocks * sizeof (LBA_CACHE));
- if (FvbDev->LbaCache == NULL) {
- CoreFreePool (FvbDev);
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Last, fill in the cache with the linear address of the blocks
- //
- BlockIndex = 0;
- LinearOffset = 0;
- for (PtrBlockMapEntry = FwVolHeader->BlockMap;
- PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++)
- {
- for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
- FvbDev->LbaCache[BlockIndex].Base = LinearOffset;
- FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->Length;
- LinearOffset += PtrBlockMapEntry->Length;
- BlockIndex++;
- }
- }
-
- //
- // Judget whether FV name guid is produced in Fv extension header
- //
- if (FwVolHeader->ExtHeaderOffset == 0) {
- //
- // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
- //
- FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);
- if (FvbDev->DevicePath == NULL) {
- FreePool (FvbDev->LbaCache);
- FreePool (FvbDev);
- return EFI_OUT_OF_RESOURCES;
- }
-
- ((FV_MEMMAP_DEVICE_PATH *)FvbDev->DevicePath)->MemMapDevPath.StartingAddress = BaseAddress;
- ((FV_MEMMAP_DEVICE_PATH *)FvbDev->DevicePath)->MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1;
- } else {
- //
- // FV contains extension header, then produce MEDIA_FW_VOL_DEVICE_PATH
- //
- FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);
- if (FvbDev->DevicePath == NULL) {
- FreePool (FvbDev->LbaCache);
- FreePool (FvbDev);
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyGuid (
- &((FV_PIWG_DEVICE_PATH *)FvbDev->DevicePath)->FvDevPath.FvName,
- (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)
- );
- }
-
- //
- //
- // Attach FvVolBlock Protocol to new handle
- //
- Status = CoreInstallMultipleProtocolInterfaces (
- &FvbDev->Handle,
- &gEfiFirmwareVolumeBlockProtocolGuid,
- &FvbDev->FwVolBlockInstance,
- &gEfiDevicePathProtocolGuid,
- FvbDev->DevicePath,
- NULL
- );
-
- //
- // If they want the handle back, set it.
- //
- if (FvProtocol != NULL) {
- *FvProtocol = FvbDev->Handle;
- }
-
- return Status;
-}
-
-/**
- This routine consumes FV hobs and produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
-
- @param ImageHandle The image handle.
- @param SystemTable The system table.
-
- @retval EFI_SUCCESS Successfully initialized firmware volume block
- driver.
-
-**/
-EFI_STATUS
-EFIAPI
-FwVolBlockDriverInit (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_PEI_HOB_POINTERS FvHob;
- EFI_PEI_HOB_POINTERS Fv3Hob;
- UINT32 AuthenticationStatus;
-
- //
- // Core Needs Firmware Volumes to function
- //
- FvHob.Raw = GetHobList ();
- while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) {
- AuthenticationStatus = 0;
- //
- // Get the authentication status propagated from PEI-phase to DXE.
- //
- Fv3Hob.Raw = GetHobList ();
- while ((Fv3Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV3, Fv3Hob.Raw)) != NULL) {
- if ((Fv3Hob.FirmwareVolume3->BaseAddress == FvHob.FirmwareVolume->BaseAddress) &&
- (Fv3Hob.FirmwareVolume3->Length == FvHob.FirmwareVolume->Length))
- {
- AuthenticationStatus = Fv3Hob.FirmwareVolume3->AuthenticationStatus;
- break;
- }
-
- Fv3Hob.Raw = GET_NEXT_HOB (Fv3Hob);
- }
-
- //
- // Produce an FVB protocol for it
- //
- ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, AuthenticationStatus, NULL);
- FvHob.Raw = GET_NEXT_HOB (FvHob);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- This DXE service routine is used to process a firmware volume. In
- particular, it can be called by BDS to process a single firmware
- volume found in a capsule.
-
- Caution: The caller need validate the input firmware volume to follow
- PI specification.
- DxeCore will trust the input data and process firmware volume directly.
-
- @param FvHeader pointer to a firmware volume header
- @param Size the size of the buffer pointed to by FvHeader
- @param FVProtocolHandle the handle on which a firmware volume protocol
- was produced for the firmware volume passed in.
-
- @retval EFI_OUT_OF_RESOURCES if an FVB could not be produced due to lack of
- system resources
- @retval EFI_VOLUME_CORRUPTED if the volume was corrupted
- @retval EFI_SUCCESS a firmware volume protocol was produced for the
- firmware volume
-
-**/
-EFI_STATUS
-EFIAPI
-CoreProcessFirmwareVolume (
- IN VOID *FvHeader,
- IN UINTN Size,
- OUT EFI_HANDLE *FVProtocolHandle
- )
-{
- VOID *Ptr;
- EFI_STATUS Status;
-
- *FVProtocolHandle = NULL;
- Status = ProduceFVBProtocolOnBuffer (
- (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
- (UINT64)Size,
- NULL,
- 0,
- FVProtocolHandle
- );
- //
- // Since in our implementation we use register-protocol-notify to put a
- // FV protocol on the FVB protocol handle, we can't directly verify that
- // the FV protocol was produced. Therefore here we will check the handle
- // and make sure an FV protocol is on it. This indicates that all went
- // well. Otherwise we have to assume that the volume was corrupted
- // somehow.
- //
- if (!EFI_ERROR (Status)) {
- ASSERT (*FVProtocolHandle != NULL);
- Ptr = NULL;
- Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Ptr);
- if (EFI_ERROR (Status) || (Ptr == NULL)) {
- return EFI_VOLUME_CORRUPTED;
- }
-
- return EFI_SUCCESS;
- }
-
- return Status;
-}
+/** @file + Implementations for Firmware Volume Block protocol. + + It consumes FV HOBs and creates read-only Firmare Volume Block protocol + instances for each of them. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DxeMain.h" +#include "FwVolBlock.h" + +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS)0, + (EFI_PHYSICAL_ADDRESS)0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = { + { + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + { + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) + } + }, + { 0 } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +EFI_FW_VOL_BLOCK_DEVICE mFwVolBlock = { + FVB_DEVICE_SIGNATURE, + NULL, + NULL, + { + FwVolBlockGetAttributes, + (EFI_FVB_SET_ATTRIBUTES)FwVolBlockSetAttributes, + FwVolBlockGetPhysicalAddress, + FwVolBlockGetBlockSize, + FwVolBlockReadBlock, + (EFI_FVB_WRITE)FwVolBlockWriteBlock, + (EFI_FVB_ERASE_BLOCKS)FwVolBlockEraseBlock, + NULL + }, + 0, + NULL, + 0, + 0, + 0 +}; + +/** + Retrieves Volume attributes. No polarity translations are done. + + @param This Calling context + @param Attributes output buffer which contains attributes + + @retval EFI_SUCCESS The firmware volume attributes were returned. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + // + // Since we are read only, it's safe to get attributes data from our in-memory copy. + // + *Attributes = FvbDevice->FvbAttributes & ~EFI_FVB2_WRITE_STATUS; + + return EFI_SUCCESS; +} + +/** + Modifies the current settings of the firmware volume according to the input parameter. + + @param This Calling context + @param Attributes input buffer which contains attributes + + @retval EFI_SUCCESS The firmware volume attributes were returned. + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with + the capabilities as declared in the firmware + volume header. + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + return EFI_UNSUPPORTED; +} + +/** + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be verified + prior to erasing any blocks. If a block is requested that does not exist + within the associated firmware volume (it has a larger index than the last + block of the firmware volume), the EraseBlock() function must return + EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. + + @param This Calling context + @param ... Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. + + @retval EFI_SUCCESS The erase request was successfully completed. + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled + state. + @retval EFI_DEVICE_ERROR The block device is not functioning correctly + and could not be written. The firmware device + may have been partially erased. + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable + argument list do + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockEraseBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Read the specified number of bytes from the block to the input buffer. + + @param This Indicates the calling context. + @param Lba The starting logical block index to read. + @param Offset Offset into the block at which to begin reading. + @param NumBytes Pointer to a UINT32. At entry, *NumBytes + contains the total size of the buffer. At exit, + *NumBytes contains the total number of bytes + actually read. + @param Buffer Pinter to a caller-allocated buffer that + contains the destine for the read. + + @retval EFI_SUCCESS The firmware volume was read successfully. + @retval EFI_BAD_BUFFER_SIZE The read was attempted across an LBA boundary. + @retval EFI_ACCESS_DENIED Access denied. + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not + be read. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockReadBlock ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN CONST UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINT8 *LbaOffset; + UINTN LbaStart; + UINTN NumOfBytesRead; + UINTN LbaIndex; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + // + // Check if This FW can be read + // + if ((FvbDevice->FvbAttributes & EFI_FVB2_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + LbaIndex = (UINTN)Lba; + if (LbaIndex >= FvbDevice->NumBlocks) { + // + // Invalid Lba, read nothing. + // + *NumBytes = 0; + return EFI_BAD_BUFFER_SIZE; + } + + if (Offset > FvbDevice->LbaCache[LbaIndex].Length) { + // + // all exceed boundary, read nothing. + // + *NumBytes = 0; + return EFI_BAD_BUFFER_SIZE; + } + + NumOfBytesRead = *NumBytes; + if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) { + // + // partial exceed boundary, read data from current postion to end. + // + NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset; + } + + LbaStart = FvbDevice->LbaCache[LbaIndex].Base; + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress); + LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset; + + // + // Perform read operation + // + CopyMem (Buffer, LbaOffset, NumOfBytesRead); + + if (NumOfBytesRead == *NumBytes) { + return EFI_SUCCESS; + } + + *NumBytes = NumOfBytesRead; + return EFI_BAD_BUFFER_SIZE; +} + +/** + Writes the specified number of bytes from the input buffer to the block. + + @param This Indicates the calling context. + @param Lba The starting logical block index to write to. + @param Offset Offset into the block at which to begin writing. + @param NumBytes Pointer to a UINT32. At entry, *NumBytes + contains the total size of the buffer. At exit, + *NumBytes contains the total number of bytes + actually written. + @param Buffer Pinter to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary. + On output, NumBytes contains the total number of + bytes actually written. + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled + state. + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not + be written. + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockWriteBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Get Fvb's base address. + + @param This Indicates the calling context. + @param Address Fvb device base address. + + @retval EFI_SUCCESS Successfully got Fvb's base address. + @retval EFI_UNSUPPORTED Not supported. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + if ((FvbDevice->FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { + *Address = FvbDevice->BaseAddress; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +/** + Retrieves the size in bytes of a specific block within a firmware volume. + + @param This Indicates the calling context. + @param Lba Indicates the block for which to return the + size. + @param BlockSize Pointer to a caller-allocated UINTN in which the + size of the block is returned. + @param NumberOfBlocks Pointer to a caller-allocated UINTN in which the + number of consecutive blocks starting with Lba + is returned. All blocks in this range have a + size of BlockSize. + + @retval EFI_SUCCESS The firmware volume base address is returned. + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN OUT UINTN *BlockSize, + IN OUT UINTN *NumberOfBlocks + ) +{ + UINTN TotalBlocks; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + // + // Do parameter checking + // + if (Lba >= FvbDevice->NumBlocks) { + return EFI_INVALID_PARAMETER; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress); + + PtrBlockMapEntry = FwVolHeader->BlockMap; + + // + // Search the block map for the given block + // + TotalBlocks = 0; + while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->Length != 0)) { + TotalBlocks += PtrBlockMapEntry->NumBlocks; + if (Lba < TotalBlocks) { + // + // We find the range + // + break; + } + + PtrBlockMapEntry++; + } + + *BlockSize = PtrBlockMapEntry->Length; + *NumberOfBlocks = TotalBlocks - (UINTN)Lba; + + return EFI_SUCCESS; +} + +/** + + Get FVB authentication status + + @param FvbProtocol FVB protocol. + + @return Authentication status. + +**/ +UINT32 +GetFvbAuthenticationStatus ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol + ) +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + UINT32 AuthenticationStatus; + + AuthenticationStatus = 0; + FvbDevice = BASE_CR (FvbProtocol, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance); + if (FvbDevice->Signature == FVB_DEVICE_SIGNATURE) { + AuthenticationStatus = FvbDevice->AuthenticationStatus; + } + + return AuthenticationStatus; +} + +/** + This routine produces a firmware volume block protocol on a given + buffer. + + @param BaseAddress base address of the firmware volume image + @param Length length of the firmware volume image + @param ParentHandle handle of parent firmware volume, if this image + came from an FV image file and section in another firmware + volume (ala capsules) + @param AuthenticationStatus Authentication status inherited, if this image + came from an FV image file and section in another firmware volume. + @param FvProtocol Firmware volume block protocol produced. + + @retval EFI_VOLUME_CORRUPTED Volume corrupted. + @retval EFI_OUT_OF_RESOURCES No enough buffer to be allocated. + @retval EFI_SUCCESS Successfully produced a FVB protocol on given + buffer. + +**/ +EFI_STATUS +ProduceFVBProtocolOnBuffer ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_HANDLE ParentHandle, + IN UINT32 AuthenticationStatus, + OUT EFI_HANDLE *FvProtocol OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_FW_VOL_BLOCK_DEVICE *FvbDev; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINTN BlockIndex; + UINTN BlockIndex2; + UINTN LinearOffset; + UINT32 FvAlignment; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + + FvAlignment = 0; + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; + // + // Validate FV Header, if not as expected, return + // + if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) { + return EFI_VOLUME_CORRUPTED; + } + + // + // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume + // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from + // its initial linked location and maintain its alignment. + // + if ((FwVolHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) { + // + // Get FvHeader alignment + // + FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); + // + // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value. + // + if (FvAlignment < 8) { + FvAlignment = 8; + } + + if ((UINTN)BaseAddress % FvAlignment != 0) { + // + // FvImage buffer is not at its required alignment. + // + DEBUG (( + DEBUG_ERROR, + "Unaligned FvImage found at 0x%lx:0x%lx, the required alignment is 0x%x\n", + BaseAddress, + Length, + FvAlignment + )); + return EFI_VOLUME_CORRUPTED; + } + } + + // + // Allocate EFI_FW_VOL_BLOCK_DEVICE + // + FvbDev = AllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock); + if (FvbDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FvbDev->BaseAddress = BaseAddress; + FvbDev->FvbAttributes = FwVolHeader->Attributes; + FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle; + FvbDev->AuthenticationStatus = AuthenticationStatus; + + // + // Init the block caching fields of the device + // First, count the number of blocks + // + FvbDev->NumBlocks = 0; + for (PtrBlockMapEntry = FwVolHeader->BlockMap; + PtrBlockMapEntry->NumBlocks != 0; + PtrBlockMapEntry++) + { + FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks; + } + + // + // Second, allocate the cache + // + if (FvbDev->NumBlocks >= (MAX_ADDRESS / sizeof (LBA_CACHE))) { + CoreFreePool (FvbDev); + return EFI_OUT_OF_RESOURCES; + } + + FvbDev->LbaCache = AllocatePool (FvbDev->NumBlocks * sizeof (LBA_CACHE)); + if (FvbDev->LbaCache == NULL) { + CoreFreePool (FvbDev); + return EFI_OUT_OF_RESOURCES; + } + + // + // Last, fill in the cache with the linear address of the blocks + // + BlockIndex = 0; + LinearOffset = 0; + for (PtrBlockMapEntry = FwVolHeader->BlockMap; + PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) + { + for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) { + FvbDev->LbaCache[BlockIndex].Base = LinearOffset; + FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->Length; + LinearOffset += PtrBlockMapEntry->Length; + BlockIndex++; + } + } + + // + // Judget whether FV name guid is produced in Fv extension header + // + if (FwVolHeader->ExtHeaderOffset == 0) { + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH + // + FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate); + if (FvbDev->DevicePath == NULL) { + FreePool (FvbDev->LbaCache); + FreePool (FvbDev); + return EFI_OUT_OF_RESOURCES; + } + + ((FV_MEMMAP_DEVICE_PATH *)FvbDev->DevicePath)->MemMapDevPath.StartingAddress = BaseAddress; + ((FV_MEMMAP_DEVICE_PATH *)FvbDev->DevicePath)->MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1; + } else { + // + // FV contains extension header, then produce MEDIA_FW_VOL_DEVICE_PATH + // + FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate); + if (FvbDev->DevicePath == NULL) { + FreePool (FvbDev->LbaCache); + FreePool (FvbDev); + return EFI_OUT_OF_RESOURCES; + } + + CopyGuid ( + &((FV_PIWG_DEVICE_PATH *)FvbDev->DevicePath)->FvDevPath.FvName, + (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) + ); + } + + // + // + // Attach FvVolBlock Protocol to new handle + // + Status = CoreInstallMultipleProtocolInterfaces ( + &FvbDev->Handle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDev->FwVolBlockInstance, + &gEfiDevicePathProtocolGuid, + FvbDev->DevicePath, + NULL + ); + + // + // If they want the handle back, set it. + // + if (FvProtocol != NULL) { + *FvProtocol = FvbDev->Handle; + } + + return Status; +} + +/** + This routine consumes FV hobs and produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate. + + @param ImageHandle The image handle. + @param SystemTable The system table. + + @retval EFI_SUCCESS Successfully initialized firmware volume block + driver. + +**/ +EFI_STATUS +EFIAPI +FwVolBlockDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_PEI_HOB_POINTERS FvHob; + EFI_PEI_HOB_POINTERS Fv3Hob; + UINT32 AuthenticationStatus; + + // + // Core Needs Firmware Volumes to function + // + FvHob.Raw = GetHobList (); + while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) { + AuthenticationStatus = 0; + // + // Get the authentication status propagated from PEI-phase to DXE. + // + Fv3Hob.Raw = GetHobList (); + while ((Fv3Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV3, Fv3Hob.Raw)) != NULL) { + if ((Fv3Hob.FirmwareVolume3->BaseAddress == FvHob.FirmwareVolume->BaseAddress) && + (Fv3Hob.FirmwareVolume3->Length == FvHob.FirmwareVolume->Length)) + { + AuthenticationStatus = Fv3Hob.FirmwareVolume3->AuthenticationStatus; + break; + } + + Fv3Hob.Raw = GET_NEXT_HOB (Fv3Hob); + } + + // + // Produce an FVB protocol for it + // + ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, AuthenticationStatus, NULL); + FvHob.Raw = GET_NEXT_HOB (FvHob); + } + + return EFI_SUCCESS; +} + +/** + This DXE service routine is used to process a firmware volume. In + particular, it can be called by BDS to process a single firmware + volume found in a capsule. + + Caution: The caller need validate the input firmware volume to follow + PI specification. + DxeCore will trust the input data and process firmware volume directly. + + @param FvHeader pointer to a firmware volume header + @param Size the size of the buffer pointed to by FvHeader + @param FVProtocolHandle the handle on which a firmware volume protocol + was produced for the firmware volume passed in. + + @retval EFI_OUT_OF_RESOURCES if an FVB could not be produced due to lack of + system resources + @retval EFI_VOLUME_CORRUPTED if the volume was corrupted + @retval EFI_SUCCESS a firmware volume protocol was produced for the + firmware volume + +**/ +EFI_STATUS +EFIAPI +CoreProcessFirmwareVolume ( + IN VOID *FvHeader, + IN UINTN Size, + OUT EFI_HANDLE *FVProtocolHandle + ) +{ + VOID *Ptr; + EFI_STATUS Status; + + *FVProtocolHandle = NULL; + Status = ProduceFVBProtocolOnBuffer ( + (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader, + (UINT64)Size, + NULL, + 0, + FVProtocolHandle + ); + // + // Since in our implementation we use register-protocol-notify to put a + // FV protocol on the FVB protocol handle, we can't directly verify that + // the FV protocol was produced. Therefore here we will check the handle + // and make sure an FV protocol is on it. This indicates that all went + // well. Otherwise we have to assume that the volume was corrupted + // somehow. + // + if (!EFI_ERROR (Status)) { + ASSERT (*FVProtocolHandle != NULL); + Ptr = NULL; + Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Ptr); + if (EFI_ERROR (Status) || (Ptr == NULL)) { + return EFI_VOLUME_CORRUPTED; + } + + return EFI_SUCCESS; + } + + return Status; +} |
