123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845 |
- /** @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>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #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
- EMU_FVB_BLOCK_SIZE, // BlockSize
- EMU_FVB_SIZE, // 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 >= EMU_FVB_NUM_TOTAL_BLOCKS) {
- return EFI_INVALID_PARAMETER;
- }
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
- *BlockSize = FvbDevice->BlockSize;
- *NumberOfBlocks = (UINTN)(EMU_FVB_NUM_TOTAL_BLOCKS - 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 *ErasePtr;
- UINTN EraseSize;
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
- //
- // Check input parameters
- //
- VA_START (Args, This);
- do {
- StartingLba = VA_ARG (Args, EFI_LBA);
- if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
- break;
- }
- NumOfLba = VA_ARG (Args, UINTN);
- if ((StartingLba > EMU_FVB_NUM_TOTAL_BLOCKS) ||
- (NumOfLba > EMU_FVB_NUM_TOTAL_BLOCKS - StartingLba))
- {
- VA_END (Args);
- return EFI_INVALID_PARAMETER;
- }
- } while (1);
- VA_END (Args);
- //
- // Erase blocks
- //
- VA_START (Args, This);
- do {
- StartingLba = VA_ARG (Args, EFI_LBA);
- if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
- break;
- }
- NumOfLba = VA_ARG (Args, UINTN);
- ErasePtr = FvbDevice->BufferPtr;
- ErasePtr += (UINTN)StartingLba * FvbDevice->BlockSize;
- EraseSize = NumOfLba * FvbDevice->BlockSize;
- SetMem (ErasePtr, EraseSize, ERASED_UINT8);
- } while (1);
- VA_END (Args);
- //
- // Call platform hook
- //
- 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;
- EFI_STATUS Status;
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
- if ((Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) ||
- (Offset > FvbDevice->BlockSize))
- {
- return EFI_INVALID_PARAMETER;
- }
- Status = EFI_SUCCESS;
- if (*NumBytes > FvbDevice->BlockSize - Offset) {
- *NumBytes = FvbDevice->BlockSize - Offset;
- Status = EFI_BAD_BUFFER_SIZE;
- }
- FvbDataPtr = FvbDevice->BufferPtr;
- FvbDataPtr += (UINTN)Lba * FvbDevice->BlockSize;
- FvbDataPtr += Offset;
- CopyMem (FvbDataPtr, Buffer, *NumBytes);
- PlatformFvbDataWritten (This, Lba, Offset, *NumBytes, Buffer);
- return Status;
- }
- /**
- 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;
- EFI_STATUS Status;
- FvbDevice = FVB_DEVICE_FROM_THIS (This);
- if ((Lba >= EMU_FVB_NUM_TOTAL_BLOCKS) ||
- (Offset > FvbDevice->BlockSize))
- {
- return EFI_INVALID_PARAMETER;
- }
- Status = EFI_SUCCESS;
- if (*NumBytes > FvbDevice->BlockSize - Offset) {
- *NumBytes = FvbDevice->BlockSize - Offset;
- Status = EFI_BAD_BUFFER_SIZE;
- }
- FvbDataPtr = FvbDevice->BufferPtr;
- FvbDataPtr += (UINTN)Lba * FvbDevice->BlockSize;
- FvbDataPtr += Offset;
- CopyMem (Buffer, FvbDataPtr, *NumBytes);
- PlatformFvbDataRead (This, Lba, Offset, *NumBytes, Buffer);
- return Status;
- }
- /**
- 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 ((DEBUG_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 ((DEBUG_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 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];
- {
- {
- EMU_FVB_NUM_TOTAL_BLOCKS, // 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 (PcdFlashNvStorageVariableSize) -
- 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
- //
- CopyMem (
- Ptr,
- &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;
- RETURN_STATUS PcdStatus;
- DEBUG ((DEBUG_INFO, "EMU Variable FVB Started\n"));
- //
- // Verify that the PCD's are set correctly.
- //
- ASSERT (
- FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) %
- EMU_FVB_BLOCK_SIZE == 0
- );
- if (
- (PcdGet32 (PcdFlashNvStorageVariableSize) +
- PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
- ) >
- EMU_FVB_NUM_SPARE_BLOCKS * EMU_FVB_BLOCK_SIZE
- )
- {
- DEBUG ((DEBUG_ERROR, "EMU Variable invalid PCD sizes\n"));
- return EFI_INVALID_PARAMETER;
- }
- if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
- DEBUG ((
- DEBUG_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 ((
- DEBUG_INFO,
- "EMU Variable FVB: Using pre-reserved block at %p\n",
- Ptr
- ));
- Status = ValidateFvHeader (Ptr);
- if (!EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "EMU Variable FVB: Found valid pre-existing FV\n"));
- Initialize = FALSE;
- }
- } else {
- Ptr = AllocateRuntimePages (EFI_SIZE_TO_PAGES (EMU_FVB_SIZE));
- }
- mEmuVarsFvb.BufferPtr = Ptr;
- //
- // Initialize the main FV header and variable store header
- //
- if (Initialize) {
- SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);
- InitializeFvAndVariableStoreHeaders (Ptr);
- }
- PcdStatus = PcdSet64S (PcdFlashNvStorageVariableBase64, (UINTN)Ptr);
- ASSERT_RETURN_ERROR (PcdStatus);
- //
- // Initialize the Fault Tolerant Write data area
- //
- SubPtr = (VOID *)((UINT8 *)Ptr + PcdGet32 (PcdFlashNvStorageVariableSize));
- PcdStatus = PcdSet64S (
- PcdFlashNvStorageFtwWorkingBase64,
- (UINTN)SubPtr
- );
- ASSERT_RETURN_ERROR (PcdStatus);
- //
- // Initialize the Fault Tolerant Write spare block
- //
- SubPtr = (VOID *)((UINT8 *)Ptr +
- EMU_FVB_NUM_SPARE_BLOCKS * EMU_FVB_BLOCK_SIZE);
- PcdStatus = PcdSet64S (
- PcdFlashNvStorageFtwSpareBase64,
- (UINTN)SubPtr
- );
- ASSERT_RETURN_ERROR (PcdStatus);
- //
- // 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 ((DEBUG_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;
- }
|