hikey: Add UEFI sources for reference

UEFI needs to be built outside Android build system.
Please follow the instructions in README.

The sources correspond to:
https://github.com/96boards/edk2/commit/14eae0c12e71fd33c4c0fc51e4475e8db02566cf
https://github.com/96boards/arm-trusted-firmware/commit/e9b4909dcd75fc4ae7041cfb83d28ab9adb7afdf
https://github.com/96boards/l-loader/commit/6b784ad5c4ab00e2b1c6f53cd5f74054e5d00a78
https://git.linaro.org/uefi/uefi-tools.git/commit/abe618f8ab72034fff1ce46c9c006a2c6bd40a7e

Change-Id: Ieeefdb63e673e0c8e64e0a1f02c7bddc63b2c7fb
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
diff --git a/uefi/linaro-edk2/OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.c b/uefi/linaro-edk2/OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.c
new file mode 100644
index 0000000..7a8beb3
--- /dev/null
+++ b/uefi/linaro-edk2/OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.c
@@ -0,0 +1,917 @@
+/** @file

+  Firmware Block Services to support emulating non-volatile variables

+  by pretending that a memory buffer is storage for the NV variables.

+

+  Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "PiDxe.h"

+#include <Guid/EventGroup.h>

+#include <Guid/SystemNvDataGuid.h>

+#include <Guid/VariableFormat.h>

+

+#include <Protocol/FirmwareVolumeBlock.h>

+#include <Protocol/DevicePath.h>

+

+#include <Library/UefiLib.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/BaseLib.h>

+#include <Library/UefiRuntimeLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/PcdLib.h>

+#include <Library/PlatformFvbLib.h>

+#include "Fvb.h"

+

+#define EFI_AUTHENTICATED_VARIABLE_GUID \

+{ 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }

+

+//

+// Virtual Address Change Event

+//

+// This is needed for runtime variable access.

+//

+EFI_EVENT   mEmuVarsFvbAddrChangeEvent = NULL;

+

+//

+// This is the single instance supported by this driver.  It

+// supports the FVB and Device Path protocols.

+//

+EFI_FW_VOL_BLOCK_DEVICE mEmuVarsFvb = {

+  FVB_DEVICE_SIGNATURE,

+  {     // DevicePath

+    {

+      {

+        HARDWARE_DEVICE_PATH,

+        HW_MEMMAP_DP,

+        {

+          sizeof (MEMMAP_DEVICE_PATH),

+          0

+        }

+      },

+      EfiMemoryMappedIO,

+      0,

+      0,

+    },

+    {

+      END_DEVICE_PATH_TYPE,

+      END_ENTIRE_DEVICE_PATH_SUBTYPE,

+      {

+        sizeof (EFI_DEVICE_PATH_PROTOCOL),

+        0

+      }

+    }

+  },

+  NULL, // BufferPtr

+  FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize), // BlockSize

+  2 * FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize), // Size

+  {     // FwVolBlockInstance

+    FvbProtocolGetAttributes,

+    FvbProtocolSetAttributes,

+    FvbProtocolGetPhysicalAddress,

+    FvbProtocolGetBlockSize,

+    FvbProtocolRead,

+    FvbProtocolWrite,

+    FvbProtocolEraseBlocks,

+    NULL

+  },

+};

+

+

+/**

+  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.

+

+  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.

+  It converts pointer to new virtual address.

+

+  @param  Event        Event whose notification function is being invoked.

+  @param  Context      Pointer to the notification function's context.

+

+**/

+VOID

+EFIAPI

+FvbVirtualAddressChangeEvent (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  )

+{

+  EfiConvertPointer (0x0, &mEmuVarsFvb.BufferPtr);

+}

+

+

+//

+// FVB protocol APIs

+//

+

+/**

+  The GetPhysicalAddress() function retrieves the base address of

+  a memory-mapped firmware volume. This function should be called

+  only for memory-mapped firmware volumes.

+

+  @param This     Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.

+  

+  @param Address  Pointer to a caller-allocated

+                  EFI_PHYSICAL_ADDRESS that, on successful

+                  return from GetPhysicalAddress(), contains the

+                  base address of the firmware volume.

+  

+  @retval EFI_SUCCESS       The firmware volume base address is returned.

+  

+  @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolGetPhysicalAddress (

+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,

+  OUT       EFI_PHYSICAL_ADDRESS                *Address

+  )

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  *Address = (EFI_PHYSICAL_ADDRESS)(UINTN) FvbDevice->BufferPtr;

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  The GetBlockSize() function retrieves the size of the requested

+  block. It also returns the number of additional blocks with

+  the identical size. The GetBlockSize() function is used to

+  retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).

+

+

+  @param This           Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.

+

+  @param Lba            Indicates the block for which to return the size.

+

+  @param BlockSize      Pointer to a caller-allocated UINTN in which

+                        the size of the block is returned.

+

+  @param NumberOfBlocks Pointer to a caller-allocated UINTN in

+                        which the number of consecutive blocks,

+                        starting with Lba, is returned. All

+                        blocks in this range have a size of

+                        BlockSize.

+

+  

+  @retval EFI_SUCCESS             The firmware volume base address is returned.

+  

+  @retval EFI_INVALID_PARAMETER   The requested LBA is out of range.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolGetBlockSize (

+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,

+  IN        EFI_LBA                             Lba,

+  OUT       UINTN                               *BlockSize,

+  OUT       UINTN                               *NumberOfBlocks

+  )

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  if (Lba > 1) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  *BlockSize = FvbDevice->BlockSize;

+  *NumberOfBlocks = (UINTN) (2 - (UINTN) Lba);

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  The GetAttributes() function retrieves the attributes and

+  current settings of the block. Status Codes Returned

+

+  @param This       Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.

+

+  @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the

+                    attributes and current settings are

+                    returned. Type EFI_FVB_ATTRIBUTES_2 is defined

+                    in EFI_FIRMWARE_VOLUME_HEADER.

+

+  @retval EFI_SUCCESS The firmware volume attributes were

+                      returned.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolGetAttributes (

+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,

+  OUT       EFI_FVB_ATTRIBUTES_2                *Attributes

+  )

+{

+  *Attributes =

+    (EFI_FVB_ATTRIBUTES_2) (

+      EFI_FVB2_READ_ENABLED_CAP |

+      EFI_FVB2_READ_STATUS |

+      EFI_FVB2_WRITE_ENABLED_CAP |

+      EFI_FVB2_WRITE_STATUS |

+      EFI_FVB2_ERASE_POLARITY

+      );

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  The SetAttributes() function sets configurable firmware volume

+  attributes and returns the new settings of the firmware volume.

+

+  @param This         Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.

+

+  @param Attributes   On input, Attributes is a pointer to

+                      EFI_FVB_ATTRIBUTES_2 that contains the

+                      desired firmware volume settings. On

+                      successful return, it contains the new

+                      settings of the firmware volume. Type

+                      EFI_FVB_ATTRIBUTES_2 is defined in

+                      EFI_FIRMWARE_VOLUME_HEADER.

+  

+  @retval EFI_SUCCESS           The firmware volume attributes were returned.

+

+  @retval EFI_INVALID_PARAMETER The attributes requested are in

+                                conflict with the capabilities

+                                as declared in the firmware

+                                volume header.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolSetAttributes (

+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,

+  IN OUT    EFI_FVB_ATTRIBUTES_2                *Attributes

+  )

+{

+  return EFI_ACCESS_DENIED;

+}

+

+

+/**

+  Erases and initializes a firmware volume block.

+

+  The EraseBlocks() function erases one or more blocks as denoted

+  by the variable argument list. The entire parameter list of

+  blocks must be verified before erasing any blocks. If a block is

+  requested that does not exist within the associated firmware

+  volume (it has a larger index than the last block of the

+  firmware volume), the EraseBlocks() function must return the

+  status code EFI_INVALID_PARAMETER without modifying the contents

+  of the firmware volume. Implementations should be mindful that

+  the firmware volume might be in the WriteDisabled state. If it

+  is in this state, the EraseBlocks() function must return the

+  status code EFI_ACCESS_DENIED without modifying the contents of

+  the firmware volume. All calls to EraseBlocks() must be fully

+  flushed to the hardware before the EraseBlocks() service

+  returns.

+

+  @param This   Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL

+                instance.

+

+  @param ...    The variable argument list is a list of tuples.

+                Each tuple describes a range of LBAs to erase

+                and consists of the following:

+                - An EFI_LBA that indicates the starting LBA

+                - A UINTN that indicates the number of blocks to

+                  erase

+

+                The list is terminated with an

+                EFI_LBA_LIST_TERMINATOR. For example, the

+                following indicates that two ranges of blocks

+                (5-7 and 10-11) are to be erased: EraseBlocks

+                (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);

+

+  @retval EFI_SUCCESS The erase request was successfully

+                      completed.

+  

+  @retval EFI_ACCESS_DENIED   The firmware volume is in the

+                              WriteDisabled state.

+  @retval EFI_DEVICE_ERROR  The block device is not functioning

+                            correctly and could not be written.

+                            The firmware device may have been

+                            partially erased.

+  @retval EFI_INVALID_PARAMETER One or more of the LBAs listed

+                                in the variable argument list do

+                                not exist in the firmware volume.  

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolEraseBlocks (

+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,

+  ...

+  )

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+  VA_LIST                 args;

+  EFI_LBA                 StartingLba;

+  UINTN                   NumOfLba;

+  UINT8                   Erase;

+  VOID                    *ErasePtr;

+  UINTN                   EraseSize;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+  Erase = 0;

+

+  VA_START (args, This);

+

+  do {

+    StartingLba = VA_ARG (args, EFI_LBA);

+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {

+      break;

+    }

+

+    NumOfLba = VA_ARG (args, UINT32);

+

+    //

+    // Check input parameters

+    //

+    if ((NumOfLba == 0) || (StartingLba > 1) || ((StartingLba + NumOfLba) > 2)) {

+      VA_END (args);

+      return EFI_INVALID_PARAMETER;

+    }

+

+    if (StartingLba == 0) {

+      Erase = (UINT8) (Erase | BIT0);

+    }

+    if ((StartingLba + NumOfLba) == 2) {

+      Erase = (UINT8) (Erase | BIT1);

+    }

+

+  } while (1);

+

+  VA_END (args);

+

+  ErasePtr = (UINT8*) FvbDevice->BufferPtr;

+  EraseSize = 0;

+

+  if ((Erase & BIT0) != 0) {

+    EraseSize = EraseSize + FvbDevice->BlockSize;

+  } else {

+    ErasePtr = (VOID*) ((UINT8*)ErasePtr + FvbDevice->BlockSize);

+  }

+

+  if ((Erase & BIT1) != 0) {

+    EraseSize = EraseSize + FvbDevice->BlockSize;

+  }

+

+  if (EraseSize != 0) {

+    SetMem (

+      (VOID*) ErasePtr,

+      EraseSize,

+      ERASED_UINT8

+      );

+    VA_START (args, This);

+    PlatformFvbBlocksErased (This, args);

+    VA_END (args);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  Writes the specified number of bytes from the input buffer to the block.

+

+  The Write() function writes the specified number of bytes from

+  the provided buffer to the specified block and offset. If the

+  firmware volume is sticky write, the caller must ensure that

+  all the bits of the specified range to write are in the

+  EFI_FVB_ERASE_POLARITY state before calling the Write()

+  function, or else the result will be unpredictable. This

+  unpredictability arises because, for a sticky-write firmware

+  volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY

+  state but cannot flip it back again. In general, before

+  calling the Write() function, the caller should call the

+  EraseBlocks() function first to erase the specified block to

+  write. A block erase cycle will transition bits from the

+  (NOT)EFI_FVB_ERASE_POLARITY state back to the

+  EFI_FVB_ERASE_POLARITY state. Implementations should be

+  mindful that the firmware volume might be in the WriteDisabled

+  state. If it is in this state, the Write() function must

+  return the status code EFI_ACCESS_DENIED without modifying the

+  contents of the firmware volume. The Write() function must

+  also prevent spanning block boundaries. If a write is

+  requested that spans a block boundary, the write must store up

+  to the boundary but not beyond. The output parameter NumBytes

+  must be set to correctly indicate the number of bytes actually

+  written. The caller must be aware that a write may be

+  partially completed. All writes, partial or otherwise, must be

+  fully flushed to the hardware before the Write() service

+  returns.

+

+  @param This     Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.

+  

+  @param Lba      The starting logical block index to write to.

+  

+  @param Offset   Offset into the block at which to begin writing.

+  

+  @param NumBytes Pointer to a UINTN. At entry, *NumBytes

+                  contains the total size of the buffer. At

+                  exit, *NumBytes contains the total number of

+                  bytes actually written.

+  

+  @param Buffer   Pointer to a caller-allocated buffer that

+                  contains the source for the write.

+  

+  @retval EFI_SUCCESS         The firmware volume was written successfully.

+  

+  @retval EFI_BAD_BUFFER_SIZE The write was attempted across an

+                              LBA boundary. On output, NumBytes

+                              contains the total number of bytes

+                              actually written.

+  

+  @retval EFI_ACCESS_DENIED   The firmware volume is in the

+                              WriteDisabled state.

+  

+  @retval EFI_DEVICE_ERROR    The block device is malfunctioning

+                              and could not be written.

+

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolWrite (

+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,

+  IN        EFI_LBA                             Lba,

+  IN        UINTN                               Offset,

+  IN OUT    UINTN                               *NumBytes,

+  IN        UINT8                               *Buffer

+  )

+{

+

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+  UINT8                   *FvbDataPtr;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  if ((Lba > 1) || (Offset > FvbDevice->BlockSize)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((Offset + *NumBytes) > FvbDevice->BlockSize) {

+    *NumBytes = FvbDevice->BlockSize - Offset;

+  }

+

+  FvbDataPtr =

+    (UINT8*) FvbDevice->BufferPtr +

+    MultU64x32 (Lba, (UINT32) FvbDevice->BlockSize) +

+    Offset;

+

+  if (*NumBytes > 0) {

+    CopyMem (FvbDataPtr, Buffer, *NumBytes);

+    PlatformFvbDataWritten (This, Lba, Offset, *NumBytes, Buffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  Reads the specified number of bytes into a buffer from the specified block.

+

+  The Read() function reads the requested number of bytes from the

+  requested block and stores them in the provided buffer.

+  Implementations should be mindful that the firmware volume

+  might be in the ReadDisabled state. If it is in this state,

+  the Read() function must return the status code

+  EFI_ACCESS_DENIED without modifying the contents of the

+  buffer. The Read() function must also prevent spanning block

+  boundaries. If a read is requested that would span a block

+  boundary, the read must read up to the boundary but not

+  beyond. The output parameter NumBytes must be set to correctly

+  indicate the number of bytes actually read. The caller must be

+  aware that a read may be partially completed.

+

+  @param This     Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.

+  

+  @param Lba      The starting logical block index

+                  from which to read.

+

+  @param Offset   Offset into the block at which to begin reading.

+

+  @param NumBytes Pointer to a UINTN. At entry, *NumBytes

+                  contains the total size of the buffer. At

+                  exit, *NumBytes contains the total number of

+                  bytes read.

+

+  @param Buffer   Pointer to a caller-allocated buffer that will

+                  be used to hold the data that is read.

+

+  @retval EFI_SUCCESS         The firmware volume was read successfully

+                              and contents are in Buffer.

+  

+  @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA

+                              boundary. On output, NumBytes

+                              contains the total number of bytes

+                              returned in Buffer.

+  

+  @retval EFI_ACCESS_DENIED   The firmware volume is in the

+                              ReadDisabled state.

+  

+  @retval EFI_DEVICE_ERROR    The block device is not

+                              functioning correctly and could

+                              not be read.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbProtocolRead (

+  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,

+  IN        EFI_LBA                             Lba,

+  IN        UINTN                               Offset,

+  IN OUT    UINTN                               *NumBytes,

+  IN OUT    UINT8                               *Buffer

+  )

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+  UINT8                   *FvbDataPtr;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  if ((Lba > 1) || (Offset > FvbDevice->BlockSize)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((Offset + *NumBytes) > FvbDevice->BlockSize) {

+    *NumBytes = FvbDevice->BlockSize - Offset;

+  }

+

+  FvbDataPtr =

+    (UINT8*) FvbDevice->BufferPtr +

+    MultU64x32 (Lba, (UINT32) FvbDevice->BlockSize) +

+    Offset;

+

+  if (*NumBytes > 0) {

+    CopyMem (Buffer, FvbDataPtr, *NumBytes);

+    PlatformFvbDataRead (This, Lba, Offset, *NumBytes, Buffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  Check the integrity of firmware volume header.

+

+  @param[in] FwVolHeader - A pointer to a firmware volume header

+

+  @retval  EFI_SUCCESS   - The firmware volume is consistent

+  @retval  EFI_NOT_FOUND - The firmware volume has been corrupted.

+

+**/

+EFI_STATUS

+ValidateFvHeader (

+  IN EFI_FIRMWARE_VOLUME_HEADER   *FwVolHeader

+  )

+{

+  UINT16  Checksum;

+

+  //

+  // Verify the header revision, header signature, length

+  // Length of FvBlock cannot be 2**64-1

+  // HeaderLength cannot be an odd number

+  //

+  if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||

+      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||

+      (FwVolHeader->FvLength != EMU_FVB_SIZE) ||

+      (FwVolHeader->HeaderLength != EMU_FV_HEADER_LENGTH)

+      ) {

+    DEBUG ((EFI_D_INFO, "EMU Variable FVB: Basic FV headers were invalid\n"));

+    return EFI_NOT_FOUND;

+  }

+  //

+  // Verify the header checksum

+  //

+  Checksum = CalculateSum16((VOID*) FwVolHeader, FwVolHeader->HeaderLength);

+

+  if (Checksum != 0) {

+    DEBUG ((EFI_D_INFO, "EMU Variable FVB: FV checksum was invalid\n"));

+    return EFI_NOT_FOUND;

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  Initializes the FV Header and Variable Store Header

+  to support variable operations.

+

+  @param[in]  Ptr - Location to initialize the headers

+

+**/

+VOID

+InitializeFvAndVariableStoreHeaders (

+  IN  VOID   *Ptr

+  )

+{

+  //

+  // Templates for standard (non-authenticated) variable FV header

+  //

+  STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndVarTemplate = {

+    { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;

+      // UINT8                     ZeroVector[16];

+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },

+

+      // EFI_GUID                  FileSystemGuid;

+      EFI_SYSTEM_NV_DATA_FV_GUID,

+

+      // UINT64                    FvLength;

+      EMU_FVB_SIZE,

+

+      // UINT32                    Signature;

+      EFI_FVH_SIGNATURE,

+

+      // EFI_FVB_ATTRIBUTES_2      Attributes;

+      0x4feff,

+

+      // UINT16                    HeaderLength;

+      EMU_FV_HEADER_LENGTH,

+

+      // UINT16                    Checksum;

+      0,

+

+      // UINT16                    ExtHeaderOffset;

+      0,

+

+      // UINT8                     Reserved[1];

+      {0},

+

+      // UINT8                     Revision;

+      EFI_FVH_REVISION,

+

+      // EFI_FV_BLOCK_MAP_ENTRY    BlockMap[1];

+      { 

+        {

+          2, // UINT32 NumBlocks;

+          EMU_FVB_BLOCK_SIZE  // UINT32 Length;

+        }

+      }

+    },

+    // EFI_FV_BLOCK_MAP_ENTRY     EndBlockMap;

+    { 0, 0 }, // End of block map

+    { // VARIABLE_STORE_HEADER      VarHdr;

+      // EFI_GUID  Signature;

+      EFI_VARIABLE_GUID,

+

+      // UINT32  Size;

+      (

+        FixedPcdGet32 (PcdVariableStoreSize) -

+        OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)

+      ),

+

+      // UINT8   Format;

+      VARIABLE_STORE_FORMATTED,

+

+      // UINT8   State;

+      VARIABLE_STORE_HEALTHY,

+

+      // UINT16  Reserved;

+      0,

+

+      // UINT32  Reserved1;

+      0

+    }

+  };

+

+  //

+  // Templates for authenticated variable FV header

+  //

+  STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate = {

+    { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;

+      // UINT8                     ZeroVector[16];

+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },

+

+      // EFI_GUID                  FileSystemGuid;

+      EFI_SYSTEM_NV_DATA_FV_GUID,

+

+      // UINT64                    FvLength;

+      EMU_FVB_SIZE,

+

+      // UINT32                    Signature;

+      EFI_FVH_SIGNATURE,

+

+      // EFI_FVB_ATTRIBUTES_2      Attributes;

+      0x4feff,

+

+      // UINT16                    HeaderLength;

+      EMU_FV_HEADER_LENGTH,

+

+      // UINT16                    Checksum;

+      0,

+

+      // UINT16                    ExtHeaderOffset;

+      0,

+

+      // UINT8                     Reserved[1];

+      {0},

+

+      // UINT8                     Revision;

+      EFI_FVH_REVISION,

+

+      // EFI_FV_BLOCK_MAP_ENTRY    BlockMap[1];

+      {

+        {

+          2, // UINT32 NumBlocks;

+          EMU_FVB_BLOCK_SIZE  // UINT32 Length;

+        }

+      }

+    },

+    // EFI_FV_BLOCK_MAP_ENTRY     EndBlockMap;

+    { 0, 0 }, // End of block map

+    { // VARIABLE_STORE_HEADER      VarHdr;

+        // EFI_GUID  Signature;     // need authenticated variables for secure boot

+        EFI_AUTHENTICATED_VARIABLE_GUID,

+

+      // UINT32  Size;

+      (

+        FixedPcdGet32 (PcdVariableStoreSize) -

+        OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)

+      ),

+

+      // UINT8   Format;

+      VARIABLE_STORE_FORMATTED,

+

+      // UINT8   State;

+      VARIABLE_STORE_HEALTHY,

+

+      // UINT16  Reserved;

+      0,

+

+      // UINT32  Reserved1;

+      0

+    }

+  };

+

+  EFI_FIRMWARE_VOLUME_HEADER  *Fv;

+

+  //

+  // Copy the template structure into the location

+  //

+  if (FeaturePcdGet (PcdSecureBootEnable) == FALSE) {

+    CopyMem (Ptr, (VOID*)&FvAndVarTemplate, sizeof (FvAndVarTemplate));

+  } else {

+    CopyMem (Ptr, (VOID*)&FvAndAuthenticatedVarTemplate, sizeof (FvAndAuthenticatedVarTemplate));

+  }

+

+  //

+  // Update the checksum for the FV header

+  //

+  Fv = (EFI_FIRMWARE_VOLUME_HEADER*) Ptr;

+  Fv->Checksum = CalculateCheckSum16 (Ptr, Fv->HeaderLength);

+}

+

+/**

+  Main entry point.

+

+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  

+  @param[in] SystemTable    A pointer to the EFI System Table.

+  

+  @retval EFI_SUCCESS       Successfully initialized.

+

+**/

+EFI_STATUS

+EFIAPI

+FvbInitialize (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  )

+{

+  EFI_STATUS                          Status;

+  VOID                                *Ptr;

+  VOID                                *SubPtr;

+  BOOLEAN                             Initialize;

+  EFI_HANDLE                          Handle;

+  EFI_PHYSICAL_ADDRESS                Address;

+

+  DEBUG ((EFI_D_INFO, "EMU Variable FVB Started\n"));

+

+  //

+  // Verify that the PCD's are set correctly.

+  //

+  if (

+       (PcdGet32 (PcdVariableStoreSize) +

+        PcdGet32 (PcdFlashNvStorageFtwWorkingSize)

+       ) >

+       EMU_FVB_BLOCK_SIZE

+     ) {

+    DEBUG ((EFI_D_ERROR, "EMU Variable invalid PCD sizes\n"));

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {

+    DEBUG ((EFI_D_INFO, "Disabling EMU Variable FVB since "

+                        "flash variables appear to be supported.\n"));

+    return EFI_ABORTED;

+  }

+

+  //

+  // By default we will initialize the FV contents.  But, if

+  // PcdEmuVariableNvStoreReserved is non-zero, then we will

+  // use this location for our buffer.

+  //

+  // If this location does not have a proper FV header, then

+  // we will initialize it.

+  //

+  Initialize = TRUE;

+  if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) {

+    Ptr = (VOID*)(UINTN) PcdGet64 (PcdEmuVariableNvStoreReserved);

+    DEBUG ((

+      EFI_D_INFO,

+      "EMU Variable FVB: Using pre-reserved block at %p\n",

+      Ptr

+      ));

+    Status = ValidateFvHeader (Ptr);

+    if (!EFI_ERROR (Status)) {

+      DEBUG ((EFI_D_INFO, "EMU Variable FVB: Found valid pre-existing FV\n"));

+      Initialize = FALSE;

+    }

+  } else {

+    Ptr = AllocateAlignedRuntimePages (

+            EFI_SIZE_TO_PAGES (EMU_FVB_SIZE),

+            SIZE_64KB

+            );

+  }

+

+  mEmuVarsFvb.BufferPtr = Ptr;

+

+  //

+  // Initialize the main FV header and variable store header

+  //

+  if (Initialize) {

+    SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);

+    InitializeFvAndVariableStoreHeaders (Ptr);

+  }

+  PcdSet64 (PcdFlashNvStorageVariableBase64, (UINT32)(UINTN) Ptr);

+

+  //

+  // Initialize the Fault Tolerant Write data area

+  //

+  SubPtr = (VOID*) ((UINT8*) Ptr + PcdGet32 (PcdVariableStoreSize));

+  PcdSet32 (PcdFlashNvStorageFtwWorkingBase, (UINT32)(UINTN) SubPtr);

+

+  //

+  // Initialize the Fault Tolerant Write spare block

+  //

+  SubPtr = (VOID*) ((UINT8*) Ptr + EMU_FVB_BLOCK_SIZE);

+  PcdSet32 (PcdFlashNvStorageFtwSpareBase, (UINT32)(UINTN) SubPtr);

+

+  //

+  // Setup FVB device path

+  //

+  Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Ptr;

+  mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address;

+  mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1;

+

+  //

+  // Install the protocols

+  //

+  DEBUG ((EFI_D_INFO, "Installing FVB for EMU Variable support\n"));

+  Handle = 0;

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &Handle,

+                  &gEfiFirmwareVolumeBlock2ProtocolGuid,

+                  &mEmuVarsFvb.FwVolBlockInstance,

+                  &gEfiDevicePathProtocolGuid,

+                  &mEmuVarsFvb.DevicePath,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Register for the virtual address change event

+  //

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_NOTIFY,

+                  FvbVirtualAddressChangeEvent,

+                  NULL,

+                  &gEfiEventVirtualAddressChangeGuid,

+                  &mEmuVarsFvbAddrChangeEvent

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return EFI_SUCCESS;

+}

+

+