13cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/** @file
23cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
33cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Implement the Firmware Volume Block (FVB) services based on SMM FVB
43cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  module and install FVB protocol.
53cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
63cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiCopyright (c) 2010  - 2014, Intel Corporation. All rights reserved. <BR>
73cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
83cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
93cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This program and the accompanying materials are licensed and made available under
103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  the terms and conditions of the BSD License that accompanies this distribution.
123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The full text of the license may be found at
143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  http://opensource.org/licenses/bsd-license.php.
163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "FvbSmmDxe.h"
293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
303cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_HANDLE                       mHandle           = NULL;
313cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_SMM_COMMUNICATION_PROTOCOL  *mSmmCommunication = NULL;
323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// Template structure used when installing FVB protocol.
353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei//
363cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_FVB_DEVICE    mFvbDeviceTemplate = {
373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FVB_DEVICE_SIGNATURE,
383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  NULL,
393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbGetAttributes,
413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbSetAttributes,
423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbGetPhysicalAddress,
433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbGetBlockSize,
443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbRead,
453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbWrite,
463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbEraseBlocks,
473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NULL
483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  },
493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  NULL
503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei};
513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
523cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {
533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      HARDWARE_DEVICE_PATH,
563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      HW_MEMMAP_DP,
573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      {
583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    },
623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    EfiMemoryMappedIO,
633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    (EFI_PHYSICAL_ADDRESS) 0,
643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    (EFI_PHYSICAL_ADDRESS) 0,
653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  },
663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_DEVICE_PATH_TYPE,
683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_ENTIRE_DEVICE_PATH_SUBTYPE,
693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      END_DEVICE_PATH_LENGTH,
713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      0
723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei};
753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
763cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {
773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MEDIA_DEVICE_PATH,
803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MEDIA_PIWG_FW_VOL_DP,
813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      {
823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    },
863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    { 0 }
873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  },
883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  {
893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_DEVICE_PATH_TYPE,
903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    END_ENTIRE_DEVICE_PATH_SUBTYPE,
913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    {
923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      END_DEVICE_PATH_LENGTH,
933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      0
943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei};
973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Initialize the communicate buffer using DataSize and Function.
1003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
1023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DataSize.
1033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out]      CommunicateBuffer The communicate buffer. Caller should free it after use.
1053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out]      DataPtr           Points to the data in the communicate buffer. Caller should not free it.
1063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]       DataSize          The payload size.
1073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]       Function          The function number used to initialize the communicate header.
1083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_INVALID_PARAMETER      The data size is too big.
1103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS                Find the specified variable.
1113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
1133cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
1143cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiInitCommunicateBuffer (
1153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT     VOID                              **CommunicateBuffer,
1163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT     VOID                              **DataPtr,
1173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN      UINTN                             DataSize,
1183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN      UINTN                             Function
1193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
1203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
1213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;
1223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_COMMUNICATE_FUNCTION_HEADER       *SmmFvbFunctionHeader;
1233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
1253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // The whole buffer size: SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE + DataSize.
1263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
1273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmCommunicateHeader = AllocatePool (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE);
1283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT (SmmCommunicateHeader != NULL);
1293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
1313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Prepare data buffer.
1323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
1333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmFirmwareVolumeBlockProtocolGuid);
1343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmCommunicateHeader->MessageLength = DataSize + SMM_FVB_COMMUNICATE_HEADER_SIZE;
1353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbFunctionHeader = (SMM_FVB_COMMUNICATE_FUNCTION_HEADER *) SmmCommunicateHeader->Data;
1373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbFunctionHeader->Function = Function;
1383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *CommunicateBuffer = SmmCommunicateHeader;
1403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *DataPtr = SmmFvbFunctionHeader->Data;
1413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
1433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
1443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
1473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Send the data in communicate buffer to SMM.
1483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out]      SmmCommunicateHeader    The communicate buffer.
1503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]       DataSize                The payload size.
1513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
1533cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
1543cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSendCommunicateBuffer (
1553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN      EFI_SMM_COMMUNICATE_HEADER        *SmmCommunicateHeader,
1563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN      UINTN                             DataSize
1573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
1583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
1593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                Status;
1603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                     CommSize;
1613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_COMMUNICATE_FUNCTION_HEADER       *SmmFvbFunctionHeader;
1623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE;
1643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = mSmmCommunication->Communicate (
1653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                mSmmCommunication,
1663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                SmmCommunicateHeader,
1673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                &CommSize
1683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                );
1693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (Status);
1703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbFunctionHeader = (SMM_FVB_COMMUNICATE_FUNCTION_HEADER *) SmmCommunicateHeader->Data;
1723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return  SmmFvbFunctionHeader->ReturnStatus;
1733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
1743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
1763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This function retrieves the attributes and current settings of the block.
1773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  This       Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
1793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes
1813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                         and current settings are returned. Type EFI_FVB_ATTRIBUTES_2
1823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                         is defined in EFI_FIRMWARE_VOLUME_HEADER.
1833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS              The firmware volume attributes were returned.
1853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_INVALID_PARAMETER    Attributes is NULL.
1863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
1873cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
1883cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
1893cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbGetAttributes (
1903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
1913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei     OUT   EFI_FVB_ATTRIBUTES_2                 *Attributes
1923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
1933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
1943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                    Status;
1953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                         PayloadSize;
1963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                    *SmmCommunicateHeader;
1973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_ATTRIBUTES_HEADER                     *SmmFvbAttributesHeader;
1983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL        *SmmFvb;
1993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                                *FvbDevice;
2003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (Attributes == NULL) {
2023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
2033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
2063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvb    = FvbDevice->SmmFvbInstance;
2073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Initialize the communicate buffer.
2103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PayloadSize  = sizeof (SMM_FVB_ATTRIBUTES_HEADER);
2123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = InitCommunicateBuffer (
2133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmCommunicateHeader,
2143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmFvbAttributesHeader,
2153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             PayloadSize,
2163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             EFI_FUNCTION_GET_ATTRIBUTES
2173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
2183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
2193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
2203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbAttributesHeader->SmmFvb     = SmmFvb;
2233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbAttributesHeader->Attributes = 0;
2243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Send data to SMM.
2273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
2293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get data from SMM.
2323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *Attributes = SmmFvbAttributesHeader->Attributes;
2343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (SmmCommunicateHeader);
2353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
2373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
2383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
2413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Sets Volume attributes. No polarity translations are done.
2423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  This        Calling context.
2443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] Attributes  Output buffer which contains attributes.
2453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS              Set the Attributes successfully.
2473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_INVALID_PARAMETER    Attributes is NULL.
2483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
2503cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
2513cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
2523cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbSetAttributes (
2533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
2543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT   EFI_FVB_ATTRIBUTES_2                 *Attributes
2553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
2563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
2573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                    Status;
2583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                         PayloadSize;
2593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                    *SmmCommunicateHeader;
2603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_ATTRIBUTES_HEADER                     *SmmFvbAttributesHeader;
2613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL        *SmmFvb;
2623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                                *FvbDevice;
2633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (Attributes == NULL) {
2653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
2663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
2693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvb    = FvbDevice->SmmFvbInstance;
2703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Initialize the communicate buffer.
2733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PayloadSize  = sizeof (SMM_FVB_ATTRIBUTES_HEADER);
2753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = InitCommunicateBuffer (
2763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmCommunicateHeader,
2773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmFvbAttributesHeader,
2783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             PayloadSize,
2793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             EFI_FUNCTION_SET_ATTRIBUTES
2803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
2813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
2823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
2833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbAttributesHeader->SmmFvb     = SmmFvb;
2863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbAttributesHeader->Attributes = *Attributes;
2873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Send data to SMM.
2903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
2923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get data from SMM.
2953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *Attributes = SmmFvbAttributesHeader->Attributes;
2973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (SmmCommunicateHeader);
2983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
3003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
3013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
3043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Retrieves the physical address of the FVB instance.
3053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  SmmFvb         A pointer to EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
3073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] Address        Output buffer containing the address.
3083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS    Get the address successfully.
3103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     Others         Failed to get address.
3113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
3133cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
3143cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiGetPhysicalAddress (
3153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN   EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *SmmFvb,
3163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  OUT  EFI_PHYSICAL_ADDRESS                    *Address
3173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
3183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
3193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                   Status;
3203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                        PayloadSize;
3213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                   *SmmCommunicateHeader;
3223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_PHYSICAL_ADDRESS_HEADER              *SmmFvbPhysicalAddressHeader;
3233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Initialize the communicate buffer.
3263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PayloadSize  = sizeof (SMM_FVB_PHYSICAL_ADDRESS_HEADER);
3283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = InitCommunicateBuffer (
3293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmCommunicateHeader,
3303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmFvbPhysicalAddressHeader,
3313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             PayloadSize,
3323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             EFI_FUNCTION_GET_PHYSICAL_ADDRESS
3333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
3343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
3353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
3363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbPhysicalAddressHeader->SmmFvb  = SmmFvb;
3393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbPhysicalAddressHeader->Address = 0;
3403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Send data to SMM.
3433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
3453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get data from SMM.
3483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *Address = SmmFvbPhysicalAddressHeader->Address;
3503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (SmmCommunicateHeader);
3513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
3533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
3543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
3573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Retrieves the physical address of the FVB instance.
3583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  This                     A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
3603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] Address                  Output buffer containing the address.
3613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS              Get the address successfully.
3633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     Others                   Failed to get the address.
3643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
3663cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
3673cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
3683cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbGetPhysicalAddress (
3693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
3703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei     OUT   EFI_PHYSICAL_ADDRESS                *Address
3713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
3723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
3733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                   Status;
3743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *SmmFvb;
3753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                               *FvbDevice;
3763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (Address == NULL) {
3783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
3793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
3823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvb    = FvbDevice->SmmFvbInstance;
3833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = GetPhysicalAddress (SmmFvb, Address);
3853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
3873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
3883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
3913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Retrieve the size of a logical block.
3923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  This        Calling context.
3943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  Lba         Indicates which block to return the size for.
3953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] BlockSize   A pointer to a caller allocated UINTN in which
3963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                          the size of the block is returned.
3973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the
3983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                          number of consecutive blocks starting with Lba is
3993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                          returned. All blocks in this range have a size of
4003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                          BlockSize.
4013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS              Get BlockSize and NumOfBlocks successfully.
4033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_INVALID_PARAMETER    BlockSize or NumOfBlocks are NULL.
4043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
4053cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
4063cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
4073cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbGetBlockSize (
4083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
4093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       EFI_LBA                             Lba,
4103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei     OUT   UINTN                               *BlockSize,
4113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei     OUT   UINTN                               *NumOfBlocks
4123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
4133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
4143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                   Status;
4153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                        PayloadSize;
4163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                   *SmmCommunicateHeader;
4173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_BLOCK_SIZE_HEADER                    *SmmFvbBlockSizeHeader;
4183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *SmmFvb;
4193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                               *FvbDevice;
4203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((BlockSize == NULL) || (NumOfBlocks == NULL)) {
4223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
4233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
4263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvb    = FvbDevice->SmmFvbInstance;
4273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Initialize the communicate buffer.
4303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PayloadSize  = sizeof (SMM_FVB_BLOCK_SIZE_HEADER);
4323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = InitCommunicateBuffer (
4333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmCommunicateHeader,
4343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmFvbBlockSizeHeader,
4353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             PayloadSize,
4363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             EFI_FUNCTION_GET_BLOCK_SIZE
4373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
4383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
4393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
4403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbBlockSizeHeader->SmmFvb = SmmFvb;
4433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbBlockSizeHeader->Lba    = Lba;
4443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Send data to SMM.
4473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
4493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get data from SMM.
4523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
4533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *BlockSize   = SmmFvbBlockSizeHeader->BlockSize;
4543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *NumOfBlocks = SmmFvbBlockSizeHeader->NumOfBlocks;
4553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (SmmCommunicateHeader);
4563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
4583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
4593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
4623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Reads data beginning at Lba:Offset from FV. The Read terminates either
4633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  when *NumBytes of data have been read, or when a block boundary is
4643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  reached.  *NumBytes is updated to reflect the actual number of bytes
4653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  written. The write opertion does not include erase. This routine will
4663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  attempt to write only the specified bytes. If the writes do not stick,
4673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  it will return an error.
4683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      This           Calling context
4703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Lba            Block in which to begin write
4713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Offset         Offset in the block at which to begin write
4723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in,out]  NumBytes       On input, indicates the requested write size. On
4733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 output, indicates the actual number of bytes written
4743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Buffer         Buffer containing source data for the write.
4753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS            The firmware volume was read successfully and
4773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 contents are in Buffer.
4783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_BAD_BUFFER_SIZE    Read attempted across a LBA boundary. On output,
4793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 NumBytes contains the total number of bytes returned
4803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 in Buffer.
4813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_ACCESS_DENIED      The firmware volume is in the ReadDisabled state
4823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly and
4833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 could not be read.
4843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_INVALID_PARAMETER  NumBytes or Buffer are NULL.
4853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
4873cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
4883cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
4893cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbRead (
4903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
4913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       EFI_LBA                              Lba,
4923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       UINTN                                Offset,
4933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT   UINTN                                *NumBytes,
4943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei     OUT   UINT8                                *Buffer
4953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
4963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
4973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                    Status;
4983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                         PayloadSize;
4993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                    *SmmCommunicateHeader;
5003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_READ_WRITE_HEADER                     *SmmFvbReadWriteHeader;
5013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL        *SmmFvb;
5023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                                *FvbDevice;
5033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((NumBytes == NULL) || (Buffer == NULL)) {
5053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
5063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
5093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvb    = FvbDevice->SmmFvbInstance;
5103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Initialize the communicate buffer.
5133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PayloadSize  = sizeof (SMM_FVB_READ_WRITE_HEADER) + *NumBytes;
5153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = InitCommunicateBuffer (
5163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmCommunicateHeader,
5173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmFvbReadWriteHeader,
5183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             PayloadSize, EFI_FUNCTION_READ
5193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
5203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
5213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
5223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->SmmFvb   = SmmFvb;
5253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->Lba      = Lba;
5263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->Offset   = Offset;
5273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->NumBytes = *NumBytes;
5283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Send data to SMM.
5313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
5333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get data from SMM.
5363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *NumBytes = SmmFvbReadWriteHeader->NumBytes;
5383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (!EFI_ERROR (Status)) {
5393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    CopyMem (Buffer, (UINT8 *)(SmmFvbReadWriteHeader + 1), *NumBytes);
5403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (SmmCommunicateHeader);
5423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
5443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
5453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
5483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Writes data beginning at Lba:Offset from FV. The write terminates either
5493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  when *NumBytes of data have been written, or when a block boundary is
5503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  reached.  *NumBytes is updated to reflect the actual number of bytes
5513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  written. The write opertion does not include erase. This routine will
5523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  attempt to write only the specified bytes. If the writes do not stick,
5533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  it will return an error.
5543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      This           Calling context.
5563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Lba            Block in which to begin write.
5573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Offset         Offset in the block at which to begin write.
5583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in,out]  NumBytes       On input, indicates the requested write size. On
5593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 output, indicates the actual number of bytes written.
5603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]      Buffer         Buffer containing source data for the write.
5613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS            The firmware volume was written successfully.
5633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_BAD_BUFFER_SIZE    Write attempted across a LBA boundary. On output,
5643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 NumBytes contains the total number of bytes
5653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 actually written.
5663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled state.
5673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly and
5683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 could not be written.
5693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_INVALID_PARAMETER  NumBytes or Buffer are NULL.
5703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
5723cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
5733cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
5743cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbWrite (
5753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
5763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       EFI_LBA                              Lba,
5773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       UINTN                                Offset,
5783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN OUT   UINTN                                *NumBytes,
5793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       UINT8                                *Buffer
5803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
5813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
5823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                    Status;
5833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                         PayloadSize;
5843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                    *SmmCommunicateHeader;
5853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_READ_WRITE_HEADER                     *SmmFvbReadWriteHeader;
5863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL        *SmmFvb;
5873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                                *FvbDevice;
5883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((NumBytes == NULL) || (Buffer == NULL)) {
5903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
5913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
5923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
5943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvb    = FvbDevice->SmmFvbInstance;
5953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
5963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Initialize the communicate buffer.
5983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
5993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PayloadSize  = sizeof (SMM_FVB_READ_WRITE_HEADER) + *NumBytes;
6003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = InitCommunicateBuffer (
6013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmCommunicateHeader,
6023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmFvbReadWriteHeader,
6033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             PayloadSize,
6043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             EFI_FUNCTION_WRITE
6053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
6063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
6073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
6083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
6093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->SmmFvb   = SmmFvb;
6113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->Lba      = Lba;
6123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->Offset   = Offset;
6133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbReadWriteHeader->NumBytes = *NumBytes;
6143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  CopyMem ((UINT8 *)(SmmFvbReadWriteHeader + 1), Buffer, *NumBytes);
6153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Send data to SMM.
6183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
6203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get data from SMM.
6233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  *NumBytes = SmmFvbReadWriteHeader->NumBytes;
6253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (SmmCommunicateHeader);
6263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
6283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
6293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
6323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The EraseBlock() function erases NumOfLba blocks started from StartingLba.
6333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] This            Calling context.
6353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] StartingLba     Starting LBA followed to erase.
6363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] NumOfLba        Number of block to erase.
6373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS        The erase request was successfully completed.
6393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_ACCESS_DENIED  The firmware volume is in the WriteDisabled state.
6403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_DEVICE_ERROR   The block device is not functioning correctly and
6413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                             could not be written. Firmware device may have been
6423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                             partially erased.
6433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
6453cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
6463cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEraseBlock (
6473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,
6483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       EFI_LBA                               StartingLba,
6493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN       UINTN                                 NumOfLba
6503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
6513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
6523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                     Status;
6533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                          PayloadSize;
6543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_COMMUNICATE_HEADER                    *SmmCommunicateHeader;
6553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM_FVB_BLOCKS_HEADER                         *SmmFvbBlocksHeader;
6563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL        *SmmFvb;
6573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                                *FvbDevice;
6583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = FVB_DEVICE_FROM_THIS (This);
6603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvb    = FvbDevice->SmmFvbInstance;
6613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Initialize the communicate buffer.
6643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PayloadSize  = sizeof (SMM_FVB_BLOCKS_HEADER);
6663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = InitCommunicateBuffer (
6673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmCommunicateHeader,
6683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             (VOID **)&SmmFvbBlocksHeader,
6693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             PayloadSize,
6703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             EFI_FUNCTION_ERASE_BLOCKS
6713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
6723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
6733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
6743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
6753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbBlocksHeader->SmmFvb   = SmmFvb;
6773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbBlocksHeader->StartLba = StartingLba;
6783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SmmFvbBlocksHeader->NumOfLba = NumOfLba;
6793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Send data to SMM.
6823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
6843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get data from SMM.
6873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
6883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (SmmCommunicateHeader);
6893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
6913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
6923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
6943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
6953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The EraseBlocks() function erases one or more blocks as denoted by the
6963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  variable argument list. The entire parameter list of blocks must be verified
6973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  prior to erasing any blocks.  If a block is requested that does not exist
6983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  within the associated firmware volume (it has a larger index than the last
6993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  block of the firmware volume), the EraseBlock() function must return
7003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
7013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] This           Calling context/
7033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] ...            Starting LBA followed by Number of Lba to erase.
7043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                            a -1 to terminate the list.
7053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/
7063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS       The erase request was successfully completed
7073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state/
7083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_DEVICE_ERROR  The block device is not functioning correctly and
7093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                            could not be written. Firmware device may have been
7103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                            partially erased/
7113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
7133cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
7143cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
7153cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbEraseBlocks (
7163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,
7173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ...
7183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
7193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
7203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                     Status;
7213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_LIST                                        Marker;
7223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_LBA                                        StartingLba;
7233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                          NumOfLba;
7243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = EFI_SUCCESS;
7263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
7283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Check the parameter.
7293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
7303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_START (Marker, This);
7313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  do {
7323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    StartingLba = VA_ARG (Marker, EFI_LBA);
7333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (StartingLba == EFI_LBA_LIST_TERMINATOR ) {
7343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      break;
7353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
7363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NumOfLba = VA_ARG (Marker, UINT32);
7383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (NumOfLba == 0) {
7393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_INVALID_PARAMETER;
7403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
7413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } while ( 1 );
7433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_END (Marker);
7443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
7463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Erase the blocks.
7473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
7483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_START (Marker, This);
7493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  do {
7503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    StartingLba = VA_ARG (Marker, EFI_LBA);
7513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (StartingLba == EFI_LBA_LIST_TERMINATOR ) {
7523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      break;
7533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
7543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    NumOfLba = VA_ARG (Marker, UINT32);
7553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = EraseBlock (This, StartingLba, NumOfLba);
7563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (EFI_ERROR (Status)) {
7573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      break;
7583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
7593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } while ( 1 );
7603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VA_END (Marker);
7613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
7633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
7643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
7673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Install the FVB protocol which based on SMM FVB protocol.
7683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] SmmFvb        The SMM FVB protocol.
7703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
7723cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiVOID
7733cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiInstallFvb (
7743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN    EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *SmmFvb
7753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
7763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
7773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                    Status;
7783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE                                    FvbHandle;
7793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FVB_DEVICE                                *FvbDevice;
7803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FIRMWARE_VOLUME_HEADER                    *VolumeHeader;
7813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_PHYSICAL_ADDRESS                          Address;
7823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL            *OldFvbInterface;
7833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice = AllocateRuntimeCopyPool (sizeof (EFI_FVB_DEVICE), &mFvbDeviceTemplate);
7853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT (FvbDevice != NULL);
7863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FvbDevice->SmmFvbInstance = SmmFvb;
7873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = gBS->LocateProtocol (
7893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &gEfiSmmCommunicationProtocolGuid,
7903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
7913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  (VOID **) &mSmmCommunication
7923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  );
7933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (Status);
7943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = GetPhysicalAddress (SmmFvb, &Address);
7963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (Status);
7973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
7983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN)Address;
7993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
8013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Set up the devicepath.
8023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
8033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (VolumeHeader->ExtHeaderOffset == 0) {
8043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH.
8063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);
8083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = (UINTN)Address;
8093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress   = (UINTN)Address + VolumeHeader->FvLength - 1;
8103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } else {
8113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);
8123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    CopyGuid (
8133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName,
8143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      (GUID *)(UINTN)((UINTN)Address + VolumeHeader->ExtHeaderOffset)
8153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      );
8163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
8173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
8193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Find a handle with a matching device path that has supports FW Block protocol.
8203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
8213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = gBS->LocateDevicePath (
8223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &gEfiFirmwareVolumeBlockProtocolGuid,
8233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &FvbDevice->DevicePath,
8243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &FvbHandle
8253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  );
8263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status) ) {
8273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // LocateDevicePath fails so install a new interface and device path.
8293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FvbHandle = NULL;
8313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status =  gBS->InstallMultipleProtocolInterfaces (
8323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     &FvbHandle,
8333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     &gEfiFirmwareVolumeBlockProtocolGuid,
8343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     &FvbDevice->FvbInstance,
8353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     &gEfiDevicePathProtocolGuid,
8363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     FvbDevice->DevicePath,
8373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     NULL
8383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     );
8393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ASSERT_EFI_ERROR (Status);
8403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {
8413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Device allready exists, so reinstall the FVB protocol.
8433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = gBS->HandleProtocol (
8453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    FvbHandle,
8463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    &gEfiFirmwareVolumeBlockProtocolGuid,
8473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    (VOID **) &OldFvbInterface
8483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    );
8493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ASSERT_EFI_ERROR (Status);
8503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status =  gBS->ReinstallProtocolInterface (
8523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     FvbHandle,
8533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     &gEfiFirmwareVolumeBlockProtocolGuid,
8543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     OldFvbInterface,
8553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     &FvbDevice->FvbInstance
8563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                     );
8573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ASSERT_EFI_ERROR (Status);
8583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } else {
8593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // There was a FVB protocol on an End Device Path node.
8613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
8623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ASSERT (FALSE);
8633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
8643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
8653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
8683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SMM Firmware Volume Block Protocol notification event handler.
8693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Discover NV Variable Store and install Variable Write Arch Protocol.
8713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] Event    Event whose notification function is being invoked.
8733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in] Context  Pointer to the notification function's context.
8743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
8753cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiVOID
8763cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
8773cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSmmFvbReady (
8783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN  EFI_EVENT                                 Event,
8793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN  VOID                                      *Context
8803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
8813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
8823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                                    Status;
8833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE                                    *HandleBuffer;
8843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                         HandleCount;
8853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                         Index;
8863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL        *SmmFvb;
8873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
8883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
8893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Locate all handles of Smm Fvb protocol.
8903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
8913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = gBS->LocateHandleBuffer (
8923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  ByProtocol,
8933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &gEfiSmmFirmwareVolumeBlockProtocolGuid,
8943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
8953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleCount,
8963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleBuffer
8973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  );
8983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
8993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return ;
9003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
9013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
9033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Install FVB protocol.
9043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
9053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  for (Index = 0; Index < HandleCount; Index++) {
9063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    SmmFvb = NULL;
9073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = gBS->HandleProtocol (
9083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    HandleBuffer[Index],
9093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
9103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    (VOID **) &SmmFvb
9113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                    );
9123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (EFI_ERROR (Status)) {
9133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      break;
9143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
9153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    InstallFvb (SmmFvb);
9173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
9183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  FreePool (HandleBuffer);
9203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
9213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
9243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The driver entry point for Firmware Volume Block Driver.
9253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  The function does the necessary initialization work
9273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Firmware Volume Block Driver.
9283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
9303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param[in]  SystemTable       A pointer to the EFI system table.
9313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval     EFI_SUCCESS       This funtion always return EFI_SUCCESS.
9333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                It will ASSERT on errors.
9343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
9363cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
9373cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
9383cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiFvbSmmDxeInitialize (
9393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_HANDLE                                 ImageHandle,
9403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_SYSTEM_TABLE                           *SystemTable
9413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
9423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
9433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID                                          *SmmFvbRegistration;
9443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
9453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
9463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Smm FVB driver is ready.
9473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
9483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EfiCreateProtocolNotifyEvent (
9493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    &gEfiSmmFirmwareVolumeBlockProtocolGuid,
950    TPL_CALLBACK,
951    SmmFvbReady,
952    NULL,
953    &SmmFvbRegistration
954    );
955
956  return EFI_SUCCESS;
957}
958
959