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;
 | |
| }
 |