13cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/** @file
23cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Firmware Volume Block Driver for Lakeport Platform.
33cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
43cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Firmware volume block driver for FWH or SPI device.
53cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  It depends on which Flash Device Library to be linked with this driver.
63cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
73cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiCopyright (c) 2006  - 2014, Intel Corporation. All rights reserved.<BR>
83cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
93cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This program and the accompanying materials are licensed and made available under
113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  the terms and conditions of the BSD License that accompanies this distribution.
133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The full text of the license may be found at
153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  http://opensource.org/licenses/bsd-license.php.
173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "FvbService.h"
303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// Global variable for this FVB driver  which contains
333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// the private data of all firmware volume block instances.
343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
353cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFWB_GLOBAL   mFvbModuleGlobal;
363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// This platform driver knows there are 3 FVs on
393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// FD, which are FvRecovery, FvMain and FvNvStorage.
403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
413cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiUINT32 mPlatformFvBaseAddress[] = {
423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FixedPcdGet32(PcdFlashNvStorageVariableBase),
433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei};
443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
453cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {
463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      HARDWARE_DEVICE_PATH,
493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      HW_MEMMAP_DP,
503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      {
513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    },
553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    EfiMemoryMappedIO,
563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    (EFI_PHYSICAL_ADDRESS) 0,
573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    (EFI_PHYSICAL_ADDRESS) 0,
583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  },
593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_DEVICE_PATH_TYPE,
613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_ENTIRE_DEVICE_PATH_SUBTYPE,
623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      END_DEVICE_PATH_LENGTH,
643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      0
653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei};
683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
693cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {
703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MEDIA_DEVICE_PATH,
733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MEDIA_PIWG_FW_VOL_DP,
743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      {
753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    },
793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    { 0 }
803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  },
813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_DEVICE_PATH_TYPE,
833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_ENTIRE_DEVICE_PATH_SUBTYPE,
843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      END_DEVICE_PATH_LENGTH,
863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      0
873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei};
903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// Template structure used when installing FVB protocol.
933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
943cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FVB_DEVICE_SIGNATURE,
963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  NULL,
973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  0, // Instance
983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbProtocolGetAttributes,
1003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbProtocolSetAttributes,
1013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbProtocolGetPhysicalAddress,
1023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbProtocolGetBlockSize,
1033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbProtocolRead,
1043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbProtocolWrite,
1053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbProtocolEraseBlocks,
1063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NULL
1073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } // FwVolBlockInstance
1083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei};
1093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
1123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Get the pointer to EFI_FW_VOL_INSTANCE from the buffer pointed
1133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  by mFvbModuleGlobal.FvInstance based on a index.
1143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Each EFI_FW_VOL_INSTANCE is  with variable length as
1153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  we have a block map at the end of the EFI_FIRMWARE_VOLUME_HEADER.
1163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] Instance The index of the EFI_FW_VOL_INSTANCE.
1183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @return A pointer to EFI_FW_VOL_INSTANCE.
1203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
1223cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_FW_VOL_INSTANCE *
1233cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiGetFvbInstance (
1243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN  UINTN             Instance
1253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
1263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
1273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE   *FwhRecord;
1283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( Instance >= mFvbModuleGlobal.NumFv ) {
1303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
1313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return NULL;
1323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
1333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
1353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Find the right instance of the FVB private data.
1363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
1373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwhRecord = mFvbModuleGlobal.FvInstance;
1383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  while ( Instance > 0 ) {
1393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FwhRecord = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhRecord) +
1403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                FwhRecord->VolumeHeader.HeaderLength +
1413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));
1423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Instance --;
1433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
1443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return FwhRecord;
1463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
1483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
1513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Get the EFI_FVB_ATTRIBUTES_2 of a FV.
1523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  The index of the EFI_FW_VOL_INSTANCE.
1543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @return     EFI_FVB_ATTRIBUTES_2 of the FV identified by Instance.
1563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
1583cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSTATIC
1593cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_FVB_ATTRIBUTES_2
1603cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbGetVolumeAttributes (
1613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                Instance
1623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
1633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
1643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE *    FwInstance = NULL;
1653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwInstance = GetFvbInstance(Instance);
1663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (FwInstance != NULL);
1673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( FwInstance != NULL ) {
1693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return FwInstance->VolumeHeader.Attributes;
1703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } else {
1713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return 0;
1723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
1733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
1743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
1773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Retrieves the starting address of an LBA in an FV. It also
1783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return a few other attribut of the FV.
1793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Instance               The index of the EFI_FW_VOL_INSTANCE.
1813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Lba                    The logical block address.
1823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] LbaAddress             On output, contains the physical starting address
1833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     of the Lba.
1843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] LbaLength              On output, contains the length of the block.
1853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] NumOfBlocks            A pointer to a caller allocated UINTN in which the
1863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     number of consecutive blocks starting with Lba is
1873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     returned. All blocks in this range have a size of
1883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     BlockSize.
1893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval  EFI_SUCCESS Successfully  returns.
1913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval  EFI_INVALID_PARAMETER     Instance not found.
1923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
1943cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSTATIC
1953cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
1963cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbGetLbaAddress (
1973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN  UINTN                               Instance,
1983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN  EFI_LBA                             Lba,
1993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT UINTN                               *LbaAddress,
2003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT UINTN                               *LbaLength,
2013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT UINTN                               *NumOfBlocks
2023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
2033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
2043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINT32                                  NumBlocks = 0;
2053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINT32                                  BlockLength = 0;
2063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                   Offset;
2073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_LBA                                 StartLba;
2083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_LBA                                 NextLba;
2093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE                     *FwhInstance;
2103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FV_BLOCK_MAP_ENTRY                  *BlockMap = NULL;
2113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Find the right instance of the FVB private data.
2143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwhInstance = GetFvbInstance (Instance);
2163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  StartLba  = 0;
2183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Offset    = 0;
2193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BlockMap  = &(FwhInstance->VolumeHeader.BlockMap[0]);
2203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (BlockMap != NULL);
2213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Parse the blockmap of the FV to find which map entry the Lba belongs to.
2243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  while (TRUE) {
2263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ( BlockMap != NULL) {
2273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      NumBlocks   = BlockMap->NumBlocks;
2283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      BlockLength = BlockMap->Length;
2293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
2303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ( NumBlocks == 0 || BlockLength == 0) {
2323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
2333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
2343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NextLba = StartLba + NumBlocks;
2363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
2383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // The map entry found.
2393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
2403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (Lba >= StartLba && Lba < NextLba) {
2413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Offset = Offset + (UINTN)MultU64x32((Lba - StartLba), BlockLength);
2423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if ( LbaAddress && FwhInstance ) {
2433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        *LbaAddress = FwhInstance->FvBase + Offset;
2443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
2453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (LbaLength ) {
2473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        *LbaLength = BlockLength;
2483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
2493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (NumOfBlocks ) {
2513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        *NumOfBlocks = (UINTN)(NextLba - Lba);
2523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
2533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_SUCCESS;
2543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
2553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    StartLba  = NextLba;
2573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Offset    = Offset + NumBlocks * BlockLength;
2583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    BlockMap++;
2593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
2613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
2643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Reads specified number of bytes into a buffer from the specified block.
2653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Instance               The FV instance to be read from.
2673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Lba                    The logical block address to be read from.
2683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      BlockOffset            Offset into the block at which to begin reading.
2693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      NumBytes               Pointer that on input contains the total size of
2703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                         the buffer. On output, it contains the total number
2713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                         of bytes read.
2723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Buffer                 Pointer to a caller allocated buffer that will be
2733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                         used to hold the data read.
2743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval         EFI_SUCCESS            The firmware volume was read successfully and
2773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                         contents are in Buffer.
2783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval         EFI_BAD_BUFFER_SIZE    Read attempted across a LBA boundary. On output,
2793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                         NumBytes contains the total number of bytes returned
2803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                         in Buffer.
2813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval         EFI_ACCESS_DENIED      The firmware volume is in the ReadDisabled state.
2823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval         EFI_DEVICE_ERROR       The block device is not functioning correctly and
2833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                         could not be read.
2843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval         EFI_INVALID_PARAMETER  Instance not found, or NumBytes, Buffer are NULL.
2853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
2873cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSTATIC
2883cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
2893cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbReadBlock (
2903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                Instance,
2913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_LBA                              Lba,
2923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                BlockOffset,
2933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT UINTN                            *NumBytes,
2943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINT8                                *Buffer
2953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
2963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
2973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_ATTRIBUTES_2                    Attributes;
2983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                   LbaAddress;
2993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                   LbaLength;
3003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                              Status;
3013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( (NumBytes == NULL) || (Buffer == NULL)) {
3033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_INVALID_PARAMETER);
3043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (*NumBytes == 0) {
3063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_INVALID_PARAMETER);
3073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);
3103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR(Status)) {
3113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
3123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Attributes = FvbGetVolumeAttributes (Instance);
3153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( (Attributes & EFI_FVB2_READ_STATUS) == 0) {
3173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_ACCESS_DENIED);
3183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (BlockOffset > LbaLength) {
3213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei   return (EFI_INVALID_PARAMETER);
3223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (LbaLength < ( *NumBytes + BlockOffset ) ) {
3253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *NumBytes = (UINT32) (LbaLength - BlockOffset);
3263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = EFI_BAD_BUFFER_SIZE;
3273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  LibFvbFlashDeviceRead (LbaAddress + BlockOffset, NumBytes, Buffer);
3303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
3323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
3333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
3363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Writes specified number of bytes from the input buffer to the block.
3373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Instance               The FV instance to be written to.
3393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Lba                    The starting logical block index to write to.
3403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  BlockOffset            Offset into the block at which to begin writing.
3413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  NumBytes               Pointer that on input contains the total size of
3423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     the buffer. On output, it contains the total number
3433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     of bytes actually written.
3443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Buffer                 Pointer to a caller allocated buffer that contains
3453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     the source for the write.
3463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS            The firmware volume was written successfully.
3473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_BAD_BUFFER_SIZE    Write attempted across a LBA boundary. On output,
3483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     NumBytes contains the total number of bytes
3493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     actually writte.
3503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled state.
3513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_DEVICE_ERROR       The block device is not functioning correctly and
3523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                     could not be written.
3533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_INVALID_PARAMETER  Instance not found, or NumBytes, Buffer are NULL.
3543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
3563cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
3573cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbWriteBlock (
3583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                Instance,
3593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_LBA                              Lba,
3603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                BlockOffset,
3613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT UINTN                            *NumBytes,
3623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINT8                                *Buffer
3633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
3643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
3653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_ATTRIBUTES_2                    Attributes;
3663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                   LbaAddress;
3673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                   LbaLength;
3683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE                     *FwhInstance;
3693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                              Status;
3703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                              Status1;
3713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwhInstance = GetFvbInstance (Instance);
3733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( (NumBytes == NULL) || (Buffer == NULL)) {
3753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_INVALID_PARAMETER);
3763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (*NumBytes == 0) {
3783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_INVALID_PARAMETER);
3793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);
3823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR(Status)) {
3833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
3843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Check if the FV is write enabled.
3883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Attributes = FvbGetVolumeAttributes (Instance);
3903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( (Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
3913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_ACCESS_DENIED);
3923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Perform boundary checks and adjust NumBytes.
3963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (BlockOffset > LbaLength) {
3983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_INVALID_PARAMETER);
3993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( LbaLength < ( *NumBytes + BlockOffset ) ) {
4023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    DEBUG ((EFI_D_ERROR,
4033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      "FvWriteBlock: Reducing Numbytes from 0x%x to 0x%x\n",
4043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      *NumBytes,
4053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      (UINT32)(LbaLength-BlockOffset))
4063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      );
4073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *NumBytes = (UINT32) (LbaLength - BlockOffset);
4083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = EFI_BAD_BUFFER_SIZE;
4093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);
4123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status1 = LibFvbFlashDeviceWrite (LbaAddress + BlockOffset, NumBytes, Buffer);
4143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);
4163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  WriteBackInvalidateDataCacheRange ((VOID *) (LbaAddress + BlockOffset), *NumBytes);
4173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( EFI_ERROR (Status1) ) {
4193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status1;
4203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
4233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
4243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
4273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Erases and initializes a firmware volume block.
4283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]    Instance           The FV instance to be erased.
4303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]    Lba                The logical block index to be erased.
4313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval   EFI_SUCCESS            The erase request was successfully completed.
4333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval   EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled state.
4343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval   EFI_DEVICE_ERROR       The block device is not functioning correctly and
4353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                   could not be written. Firmware device may have been
4363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                   partially erased.
4373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval   EFI_INVALID_PARAMETER  Instance not found.
4383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
4403cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
4413cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbEraseBlock (
4423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                Instance,
4433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_LBA                              Lba
4443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
4453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
4463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_ATTRIBUTES_2                    Attributes;
4473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                   LbaAddress;
4483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE                     *FwhInstance;
4493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                   LbaLength;
4503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                              Status;
4513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Find the right instance of the FVB private data.
4543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwhInstance = GetFvbInstance (Instance);
4563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Check if the FV is write enabled.
4593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Attributes = FvbGetVolumeAttributes (Instance);
4613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if( (Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
4633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return (EFI_ACCESS_DENIED);
4643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get the starting address of the block for erase.
4683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL);
4703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR(Status)) {
4713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
4723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, FALSE);
4753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = LibFvbFlashDeviceBlockErase (LbaAddress, LbaLength);
4773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  LibFvbFlashDeviceBlockLock (LbaAddress, LbaLength, TRUE);
4793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  WriteBackInvalidateDataCacheRange ((VOID *) LbaAddress, LbaLength);
4813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
4833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
4843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
4873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Modifies the current settings of the firmware volume according to the
4883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  input parameter, and returns the new setting of the volume.
4893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Instance              The FV instance whose attributes is going to be
4913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                    modified.
4923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Attributes            On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
4933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                    containing the desired firmware volume settings.
4943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                    On successful return, it contains the new settings
4953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                    of the firmware volume.
4963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS           Successfully returns.
4983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_ACCESS_DENIED     The volume setting is locked and cannot be modified.
4993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_INVALID_PARAMETER Instance not found, or The attributes requested are
5003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                    in conflict with the capabilities as declared in the
5013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                    firmware volume header.
5023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
5043cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSTATIC
5053cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
5063cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbSetVolumeAttributes (
5073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                Instance,
5083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT EFI_FVB_ATTRIBUTES_2             *Attributes
5093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
5103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
5113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE                       *FwhInstance = NULL;
5123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_ATTRIBUTES_2                      OldAttributes = 0;
5133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_ATTRIBUTES_2                      *AttribPtr = NULL;
5143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_ATTRIBUTES_2                      UnchangedAttributes;
5153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINT32                                    Capabilities;
5163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINT32                                    OldStatus, NewStatus;
5173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Find the right instance of the FVB private data.
5203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwhInstance = GetFvbInstance (Instance);
5223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  AttribPtr     = (EFI_FVB_ATTRIBUTES_2 *) & (FwhInstance->VolumeHeader.Attributes);
5243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (AttribPtr != NULL);
5253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( AttribPtr != NULL) {
5273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    OldAttributes = *AttribPtr;
5283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Capabilities  = OldAttributes & EFI_FVB2_CAPABILITIES;
5313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OldStatus     = OldAttributes & EFI_FVB2_STATUS;
5323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  NewStatus     = *Attributes & EFI_FVB2_STATUS;
5333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP  | \
5353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_READ_ENABLED_CAP   | \
5363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_WRITE_DISABLED_CAP | \
5373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_WRITE_ENABLED_CAP  | \
5383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_LOCK_CAP           | \
5393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_STICKY_WRITE       | \
5403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_MEMORY_MAPPED      | \
5413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_ERASE_POLARITY     | \
5423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_READ_LOCK_CAP      | \
5433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_WRITE_LOCK_CAP     | \
5443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                        EFI_FVB2_ALIGNMENT;
5453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Some attributes of FV is read only can *not* be set.
5483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) {
5503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
5513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // If firmware volume is locked, no status bit can be updated.
5553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( OldAttributes & EFI_FVB2_LOCK_STATUS ) {
5573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ( OldStatus ^ NewStatus ) {
5583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_ACCESS_DENIED;
5593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
5603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Test read disable.
5643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
5663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
5673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
5683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
5693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Test read enable.
5733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
5753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (NewStatus & EFI_FVB2_READ_STATUS) {
5763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
5773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
5783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Test write disable.
5823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
5843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
5853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
5863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
5873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Test write enable.
5913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
5933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (NewStatus & EFI_FVB2_WRITE_STATUS) {
5943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
5953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
5963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Test lock.
6003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
6023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (NewStatus & EFI_FVB2_LOCK_STATUS) {
6033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
6043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
6053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
6063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *AttribPtr  = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
6083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *AttribPtr  = (*AttribPtr) | NewStatus;
6093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *Attributes = *AttribPtr;
6103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
6123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
6133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
6153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// FVB protocol APIs.
6163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
6173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
6183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Retrieves the physical address of the device.
6193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  This    A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
6213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] Address Output buffer containing the address.
6223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  retval      EFI_SUCCESS The function always return successfully.
6243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
6263cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
6273cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
6283cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbProtocolGetPhysicalAddress (
6293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
6303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT EFI_PHYSICAL_ADDRESS               *Address
6313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
6323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
6333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;
6343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE                   *FvInstance;
6353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
6373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvInstance = GetFvbInstance(FvbDevice->Instance);
6383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (FvInstance != NULL) {
6403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *Address = FvInstance->FvBase;
6413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
6423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
6443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
6453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
6483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Retrieve the size of a logical block.
6493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  This         Calling context.
6513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Lba          Indicates which block to return the size for.
6523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] BlockSize    A pointer to a caller allocated UINTN in which
6533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                           the size of the block is returned.
6543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] NumOfBlocks  A pointer to a caller allocated UINTN in which the
6553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                           number of consecutive blocks starting with Lba is
6563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                           returned. All blocks in this range have a size of
6573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                           BlockSize.
6583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS  The function always return successfully.
6603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
6623cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
6633cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
6643cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbProtocolGetBlockSize (
6653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
6663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN  EFI_LBA                            Lba,
6673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT UINTN                              *BlockSize,
6683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT UINTN                              *NumOfBlocks
6693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
6703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
6713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_BLOCK_DEVICE                 *FvbDevice;
6723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DEBUG((EFI_D_INFO,
6743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    "FvbProtocolGetBlockSize: Lba: 0x%lx BlockSize: 0x%x NumOfBlocks: 0x%x\n",
6753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Lba,
6763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    BlockSize,
6773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NumOfBlocks)
6783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    );
6793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
6813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return FvbGetLbaAddress (
6833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei           FvbDevice->Instance,
6843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei           Lba,
6853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei           NULL,
6863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei           BlockSize,
6873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei           NumOfBlocks
6883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei           );
6893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
6903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
6933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Retrieves Volume attributes.  No polarity translations are done.
6943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]    This         Calling context.
6963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out]   Attributes   Output buffer which contains attributes.
6973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval       EFI_SUCCESS  The function always return successfully.
6993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
7013cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
7023cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
7033cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbProtocolGetAttributes (
7043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
7053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT EFI_FVB_ATTRIBUTES_2                *Attributes
7063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
7073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
7083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;
7093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
7113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *Attributes = FvbGetVolumeAttributes (FvbDevice->Instance);
7133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DEBUG ((EFI_D_INFO,
7153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    "FvbProtocolGetAttributes: This: 0x%x Attributes: 0x%x\n",
7163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    This,
7173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *Attributes)
7183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    );
7193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
7213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
7223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
7253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Sets Volume attributes. No polarity translations are done.
7263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  This         Calling context.
7283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] Attributes   Output buffer which contains attributes.
7293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS  The function always return successfully.
7313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
7333cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
7343cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
7353cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbProtocolSetAttributes (
7363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
7373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT EFI_FVB_ATTRIBUTES_2             *Attributes
7383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
7393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
7403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                            Status;
7413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;
7423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DEBUG((EFI_D_INFO,
7443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    "FvbProtocolSetAttributes: Before SET -  This: 0x%x Attributes: 0x%x\n",
7453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    This,
7463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *Attributes)
7473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    );
7483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
7503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = FvbSetVolumeAttributes (FvbDevice->Instance, Attributes);
7523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DEBUG((EFI_D_INFO,
7543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    "FvbProtocolSetAttributes: After SET -  This: 0x%x Attributes: 0x%x\n",
7553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    This,
7563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *Attributes)
7573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    );
7583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
7603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
7613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
7643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The EraseBlock() function erases one or more blocks as denoted by the
7653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  variable argument list. The entire parameter list of blocks must be verified
7663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  prior to erasing any blocks.  If a block is requested that does not exist
7673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  within the associated firmware volume (it has a larger index than the last
7683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  block of the firmware volume), the EraseBlock() function must return
7693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
7703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] This            Calling context.
7723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] ...             Starting LBA followed by Number of Lba to erase.
7733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                             a -1 to terminate the list.
7743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS        The erase request was successfully completed.
7763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_ACCESS_DENIED  The firmware volume is in the WriteDisabled state.
7773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_DEVICE_ERROR   The block device is not functioning correctly and
7783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                             could not be written. Firmware device may have been
7793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                             partially erased.
7803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
7823cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
7833cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
7843cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbProtocolEraseBlocks (
7853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,
7863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ...
7873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
7883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
7893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;
7903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE                   *FwhInstance;
7913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                 NumOfBlocks = 0;
7923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_LIST                               args;
7933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_LBA                               StartingLba;
7943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                 NumOfLba;
7953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                            Status;
7963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DEBUG((EFI_D_INFO, "FvbProtocolEraseBlocks: \n"));
7983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
7993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwhInstance  = GetFvbInstance (FvbDevice->Instance);
8013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (FwhInstance != NULL) {
8033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NumOfBlocks = FwhInstance->NumOfBlocks;
8043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
8053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_START (args, This);
8073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  do {
8093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    StartingLba = VA_ARG (args, EFI_LBA);
8103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ( StartingLba == EFI_LBA_LIST_TERMINATOR ) {
8113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      break;
8123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
8133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NumOfLba = VA_ARG (args, UINT32);
8153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Check input parameters.
8183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (NumOfLba == 0) {
8203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      VA_END (args);
8213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
8223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
8233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ( ( StartingLba + NumOfLba ) > NumOfBlocks ) {
8253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
8263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
8273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } while ( 1 );
8283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_END (args);
8303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_START (args, This);
8323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  do {
8333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    StartingLba = VA_ARG (args, EFI_LBA);
8343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
8353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      break;
8363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
8373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NumOfLba = VA_ARG (args, UINT32);
8393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    while ( NumOfLba > 0 ) {
8413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status = FvbEraseBlock (FvbDevice->Instance, StartingLba);
8423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if ( EFI_ERROR(Status)) {
8433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        VA_END (args);
8443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        return Status;
8453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
8463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      StartingLba ++;
8473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      NumOfLba --;
8483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
8493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } while ( 1 );
8513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_END (args);
8533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
8553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
8563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
8593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Writes data beginning at Lba:Offset from FV. The write terminates either
8603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  when *NumBytes of data have been written, or when a block boundary is
8613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  reached.  *NumBytes is updated to reflect the actual number of bytes
8623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  written. The write opertion does not include erase. This routine will
8633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  attempt to write only the specified bytes. If the writes do not stick,
8643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  it will return an error.
8653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      This      Calling context.
8673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Lba       Block in which to begin write.
8683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Offset    Offset in the block at which to begin write.
8693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in,out]  NumBytes  On input, indicates the requested write size. On
8703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                            output, indicates the actual number of bytes written
8713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Buffer    Buffer containing source data for the write.
8723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS           The firmware volume was written successfully.
8743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_BAD_BUFFER_SIZE   Write attempted across a LBA boundary. On output,
8753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                NumBytes contains the total number of bytes
8763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                actually written.
8773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_ACCESS_DENIED     The firmware volume is in the WriteDisabled state.
8783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_DEVICE_ERROR      The block device is not functioning correctly and
8793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                could not be written.
8803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL.
8813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
8833cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
8843cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
8853cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbProtocolWrite (
8863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
8873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_LBA                              Lba,
8883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                Offset,
8893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT UINTN                            *NumBytes,
8903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINT8                                *Buffer
8913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
8923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
8933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;
8953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
8973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DEBUG((EFI_D_INFO,
8993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    "FvbProtocolWrite: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n",
9003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Lba,
9013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Offset,
9023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *NumBytes,
9033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Buffer)
9043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    );
9053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);
9073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
9083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
9113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Reads data beginning at Lba:Offset from FV. The Read terminates either
9123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  when *NumBytes of data have been read, or when a block boundary is
9133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  reached.  *NumBytes is updated to reflect the actual number of bytes
9143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  written. The write opertion does not include erase. This routine will
9153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  attempt to write only the specified bytes. If the writes do not stick,
9163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  it will return an error.
9173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      This      Calling context.
9193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Lba       Block in which to begin write.
9203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Offset    Offset in the block at which to begin write
9213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in,out]  NumBytes  On input, indicates the requested write size. On
9223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                            output, indicates the actual number of bytes written.
9233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Buffer    Buffer containing source data for the write.
9243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9263cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiReturns:
9273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS            The firmware volume was read successfully and
9283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 contents are in Buffer.
9293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_BAD_BUFFER_SIZE    Read attempted across a LBA boundary. On output,
9303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 NumBytes contains the total number of bytes returned
9313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 in Buffer.
9323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_ACCESS_DENIED      The firmware volume is in the ReadDisabled state
9333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly and
9343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 could not be read.
9353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_INVALID_PARAMETER  NumBytes or Buffer are NULL.
9363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
9383cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
9393cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
9403cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbProtocolRead (
9413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
9423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_LBA                              Lba,
9433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINTN                                Offset,
9443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT UINTN                            *NumBytes,
9453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT UINT8                                *Buffer
9463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
9473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
9483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_BLOCK_DEVICE   *FvbDevice;
9503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                Status;
9513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
9533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer);
9543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DEBUG((EFI_D_INFO,
9553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    "FvbProtocolRead: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n",
9563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Lba,
9573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Offset,
9583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    *NumBytes,
9593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Buffer)
9603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    );
9613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
9633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
9643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
9673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Check the integrity of firmware volume header.
9683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  FwVolHeader   A pointer to a firmware volume header.
9703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     TRUE          The firmware volume is consistent.
9723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     FALSE         The firmware volume has corrupted.
9733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
9753cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBOOLEAN
9763cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiIsFvHeaderValid (
9773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       EFI_PHYSICAL_ADDRESS          FvBase,
9783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_HEADER    *FwVolHeader
9793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
9803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
9813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (FvBase == PcdGet32(PcdFlashNvStorageVariableBase)) {
9823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof(EFI_GUID)) != 0 ) {
9833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return FALSE;
9843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
9853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } else {
9863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) {
9873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return FALSE;
9883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
9893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
9903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ( (FwVolHeader->Revision != EFI_FVH_REVISION)   ||
9913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei       (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
9923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei       (FwVolHeader->FvLength == ((UINTN) -1))       ||
9933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei       ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) {
9943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return FALSE;
9953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
9963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength) != 0) {
9983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return FALSE;
9993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
10003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return TRUE;
10023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
10033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
10063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The function does the necessary initialization work for
10073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Firmware Volume Block Driver.
10083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS       This funtion always return EFI_SUCCESS.
10103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                It will ASSERT on errors.
10113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
10133cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
10143cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbInitialize (
10153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID
10163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
10173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
10183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FW_VOL_INSTANCE                   *FwhInstance;
10193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;
10203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
10213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FV_BLOCK_MAP_ENTRY                *PtrBlockMapEntry;
10223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_PHYSICAL_ADDRESS                  BaseAddress;
10233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                            Status;
10243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                 BufferSize;
10253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                 TmpHeaderLength;
10263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                 Idx;
10273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINT32                                MaxLbaSize;
10283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BOOLEAN                               FvHeaderValid;
10293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
10313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Calculate the total size for all firmware volume block instances.
10323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
10333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BufferSize = 0;
10343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  for (Idx = 0; Idx < 1; Idx++) {
10353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) mPlatformFvBaseAddress[Idx];
10363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    BufferSize +=  (FvHeader->HeaderLength +
10373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    sizeof (EFI_FW_VOL_INSTANCE) -
10383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    sizeof (EFI_FIRMWARE_VOLUME_HEADER)
10393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                   );
10403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
10413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  mFvbModuleGlobal.FvInstance =  (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize);
10433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT (NULL != mFvbModuleGlobal.FvInstance);
10443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  MaxLbaSize      = 0;
10473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FwhInstance     = mFvbModuleGlobal.FvInstance;
10483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  mFvbModuleGlobal.NumFv   = 0;
10493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  for (Idx = 0; Idx < 1; Idx++) {
10513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    BaseAddress = mPlatformFvBaseAddress[Idx];
10523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
10533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (!IsFvHeaderValid (BaseAddress, FwVolHeader)) {
10553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      FvHeaderValid = FALSE;
10563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
10573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // If not valid, get FvbInfo from the information carried in
10583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // FVB driver.
10593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
10603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      DEBUG ((EFI_D_ERROR, "Fvb: FV header @ 0x%lx invalid\n", BaseAddress));
10613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status          = GetFvbInfo (BaseAddress, &FwVolHeader);
10623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      ASSERT_EFI_ERROR(Status);
10633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
10643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //  Write back a healthy FV header.
10653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
10663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      DEBUG ((EFI_D_ERROR, "FwBlockService.c: Writing back healthy FV header\n"));
10673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length, FALSE);
10683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status = LibFvbFlashDeviceBlockErase ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length);
10703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      TmpHeaderLength = (UINTN) FwVolHeader->HeaderLength;
10723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status = LibFvbFlashDeviceWrite (
10733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                 (UINTN)BaseAddress,
10743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                 &TmpHeaderLength,
10753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                 (UINT8 *) FwVolHeader
10763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                 );
10773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      LibFvbFlashDeviceBlockLock ((UINTN)BaseAddress, FwVolHeader->BlockMap->Length, TRUE);
10793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      WriteBackInvalidateDataCacheRange (
10813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (VOID *) (UINTN) BaseAddress,
10823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        FwVolHeader->BlockMap->Length
10833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        );
10843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
10863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength);
10883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FwVolHeader = &(FwhInstance->VolumeHeader);
10903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FwhInstance->FvBase = (UINTN)BaseAddress;
10913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
10923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
10933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Process the block map for each FV.
10943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
10953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FwhInstance->NumOfBlocks = 0;
10963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
10973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
10983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // Get the maximum size of a block.
10993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
11003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (MaxLbaSize < PtrBlockMapEntry->Length) {
11013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        MaxLbaSize  = PtrBlockMapEntry->Length;
11023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
11033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks;
11043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
11053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
11063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
11073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Add a FVB Protocol Instance.
11083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
11093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    mFvbModuleGlobal.NumFv++;
11103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1);
11113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
11123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
11133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Move on to the next FwhInstance.
11143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1115    FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) +
1116                                          FwVolHeader->HeaderLength +
1117                                          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));
1118
1119  }
1120
1121  return EFI_SUCCESS;
1122}
1123
1124