REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the UefiPayloadPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			1090 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1090 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
Firmware Volume Block Driver to provide FVB service.
 | 
						|
 | 
						|
  Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "FvbService.h"
 | 
						|
 | 
						|
//
 | 
						|
// Global variable for this FVB driver  which contains
 | 
						|
// the private data of all firmware volume block instances
 | 
						|
//
 | 
						|
FWB_GLOBAL  mFvbModuleGlobal;
 | 
						|
 | 
						|
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  mFvbDeviceTemplate = {
 | 
						|
  FVB_DEVICE_SIGNATURE,
 | 
						|
  NULL,
 | 
						|
  0, // Instance
 | 
						|
  {
 | 
						|
    FvbProtocolGetAttributes,
 | 
						|
    FvbProtocolSetAttributes,
 | 
						|
    FvbProtocolGetPhysicalAddress,
 | 
						|
    FvbProtocolGetBlockSize,
 | 
						|
    FvbProtocolRead,
 | 
						|
    FvbProtocolWrite,
 | 
						|
    FvbProtocolEraseBlocks,
 | 
						|
    NULL
 | 
						|
  } // FwVolBlockInstance
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Get the pointer to EFI_FW_VOL_INSTANCE from the buffer pointed
 | 
						|
  by mFvbModuleGlobal.FvInstance based on a index.
 | 
						|
  Each EFI_FW_VOL_INSTANCE is  with variable length as
 | 
						|
  we have a block map at the end of the EFI_FIRMWARE_VOLUME_HEADER.
 | 
						|
 | 
						|
  @param[in] Instance The index of the EFI_FW_VOL_INSTANCE.
 | 
						|
 | 
						|
  @return A pointer to EFI_FW_VOL_INSTANCE.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_FW_VOL_INSTANCE *
 | 
						|
GetFvbInstance (
 | 
						|
  IN  UINTN  Instance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_INSTANCE  *FwhRecord;
 | 
						|
 | 
						|
  if ( Instance >= mFvbModuleGlobal.NumFv ) {
 | 
						|
    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the right instance of the FVB private data
 | 
						|
  //
 | 
						|
  FwhRecord = mFvbModuleGlobal.FvInstance;
 | 
						|
  while ( Instance > 0 ) {
 | 
						|
    FwhRecord = (EFI_FW_VOL_INSTANCE *)((UINTN)((UINT8 *)FwhRecord) +
 | 
						|
                                        FwhRecord->VolumeHeader.HeaderLength +
 | 
						|
                                        (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));
 | 
						|
    Instance--;
 | 
						|
  }
 | 
						|
 | 
						|
  return FwhRecord;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the EFI_FVB_ATTRIBUTES_2 of a FV.
 | 
						|
 | 
						|
  @param[in]  Instance    The index of the EFI_FW_VOL_INSTANCE.
 | 
						|
 | 
						|
  @retval     EFI_FVB_ATTRIBUTES_2 of the FV identified by Instance.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_FVB_ATTRIBUTES_2
 | 
						|
FvbGetVolumeAttributes (
 | 
						|
  IN UINTN  Instance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_INSTANCE  *FwInstance;
 | 
						|
 | 
						|
  FwInstance = GetFvbInstance (Instance);
 | 
						|
  ASSERT (FwInstance != NULL);
 | 
						|
 | 
						|
  if (FwInstance == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return FwInstance->VolumeHeader.Attributes;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieves the starting address of an LBA in an FV. It also
 | 
						|
  return a few other attribut of the FV.
 | 
						|
 | 
						|
  @param[in]  Instance        The index of the EFI_FW_VOL_INSTANCE.
 | 
						|
  @param[in]  Lba             The logical block address
 | 
						|
  @param[out] LbaAddress      On output, contains the physical starting address
 | 
						|
                              of the Lba
 | 
						|
  @param[out] LbaLength       On output, contains the length of the block
 | 
						|
  @param[out] NumOfBlocks     A 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 Successfully returns
 | 
						|
  @retval   EFI_INVALID_PARAMETER Instance not found
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
FvbGetLbaAddress (
 | 
						|
  IN  UINTN    Instance,
 | 
						|
  IN  EFI_LBA  Lba,
 | 
						|
  OUT UINTN    *LbaAddress,
 | 
						|
  OUT UINTN    *LbaLength,
 | 
						|
  OUT UINTN    *NumOfBlocks
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32                  NumBlocks;
 | 
						|
  UINT32                  BlockLength;
 | 
						|
  UINTN                   Offset;
 | 
						|
  EFI_LBA                 StartLba;
 | 
						|
  EFI_LBA                 NextLba;
 | 
						|
  EFI_FW_VOL_INSTANCE     *FwhInstance;
 | 
						|
  EFI_FV_BLOCK_MAP_ENTRY  *BlockMap;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the right instance of the FVB private data
 | 
						|
  //
 | 
						|
  FwhInstance = GetFvbInstance (Instance);
 | 
						|
  if (FwhInstance == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  StartLba = 0;
 | 
						|
  Offset   = 0;
 | 
						|
  BlockMap = &FwhInstance->VolumeHeader.BlockMap[0];
 | 
						|
  ASSERT (BlockMap != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the blockmap of the FV to find which map entry the Lba belongs to
 | 
						|
  //
 | 
						|
  while (TRUE) {
 | 
						|
    if ( BlockMap != NULL) {
 | 
						|
      NumBlocks   = BlockMap->NumBlocks;
 | 
						|
      BlockLength = BlockMap->Length;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((NumBlocks == 0) || (BlockLength == 0)) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    NextLba = StartLba + NumBlocks;
 | 
						|
 | 
						|
    //
 | 
						|
    // The map entry found
 | 
						|
    //
 | 
						|
    if ((Lba >= StartLba) && (Lba < NextLba)) {
 | 
						|
      Offset = Offset + (UINTN)MultU64x32 ((Lba - StartLba), BlockLength);
 | 
						|
      if (LbaAddress != NULL) {
 | 
						|
        *LbaAddress = FwhInstance->FvBase + Offset;
 | 
						|
      }
 | 
						|
 | 
						|
      if (LbaLength != NULL) {
 | 
						|
        *LbaLength = BlockLength;
 | 
						|
      }
 | 
						|
 | 
						|
      if (NumOfBlocks != NULL) {
 | 
						|
        *NumOfBlocks = (UINTN)(NextLba - Lba);
 | 
						|
      }
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    StartLba = NextLba;
 | 
						|
    Offset   = Offset + NumBlocks * BlockLength;
 | 
						|
    BlockMap++;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Reads specified number of bytes into a buffer from the specified block
 | 
						|
 | 
						|
  @param[in]      Instance        The FV instance to be read from
 | 
						|
  @param[in]      Lba             The logical block address to be read from
 | 
						|
  @param[in]      BlockOffset     Offset into the block at which to begin reading
 | 
						|
  @param[in, out] NumBytes        Pointer that on input contains the total size of
 | 
						|
                                  the buffer. On output, it contains the total number
 | 
						|
                                  of bytes read
 | 
						|
  @param[in]      Buffer          Pointer to a caller allocated buffer that will be
 | 
						|
                                  used to hold the data read
 | 
						|
 | 
						|
 | 
						|
  @retval         EFI_SUCCESS         The firmware volume was read successfully and
 | 
						|
                                      contents are in Buffer
 | 
						|
  @retval         EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output,
 | 
						|
                                      NumBytes contains the total number of bytes returned
 | 
						|
                                      in Buffer
 | 
						|
  @retval         EFI_ACCESS_DENIED   The firmware volume is in the ReadDisabled state
 | 
						|
  @retval         EFI_DEVICE_ERROR    The block device is not functioning correctly and
 | 
						|
                                      could not be read
 | 
						|
  @retval         EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
FvbReadBlock (
 | 
						|
  IN UINTN      Instance,
 | 
						|
  IN EFI_LBA    Lba,
 | 
						|
  IN UINTN      BlockOffset,
 | 
						|
  IN OUT UINTN  *NumBytes,
 | 
						|
  IN UINT8      *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FVB_ATTRIBUTES_2  Attributes;
 | 
						|
  UINTN                 LbaAddress;
 | 
						|
  UINTN                 LbaLength;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_STATUS            ReadStatus;
 | 
						|
 | 
						|
  if ((NumBytes == NULL) || (Buffer == NULL)) {
 | 
						|
    return (EFI_INVALID_PARAMETER);
 | 
						|
  }
 | 
						|
 | 
						|
  if (*NumBytes == 0) {
 | 
						|
    return (EFI_INVALID_PARAMETER);
 | 
						|
  }
 | 
						|
 | 
						|
  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Attributes = FvbGetVolumeAttributes (Instance);
 | 
						|
 | 
						|
  if ((Attributes & EFI_FVB2_READ_STATUS) == 0) {
 | 
						|
    return (EFI_ACCESS_DENIED);
 | 
						|
  }
 | 
						|
 | 
						|
  if (BlockOffset > LbaLength) {
 | 
						|
    return (EFI_INVALID_PARAMETER);
 | 
						|
  }
 | 
						|
 | 
						|
  if (LbaLength < (*NumBytes + BlockOffset)) {
 | 
						|
    *NumBytes = (UINT32)(LbaLength - BlockOffset);
 | 
						|
    Status    = EFI_BAD_BUFFER_SIZE;
 | 
						|
  }
 | 
						|
 | 
						|
  ReadStatus = LibFvbFlashDeviceRead (LbaAddress + BlockOffset, NumBytes, Buffer);
 | 
						|
  if (EFI_ERROR (ReadStatus)) {
 | 
						|
    return ReadStatus;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Writes specified number of bytes from the input buffer to the block
 | 
						|
 | 
						|
  @param[in]  Instance          The FV instance to be written to
 | 
						|
  @param[in]  Lba               The starting logical block index to write to
 | 
						|
  @param[in]  BlockOffset       Offset into the block at which to begin writing
 | 
						|
  @param[in, out]  NumBytes     Pointer that on input contains the total size of
 | 
						|
                                 the buffer. On output, it contains the total number
 | 
						|
                                 of bytes actually written
 | 
						|
  @param[in]  Buffer            Pointer 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 Write attempted across a 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 not functioning correctly and
 | 
						|
                                  could not be written
 | 
						|
  @retval     EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FvbWriteBlock (
 | 
						|
  IN UINTN      Instance,
 | 
						|
  IN EFI_LBA    Lba,
 | 
						|
  IN UINTN      BlockOffset,
 | 
						|
  IN OUT UINTN  *NumBytes,
 | 
						|
  IN UINT8      *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FVB_ATTRIBUTES_2  Attributes;
 | 
						|
  UINTN                 LbaAddress;
 | 
						|
  UINTN                 LbaLength;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  if ((NumBytes == NULL) || (Buffer == NULL)) {
 | 
						|
    return (EFI_INVALID_PARAMETER);
 | 
						|
  }
 | 
						|
 | 
						|
  if (*NumBytes == 0) {
 | 
						|
    return (EFI_INVALID_PARAMETER);
 | 
						|
  }
 | 
						|
 | 
						|
  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if the FV is write enabled
 | 
						|
  //
 | 
						|
  Attributes = FvbGetVolumeAttributes (Instance);
 | 
						|
  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
 | 
						|
    return EFI_ACCESS_DENIED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Perform boundary checks and adjust NumBytes
 | 
						|
  //
 | 
						|
  if (BlockOffset > LbaLength) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( LbaLength < (*NumBytes + BlockOffset)) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_ERROR,
 | 
						|
      "FvWriteBlock: Reducing Numbytes from 0x%x to 0x%x\n",
 | 
						|
      *NumBytes,
 | 
						|
      (UINT32)(LbaLength - BlockOffset)
 | 
						|
      ));
 | 
						|
    *NumBytes = (UINT32)(LbaLength - BlockOffset);
 | 
						|
    return EFI_BAD_BUFFER_SIZE;
 | 
						|
  }
 | 
						|
 | 
						|
  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);
 | 
						|
  Status = LibFvbFlashDeviceWrite (LbaAddress + BlockOffset, NumBytes, Buffer);
 | 
						|
 | 
						|
  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);
 | 
						|
  WriteBackInvalidateDataCacheRange ((VOID *)(LbaAddress + BlockOffset), *NumBytes);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Erases and initializes a firmware volume block
 | 
						|
 | 
						|
  @param[in]    Instance    The FV instance to be erased
 | 
						|
  @param[in]    Lba         The logical block index to be erased
 | 
						|
 | 
						|
  @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. Firmware device may have been
 | 
						|
                              partially erased
 | 
						|
  @retval   EFI_INVALID_PARAMETER Instance not found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FvbEraseBlock (
 | 
						|
  IN UINTN    Instance,
 | 
						|
  IN EFI_LBA  Lba
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FVB_ATTRIBUTES_2  Attributes;
 | 
						|
  UINTN                 LbaAddress;
 | 
						|
  UINTN                 LbaLength;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if the FV is write enabled
 | 
						|
  //
 | 
						|
  Attributes = FvbGetVolumeAttributes (Instance);
 | 
						|
 | 
						|
  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
 | 
						|
    return (EFI_ACCESS_DENIED);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the starting address of the block for erase.
 | 
						|
  //
 | 
						|
  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);
 | 
						|
 | 
						|
  Status = LibFvbFlashDeviceBlockErase (LbaAddress, LbaLength);
 | 
						|
 | 
						|
  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);
 | 
						|
 | 
						|
  WriteBackInvalidateDataCacheRange ((VOID *)LbaAddress, LbaLength);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Modifies the current settings of the firmware volume according to the
 | 
						|
  input parameter, and returns the new setting of the volume
 | 
						|
 | 
						|
  @param[in]  Instance              The FV instance whose attributes is going to be
 | 
						|
                                    modified
 | 
						|
  @param[in, out]  Attributes       On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
 | 
						|
                                    containing the desired firmware volume settings.
 | 
						|
                                    On successful return, it contains the new settings
 | 
						|
                                    of the firmware volume
 | 
						|
 | 
						|
  @retval     EFI_SUCCESS           Successfully returns
 | 
						|
  @retval     EFI_ACCESS_DENIED     The volume setting is locked and cannot be modified
 | 
						|
  @retval     EFI_INVALID_PARAMETER Instance not found, or The attributes requested are
 | 
						|
                                    in conflict with the capabilities as declared in the
 | 
						|
                                    firmware volume header
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
FvbSetVolumeAttributes (
 | 
						|
  IN UINTN                     Instance,
 | 
						|
  IN OUT EFI_FVB_ATTRIBUTES_2  *Attributes
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_INSTANCE   *FwhInstance;
 | 
						|
  EFI_FVB_ATTRIBUTES_2  OldAttributes;
 | 
						|
  EFI_FVB_ATTRIBUTES_2  *AttribPtr;
 | 
						|
  EFI_FVB_ATTRIBUTES_2  UnchangedAttributes;
 | 
						|
  UINT32                Capabilities;
 | 
						|
  UINT32                OldStatus;
 | 
						|
  UINT32                NewStatus;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the right instance of the FVB private data
 | 
						|
  //
 | 
						|
  FwhInstance = GetFvbInstance (Instance);
 | 
						|
  if (FwhInstance == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AttribPtr = (EFI_FVB_ATTRIBUTES_2 *)&(FwhInstance->VolumeHeader.Attributes);
 | 
						|
  ASSERT (AttribPtr != NULL);
 | 
						|
  if ( AttribPtr == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  OldAttributes = *AttribPtr;
 | 
						|
  Capabilities  = OldAttributes & EFI_FVB2_CAPABILITIES;
 | 
						|
  OldStatus     = OldAttributes & EFI_FVB2_STATUS;
 | 
						|
  NewStatus     = *Attributes   & EFI_FVB2_STATUS;
 | 
						|
 | 
						|
  UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP  | \
 | 
						|
                        EFI_FVB2_READ_ENABLED_CAP   | \
 | 
						|
                        EFI_FVB2_WRITE_DISABLED_CAP | \
 | 
						|
                        EFI_FVB2_WRITE_ENABLED_CAP  | \
 | 
						|
                        EFI_FVB2_LOCK_CAP           | \
 | 
						|
                        EFI_FVB2_STICKY_WRITE       | \
 | 
						|
                        EFI_FVB2_MEMORY_MAPPED      | \
 | 
						|
                        EFI_FVB2_ERASE_POLARITY     | \
 | 
						|
                        EFI_FVB2_READ_LOCK_CAP      | \
 | 
						|
                        EFI_FVB2_WRITE_LOCK_CAP     | \
 | 
						|
                        EFI_FVB2_ALIGNMENT;
 | 
						|
 | 
						|
  //
 | 
						|
  // Some attributes of FV is read only can *not* be set
 | 
						|
  //
 | 
						|
  if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If firmware volume is locked, no status bit can be updated
 | 
						|
  //
 | 
						|
  if ((OldAttributes & EFI_FVB2_LOCK_STATUS) != 0) {
 | 
						|
    if ((OldStatus ^ NewStatus) != 0) {
 | 
						|
      return EFI_ACCESS_DENIED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Test read disable
 | 
						|
  //
 | 
						|
  if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
 | 
						|
    if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Test read enable
 | 
						|
  //
 | 
						|
  if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
 | 
						|
    if ((NewStatus & EFI_FVB2_READ_STATUS) != 0) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Test write disable
 | 
						|
  //
 | 
						|
  if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
 | 
						|
    if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Test write enable
 | 
						|
  //
 | 
						|
  if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
 | 
						|
    if ((NewStatus & EFI_FVB2_WRITE_STATUS) != 0) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Test lock
 | 
						|
  //
 | 
						|
  if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
 | 
						|
    if ((NewStatus & EFI_FVB2_LOCK_STATUS) != 0) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *AttribPtr  = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
 | 
						|
  *AttribPtr  = (*AttribPtr) | NewStatus;
 | 
						|
  *Attributes = *AttribPtr;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieves the physical address of the device.
 | 
						|
 | 
						|
  @param[in]  This    A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
 | 
						|
  @param[out] Address Output buffer containing the address.
 | 
						|
 | 
						|
  @retval     EFI_SUCCESS The function always return successfully.
 | 
						|
  @retval     EFI_INVALID_PARAMETER Instance not found.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FvbProtocolGetPhysicalAddress (
 | 
						|
  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS                     *Address
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
 | 
						|
  EFI_FW_VOL_INSTANCE      *FwhInstance;
 | 
						|
 | 
						|
  FvbDevice   = FVB_DEVICE_FROM_THIS (This);
 | 
						|
  FwhInstance = GetFvbInstance (FvbDevice->Instance);
 | 
						|
  if (FwhInstance == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Address = FwhInstance->FvBase;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieve the size of a logical block
 | 
						|
 | 
						|
  @param[in]  This        Calling context
 | 
						|
  @param[in]  Lba         Indicates which block to return the size for.
 | 
						|
  @param[out] BlockSize   A pointer to a caller allocated UINTN in which
 | 
						|
                          the size of the block is returned
 | 
						|
  @param[out] NumOfBlocks A 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 function always return successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FvbProtocolGetBlockSize (
 | 
						|
  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
 | 
						|
  IN  EFI_LBA                                  Lba,
 | 
						|
  OUT UINTN                                    *BlockSize,
 | 
						|
  OUT UINTN                                    *NumOfBlocks
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
 | 
						|
 | 
						|
  FvbDevice = FVB_DEVICE_FROM_THIS (This);
 | 
						|
  return FvbGetLbaAddress (FvbDevice->Instance, Lba, NULL, BlockSize, NumOfBlocks);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieves Volume attributes.  No polarity translations are done.
 | 
						|
 | 
						|
  @param[in]    This        Calling context
 | 
						|
  @param[out]   Attributes  Output buffer which contains attributes
 | 
						|
 | 
						|
  @retval       EFI_SUCCESS The function always return successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FvbProtocolGetAttributes (
 | 
						|
  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);
 | 
						|
  *Attributes = FvbGetVolumeAttributes (FvbDevice->Instance);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sets Volume attributes. No polarity translations are done.
 | 
						|
 | 
						|
  @param[in]      This        Calling context
 | 
						|
  @param[in, out] Attributes  Output buffer which contains attributes
 | 
						|
 | 
						|
  @retval     EFI_SUCCESS The function always return successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FvbProtocolSetAttributes (
 | 
						|
  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
 | 
						|
  IN OUT EFI_FVB_ATTRIBUTES_2                  *Attributes
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS               Status;
 | 
						|
  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
 | 
						|
 | 
						|
  FvbDevice = FVB_DEVICE_FROM_THIS (This);
 | 
						|
  Status    = FvbSetVolumeAttributes (FvbDevice->Instance, Attributes);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This 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[in] This         Calling context
 | 
						|
  @param[in] ...          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. Firmware device may have been
 | 
						|
                            partially erased
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FvbProtocolEraseBlocks (
 | 
						|
  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
 | 
						|
  EFI_FW_VOL_INSTANCE      *FwhInstance;
 | 
						|
  UINTN                    NumOfBlocks;
 | 
						|
  VA_LIST                  args;
 | 
						|
  EFI_LBA                  StartingLba;
 | 
						|
  UINTN                    NumOfLba;
 | 
						|
  EFI_STATUS               Status;
 | 
						|
 | 
						|
  FvbDevice   = FVB_DEVICE_FROM_THIS (This);
 | 
						|
  FwhInstance = GetFvbInstance (FvbDevice->Instance);
 | 
						|
  if (FwhInstance == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  NumOfBlocks = FwhInstance->NumOfBlocks;
 | 
						|
  VA_START (args, This);
 | 
						|
 | 
						|
  do {
 | 
						|
    StartingLba = VA_ARG (args, EFI_LBA);
 | 
						|
    if ( StartingLba == EFI_LBA_LIST_TERMINATOR ) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    NumOfLba = VA_ARG (args, UINT32);
 | 
						|
 | 
						|
    //
 | 
						|
    // Check input parameters
 | 
						|
    //
 | 
						|
    if (NumOfLba == 0) {
 | 
						|
      VA_END (args);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((StartingLba + NumOfLba) > NumOfBlocks ) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  } while (1);
 | 
						|
 | 
						|
  VA_END (args);
 | 
						|
 | 
						|
  VA_START (args, This);
 | 
						|
  do {
 | 
						|
    StartingLba = VA_ARG (args, EFI_LBA);
 | 
						|
    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    NumOfLba = VA_ARG (args, UINT32);
 | 
						|
 | 
						|
    while ( NumOfLba > 0 ) {
 | 
						|
      Status = FvbEraseBlock (FvbDevice->Instance, StartingLba);
 | 
						|
      if ( EFI_ERROR (Status)) {
 | 
						|
        VA_END (args);
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      StartingLba++;
 | 
						|
      NumOfLba--;
 | 
						|
    }
 | 
						|
  } while (1);
 | 
						|
 | 
						|
  VA_END (args);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Writes data beginning at Lba:Offset from FV. The write terminates either
 | 
						|
  when *NumBytes of data have been written, or when a block boundary is
 | 
						|
  reached.  *NumBytes is updated to reflect the actual number of bytes
 | 
						|
  written. The write opertion does not include erase. This routine will
 | 
						|
  attempt to write only the specified bytes. If the writes do not stick,
 | 
						|
  it will return an error.
 | 
						|
 | 
						|
  @param[in]      This      Calling context
 | 
						|
  @param[in]      Lba       Block in which to begin write
 | 
						|
  @param[in]      Offset    Offset in the block at which to begin write
 | 
						|
  @param[in,out]  NumBytes  On input, indicates the requested write size. On
 | 
						|
                            output, indicates the actual number of bytes written
 | 
						|
  @param[in]      Buffer    Buffer containing source data for the write.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The firmware volume was written successfully
 | 
						|
  @retval EFI_BAD_BUFFER_SIZE   Write attempted across a 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 not functioning correctly and
 | 
						|
                                could not be written
 | 
						|
  @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FvbProtocolWrite (
 | 
						|
  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
 | 
						|
  IN EFI_LBA                                   Lba,
 | 
						|
  IN UINTN                                     Offset,
 | 
						|
  IN OUT UINTN                                 *NumBytes,
 | 
						|
  IN UINT8                                     *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
 | 
						|
  EFI_STATUS               Status;
 | 
						|
 | 
						|
  FvbDevice = FVB_DEVICE_FROM_THIS (This);
 | 
						|
  Status    = FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);
 | 
						|
  DEBUG ((
 | 
						|
    DEBUG_VERBOSE,
 | 
						|
    "FvbWrite: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x Status:%r\n",
 | 
						|
    Lba,
 | 
						|
    Offset,
 | 
						|
    *NumBytes,
 | 
						|
    Buffer,
 | 
						|
    Status
 | 
						|
    ));
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Reads data beginning at Lba:Offset from FV. The Read terminates either
 | 
						|
  when *NumBytes of data have been read, or when a block boundary is
 | 
						|
  reached.  *NumBytes is updated to reflect the actual number of bytes
 | 
						|
  written. The write opertion does not include erase. This routine will
 | 
						|
  attempt to write only the specified bytes. If the writes do not stick,
 | 
						|
  it will return an error.
 | 
						|
 | 
						|
  @param[in]      This      Calling context
 | 
						|
  @param[in]      Lba       Block in which to begin write
 | 
						|
  @param[in]      Offset    Offset in the block at which to begin write
 | 
						|
  @param[in,out]  NumBytes  On input, indicates the requested write size. On
 | 
						|
                            output, indicates the actual number of bytes written
 | 
						|
  @param[out]     Buffer    Buffer containing source data for the write.
 | 
						|
 | 
						|
 | 
						|
Returns:
 | 
						|
  @retval EFI_SUCCESS           The firmware volume was read successfully and
 | 
						|
                                contents are in Buffer
 | 
						|
  @retval EFI_BAD_BUFFER_SIZE   Read attempted across a LBA boundary. On output,
 | 
						|
                                NumBytes contains the total number of bytes returned
 | 
						|
                                in Buffer
 | 
						|
  @retval EFI_ACCESS_DENIED     The firmware volume is in the ReadDisabled state
 | 
						|
  @retval EFI_DEVICE_ERROR      The block device is not functioning correctly and
 | 
						|
                                could not be read
 | 
						|
  @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
FvbProtocolRead (
 | 
						|
  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
 | 
						|
  IN EFI_LBA                                   Lba,
 | 
						|
  IN UINTN                                     Offset,
 | 
						|
  IN OUT UINTN                                 *NumBytes,
 | 
						|
  OUT UINT8                                    *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
 | 
						|
  EFI_STATUS               Status;
 | 
						|
 | 
						|
  FvbDevice = FVB_DEVICE_FROM_THIS (This);
 | 
						|
  Status    = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);
 | 
						|
  DEBUG ((
 | 
						|
    DEBUG_VERBOSE,
 | 
						|
    "FvbRead: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x, Status:%r\n",
 | 
						|
    Lba,
 | 
						|
    Offset,
 | 
						|
    *NumBytes,
 | 
						|
    Buffer,
 | 
						|
    Status
 | 
						|
    ));
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check the integrity of firmware volume header in FvBase
 | 
						|
 | 
						|
  @param[in]  FvBase        A pointer to firmware volume base address.
 | 
						|
 | 
						|
  @retval     TRUE          The firmware volume is consistent
 | 
						|
  @retval     FALSE         The firmware volume has corrupted.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsFvHeaderValid (
 | 
						|
  IN       EFI_PHYSICAL_ADDRESS  FvBase
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT16                      Sum;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader;
 | 
						|
 | 
						|
  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;
 | 
						|
  if (FvBase == PcdGet32 (PcdFlashNvStorageVariableBase)) {
 | 
						|
    if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof (EFI_GUID)) != 0 ) {
 | 
						|
      DEBUG ((DEBUG_INFO, "  --FileSystemGuid not match: %g\n", &FwVolHeader->FileSystemGuid));
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof (EFI_GUID)) != 0 ) {
 | 
						|
      DEBUG ((DEBUG_INFO, "  --not expected guid.\n"));
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ((FwVolHeader->Revision != EFI_FVH_REVISION)   ||
 | 
						|
      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
 | 
						|
      (FwVolHeader->FvLength == ((UINTN)-1))       ||
 | 
						|
      ((FwVolHeader->HeaderLength & 0x01) != 0))
 | 
						|
  {
 | 
						|
    DEBUG ((DEBUG_INFO, "  -- >Revision = 0x%x, Signature = 0x%x\n", FwVolHeader->Revision, FwVolHeader->Signature));
 | 
						|
    DEBUG ((DEBUG_INFO, "  -- >FvLength = 0x%lx, HeaderLength = 0x%x\n", FwVolHeader->FvLength, FwVolHeader->HeaderLength));
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  Sum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);
 | 
						|
  if (Sum != 0) {
 | 
						|
    DEBUG ((DEBUG_INFO, "error: checksum: 0x%04X (expect 0x0)\n", Sum));
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get intial variable data.
 | 
						|
 | 
						|
  @param[out]  VarData          Valid variable data.
 | 
						|
  @param[out]  VarSize          Valid variable size.
 | 
						|
 | 
						|
  @retval RETURN_SUCCESS        Successfully found initial variable data.
 | 
						|
  @retval RETURN_NOT_FOUND      Failed to find the variable data file from FV.
 | 
						|
  @retval EFI_INVALID_PARAMETER VarData or VarSize is null.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetInitialVariableData (
 | 
						|
  OUT VOID   **VarData,
 | 
						|
  OUT UINTN  *VarSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  VOID                           *ImageData;
 | 
						|
  UINTN                          ImageSize;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER     *FvHeader;
 | 
						|
  VARIABLE_STORE_HEADER          *VariableStore;
 | 
						|
  AUTHENTICATED_VARIABLE_HEADER  *Variable;
 | 
						|
  UINTN                          VariableSize;
 | 
						|
  UINTN                          VarEndAddr;
 | 
						|
 | 
						|
  if ((VarData == NULL) || (VarSize == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = GetSectionFromAnyFv (PcdGetPtr (PcdNvsDataFile), EFI_SECTION_RAW, 0, &ImageData, &ImageSize);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  FvHeader      = (EFI_FIRMWARE_VOLUME_HEADER *)ImageData;
 | 
						|
  VariableStore = (VARIABLE_STORE_HEADER *)((UINT8 *)ImageData + FvHeader->HeaderLength);
 | 
						|
  VarEndAddr    = (UINTN)VariableStore + VariableStore->Size;
 | 
						|
  Variable      = (AUTHENTICATED_VARIABLE_HEADER *)HEADER_ALIGN (VariableStore + 1);
 | 
						|
  *VarData      = (VOID *)Variable;
 | 
						|
  while (((UINTN)Variable < VarEndAddr)) {
 | 
						|
    if (Variable->StartId != VARIABLE_DATA) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    VariableSize = sizeof (AUTHENTICATED_VARIABLE_HEADER) + Variable->DataSize + Variable->NameSize;
 | 
						|
    Variable     = (AUTHENTICATED_VARIABLE_HEADER *)HEADER_ALIGN ((UINTN)Variable + VariableSize);
 | 
						|
  }
 | 
						|
 | 
						|
  *VarSize = (UINTN)Variable - HEADER_ALIGN (VariableStore + 1);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The function does the necessary initialization work for
 | 
						|
  Firmware Volume Block Driver.
 | 
						|
 | 
						|
  @retval     EFI_SUCCESS       This funtion always return EFI_SUCCESS.
 | 
						|
                                It will ASSERT on errors.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FvbInitialize (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_FW_VOL_INSTANCE         *FwVolInstance;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
 | 
						|
  EFI_FV_BLOCK_MAP_ENTRY      *BlockMap;
 | 
						|
  EFI_PHYSICAL_ADDRESS        BaseAddress;
 | 
						|
  UINTN                       WriteAddr;
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  UINTN                       BufferSize;
 | 
						|
  UINTN                       Length;
 | 
						|
  VARIABLE_STORE_HEADER       VariableStore;
 | 
						|
  VOID                        *VarData;
 | 
						|
 | 
						|
  InitVariableStore ();
 | 
						|
  BaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase);
 | 
						|
  FvHeader    = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check FV header and variable store header
 | 
						|
  //
 | 
						|
  if (!IsFvHeaderValid (BaseAddress)) {
 | 
						|
    //
 | 
						|
    //  Write back a healthy FV header
 | 
						|
    //
 | 
						|
    DEBUG ((DEBUG_ERROR, "Fvb: Writing back a healthy FV header: 0x%lx\n", BaseAddress));
 | 
						|
    FvHeader = GetFvHeaderTemplate ();
 | 
						|
    LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FvHeader->BlockMap->Length, FALSE);
 | 
						|
 | 
						|
    Status = LibFvbFlashDeviceBlockErase ((UINTN)BaseAddress, FvHeader->BlockMap->Length);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    Length     = FvHeader->HeaderLength;
 | 
						|
    WriteAddr  = (UINTN)BaseAddress;
 | 
						|
    Status     = LibFvbFlashDeviceWrite (WriteAddr, &Length, (UINT8 *)FvHeader);
 | 
						|
    WriteAddr += Length;
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Write back variable store header
 | 
						|
    //
 | 
						|
    VariableStore.Size   = PcdGet32 (PcdFlashNvStorageVariableSize) - FvHeader->HeaderLength;
 | 
						|
    VariableStore.Format = VARIABLE_STORE_FORMATTED;
 | 
						|
    VariableStore.State  = VARIABLE_STORE_HEALTHY;
 | 
						|
    CopyGuid (&VariableStore.Signature, &gEfiAuthenticatedVariableGuid);
 | 
						|
    BufferSize = sizeof (VARIABLE_STORE_HEADER);
 | 
						|
    Status     = LibFvbFlashDeviceWrite (WriteAddr, &BufferSize, (UINT8 *)&VariableStore);
 | 
						|
    WriteAddr += BufferSize;
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Write initial variable data if found
 | 
						|
    //
 | 
						|
    Status = GetInitialVariableData (&VarData, &Length);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      Status = LibFvbFlashDeviceWrite (WriteAddr, &Length, (UINT8 *)VarData);
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
    }
 | 
						|
 | 
						|
    LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FvHeader->BlockMap->Length, TRUE);
 | 
						|
    WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)BaseAddress, FvHeader->BlockMap->Length);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create a new FW volume instance for NVS variable
 | 
						|
  //
 | 
						|
  BufferSize    = FvHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER);
 | 
						|
  FwVolInstance = (EFI_FW_VOL_INSTANCE *)AllocateRuntimeZeroPool (BufferSize);
 | 
						|
  if (FwVolInstance == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  FwVolInstance->FvBase = (UINTN)BaseAddress;
 | 
						|
  CopyMem (&FwVolInstance->VolumeHeader, FvHeader, FvHeader->HeaderLength);
 | 
						|
 | 
						|
  //
 | 
						|
  // Process the block map for each FV. Assume it has same block size.
 | 
						|
  //
 | 
						|
  FwVolInstance->NumOfBlocks = 0;
 | 
						|
  FvHeader                   = &FwVolInstance->VolumeHeader;
 | 
						|
  for (BlockMap = FvHeader->BlockMap; BlockMap->NumBlocks != 0; BlockMap++) {
 | 
						|
    FwVolInstance->NumOfBlocks += BlockMap->NumBlocks;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add a FVB Protocol Instance
 | 
						|
  //
 | 
						|
  Status = InstallFvbProtocol (FwVolInstance, mFvbModuleGlobal.NumFv);
 | 
						|
  mFvbModuleGlobal.NumFv++;
 | 
						|
  mFvbModuleGlobal.FvInstance = FwVolInstance;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |