2 Firmware Block Services to support emulating non-volatile variables
3 by pretending that a memory buffer is storage for the NV variables.
5 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Guid/EventGroup.h>
12 #include <Guid/SystemNvDataGuid.h>
13 #include <Guid/VariableFormat.h>
15 #include <Protocol/FirmwareVolumeBlock.h>
16 #include <Protocol/DevicePath.h>
18 #include <Library/UefiLib.h>
19 #include <Library/UefiDriverEntryPoint.h>
20 #include <Library/BaseLib.h>
21 #include <Library/UefiRuntimeLib.h>
22 #include <Library/DebugLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/DevicePathLib.h>
27 #include <Library/PcdLib.h>
28 #include <Library/PlatformFvbLib.h>
31 #define EFI_AUTHENTICATED_VARIABLE_GUID \
32 { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
35 // Virtual Address Change Event
37 // This is needed for runtime variable access.
39 EFI_EVENT mEmuVarsFvbAddrChangeEvent
= NULL
;
42 // This is the single instance supported by this driver. It
43 // supports the FVB and Device Path protocols.
45 EFI_FW_VOL_BLOCK_DEVICE mEmuVarsFvb
= {
53 sizeof (MEMMAP_DEVICE_PATH
),
63 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
65 sizeof (EFI_DEVICE_PATH_PROTOCOL
),
71 EMU_FVB_BLOCK_SIZE
, // BlockSize
73 { // FwVolBlockInstance
74 FvbProtocolGetAttributes
,
75 FvbProtocolSetAttributes
,
76 FvbProtocolGetPhysicalAddress
,
77 FvbProtocolGetBlockSize
,
80 FvbProtocolEraseBlocks
,
87 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
89 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
90 It converts pointer to new virtual address.
92 @param Event Event whose notification function is being invoked.
93 @param Context Pointer to the notification function's context.
98 FvbVirtualAddressChangeEvent (
103 EfiConvertPointer (0x0, &mEmuVarsFvb
.BufferPtr
);
112 The GetPhysicalAddress() function retrieves the base address of
113 a memory-mapped firmware volume. This function should be called
114 only for memory-mapped firmware volumes.
116 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
118 @param Address Pointer to a caller-allocated
119 EFI_PHYSICAL_ADDRESS that, on successful
120 return from GetPhysicalAddress(), contains the
121 base address of the firmware volume.
123 @retval EFI_SUCCESS The firmware volume base address is returned.
125 @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
130 FvbProtocolGetPhysicalAddress (
131 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
132 OUT EFI_PHYSICAL_ADDRESS
*Address
135 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
137 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
139 *Address
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) FvbDevice
->BufferPtr
;
146 The GetBlockSize() function retrieves the size of the requested
147 block. It also returns the number of additional blocks with
148 the identical size. The GetBlockSize() function is used to
149 retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
152 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
154 @param Lba Indicates the block for which to return the size.
156 @param BlockSize Pointer to a caller-allocated UINTN in which
157 the size of the block is returned.
159 @param NumberOfBlocks Pointer to a caller-allocated UINTN in
160 which the number of consecutive blocks,
161 starting with Lba, is returned. All
162 blocks in this range have a size of
166 @retval EFI_SUCCESS The firmware volume base address is returned.
168 @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
173 FvbProtocolGetBlockSize (
174 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
176 OUT UINTN
*BlockSize
,
177 OUT UINTN
*NumberOfBlocks
180 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
182 if (Lba
>= EMU_FVB_NUM_TOTAL_BLOCKS
) {
183 return EFI_INVALID_PARAMETER
;
186 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
188 *BlockSize
= FvbDevice
->BlockSize
;
189 *NumberOfBlocks
= (UINTN
)(EMU_FVB_NUM_TOTAL_BLOCKS
- Lba
);
196 The GetAttributes() function retrieves the attributes and
197 current settings of the block. Status Codes Returned
199 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
201 @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the
202 attributes and current settings are
203 returned. Type EFI_FVB_ATTRIBUTES_2 is defined
204 in EFI_FIRMWARE_VOLUME_HEADER.
206 @retval EFI_SUCCESS The firmware volume attributes were
212 FvbProtocolGetAttributes (
213 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
214 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
218 (EFI_FVB_ATTRIBUTES_2
) (
219 EFI_FVB2_READ_ENABLED_CAP
|
220 EFI_FVB2_READ_STATUS
|
221 EFI_FVB2_WRITE_ENABLED_CAP
|
222 EFI_FVB2_WRITE_STATUS
|
223 EFI_FVB2_ERASE_POLARITY
231 The SetAttributes() function sets configurable firmware volume
232 attributes and returns the new settings of the firmware volume.
234 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
236 @param Attributes On input, Attributes is a pointer to
237 EFI_FVB_ATTRIBUTES_2 that contains the
238 desired firmware volume settings. On
239 successful return, it contains the new
240 settings of the firmware volume. Type
241 EFI_FVB_ATTRIBUTES_2 is defined in
242 EFI_FIRMWARE_VOLUME_HEADER.
244 @retval EFI_SUCCESS The firmware volume attributes were returned.
246 @retval EFI_INVALID_PARAMETER The attributes requested are in
247 conflict with the capabilities
248 as declared in the firmware
254 FvbProtocolSetAttributes (
255 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
256 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
259 return EFI_ACCESS_DENIED
;
264 Erases and initializes a firmware volume block.
266 The EraseBlocks() function erases one or more blocks as denoted
267 by the variable argument list. The entire parameter list of
268 blocks must be verified before erasing any blocks. If a block is
269 requested that does not exist within the associated firmware
270 volume (it has a larger index than the last block of the
271 firmware volume), the EraseBlocks() function must return the
272 status code EFI_INVALID_PARAMETER without modifying the contents
273 of the firmware volume. Implementations should be mindful that
274 the firmware volume might be in the WriteDisabled state. If it
275 is in this state, the EraseBlocks() function must return the
276 status code EFI_ACCESS_DENIED without modifying the contents of
277 the firmware volume. All calls to EraseBlocks() must be fully
278 flushed to the hardware before the EraseBlocks() service
281 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
284 @param ... The variable argument list is a list of tuples.
285 Each tuple describes a range of LBAs to erase
286 and consists of the following:
287 - An EFI_LBA that indicates the starting LBA
288 - A UINTN that indicates the number of blocks to
291 The list is terminated with an
292 EFI_LBA_LIST_TERMINATOR. For example, the
293 following indicates that two ranges of blocks
294 (5-7 and 10-11) are to be erased: EraseBlocks
295 (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
297 @retval EFI_SUCCESS The erase request was successfully
300 @retval EFI_ACCESS_DENIED The firmware volume is in the
302 @retval EFI_DEVICE_ERROR The block device is not functioning
303 correctly and could not be written.
304 The firmware device may have been
306 @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
307 in the variable argument list do
308 not exist in the firmware volume.
313 FvbProtocolEraseBlocks (
314 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
318 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
325 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
328 // Check input parameters
330 VA_START (Args
, This
);
332 StartingLba
= VA_ARG (Args
, EFI_LBA
);
333 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
336 NumOfLba
= VA_ARG (Args
, UINTN
);
338 if (StartingLba
> EMU_FVB_NUM_TOTAL_BLOCKS
||
339 NumOfLba
> EMU_FVB_NUM_TOTAL_BLOCKS
- StartingLba
) {
341 return EFI_INVALID_PARAMETER
;
349 VA_START (Args
, This
);
351 StartingLba
= VA_ARG (Args
, EFI_LBA
);
352 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
355 NumOfLba
= VA_ARG (Args
, UINTN
);
357 ErasePtr
= FvbDevice
->BufferPtr
;
358 ErasePtr
+= (UINTN
)StartingLba
* FvbDevice
->BlockSize
;
359 EraseSize
= NumOfLba
* FvbDevice
->BlockSize
;
361 SetMem (ErasePtr
, EraseSize
, ERASED_UINT8
);
366 // Call platform hook
368 VA_START (Args
, This
);
369 PlatformFvbBlocksErased (This
, Args
);
377 Writes the specified number of bytes from the input buffer to the block.
379 The Write() function writes the specified number of bytes from
380 the provided buffer to the specified block and offset. If the
381 firmware volume is sticky write, the caller must ensure that
382 all the bits of the specified range to write are in the
383 EFI_FVB_ERASE_POLARITY state before calling the Write()
384 function, or else the result will be unpredictable. This
385 unpredictability arises because, for a sticky-write firmware
386 volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
387 state but cannot flip it back again. In general, before
388 calling the Write() function, the caller should call the
389 EraseBlocks() function first to erase the specified block to
390 write. A block erase cycle will transition bits from the
391 (NOT)EFI_FVB_ERASE_POLARITY state back to the
392 EFI_FVB_ERASE_POLARITY state. Implementations should be
393 mindful that the firmware volume might be in the WriteDisabled
394 state. If it is in this state, the Write() function must
395 return the status code EFI_ACCESS_DENIED without modifying the
396 contents of the firmware volume. The Write() function must
397 also prevent spanning block boundaries. If a write is
398 requested that spans a block boundary, the write must store up
399 to the boundary but not beyond. The output parameter NumBytes
400 must be set to correctly indicate the number of bytes actually
401 written. The caller must be aware that a write may be
402 partially completed. All writes, partial or otherwise, must be
403 fully flushed to the hardware before the Write() service
406 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
408 @param Lba The starting logical block index to write to.
410 @param Offset Offset into the block at which to begin writing.
412 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
413 contains the total size of the buffer. At
414 exit, *NumBytes contains the total number of
415 bytes actually written.
417 @param Buffer Pointer to a caller-allocated buffer that
418 contains the source for the write.
420 @retval EFI_SUCCESS The firmware volume was written successfully.
422 @retval EFI_BAD_BUFFER_SIZE The write was attempted across an
423 LBA boundary. On output, NumBytes
424 contains the total number of bytes
427 @retval EFI_ACCESS_DENIED The firmware volume is in the
430 @retval EFI_DEVICE_ERROR The block device is malfunctioning
431 and could not be written.
438 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
441 IN OUT UINTN
*NumBytes
,
445 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
449 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
451 if (Lba
>= EMU_FVB_NUM_TOTAL_BLOCKS
||
452 Offset
> FvbDevice
->BlockSize
) {
453 return EFI_INVALID_PARAMETER
;
456 Status
= EFI_SUCCESS
;
457 if (*NumBytes
> FvbDevice
->BlockSize
- Offset
) {
458 *NumBytes
= FvbDevice
->BlockSize
- Offset
;
459 Status
= EFI_BAD_BUFFER_SIZE
;
462 FvbDataPtr
= FvbDevice
->BufferPtr
;
463 FvbDataPtr
+= (UINTN
)Lba
* FvbDevice
->BlockSize
;
464 FvbDataPtr
+= Offset
;
466 CopyMem (FvbDataPtr
, Buffer
, *NumBytes
);
467 PlatformFvbDataWritten (This
, Lba
, Offset
, *NumBytes
, Buffer
);
473 Reads the specified number of bytes into a buffer from the specified block.
475 The Read() function reads the requested number of bytes from the
476 requested block and stores them in the provided buffer.
477 Implementations should be mindful that the firmware volume
478 might be in the ReadDisabled state. If it is in this state,
479 the Read() function must return the status code
480 EFI_ACCESS_DENIED without modifying the contents of the
481 buffer. The Read() function must also prevent spanning block
482 boundaries. If a read is requested that would span a block
483 boundary, the read must read up to the boundary but not
484 beyond. The output parameter NumBytes must be set to correctly
485 indicate the number of bytes actually read. The caller must be
486 aware that a read may be partially completed.
488 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
490 @param Lba The starting logical block index
493 @param Offset Offset into the block at which to begin reading.
495 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
496 contains the total size of the buffer. At
497 exit, *NumBytes contains the total number of
500 @param Buffer Pointer to a caller-allocated buffer that will
501 be used to hold the data that is read.
503 @retval EFI_SUCCESS The firmware volume was read successfully
504 and contents are in Buffer.
506 @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA
507 boundary. On output, NumBytes
508 contains the total number of bytes
511 @retval EFI_ACCESS_DENIED The firmware volume is in the
514 @retval EFI_DEVICE_ERROR The block device is not
515 functioning correctly and could
522 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
525 IN OUT UINTN
*NumBytes
,
529 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
533 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
535 if (Lba
>= EMU_FVB_NUM_TOTAL_BLOCKS
||
536 Offset
> FvbDevice
->BlockSize
) {
537 return EFI_INVALID_PARAMETER
;
540 Status
= EFI_SUCCESS
;
541 if (*NumBytes
> FvbDevice
->BlockSize
- Offset
) {
542 *NumBytes
= FvbDevice
->BlockSize
- Offset
;
543 Status
= EFI_BAD_BUFFER_SIZE
;
546 FvbDataPtr
= FvbDevice
->BufferPtr
;
547 FvbDataPtr
+= (UINTN
)Lba
* FvbDevice
->BlockSize
;
548 FvbDataPtr
+= Offset
;
550 CopyMem (Buffer
, FvbDataPtr
, *NumBytes
);
551 PlatformFvbDataRead (This
, Lba
, Offset
, *NumBytes
, Buffer
);
557 Check the integrity of firmware volume header.
559 @param[in] FwVolHeader - A pointer to a firmware volume header
561 @retval EFI_SUCCESS - The firmware volume is consistent
562 @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
567 IN EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
573 // Verify the header revision, header signature, length
574 // Length of FvBlock cannot be 2**64-1
575 // HeaderLength cannot be an odd number
577 if ((FwVolHeader
->Revision
!= EFI_FVH_REVISION
) ||
578 (FwVolHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
579 (FwVolHeader
->FvLength
!= EMU_FVB_SIZE
) ||
580 (FwVolHeader
->HeaderLength
!= EMU_FV_HEADER_LENGTH
)
582 DEBUG ((EFI_D_INFO
, "EMU Variable FVB: Basic FV headers were invalid\n"));
583 return EFI_NOT_FOUND
;
586 // Verify the header checksum
588 Checksum
= CalculateSum16((VOID
*) FwVolHeader
, FwVolHeader
->HeaderLength
);
591 DEBUG ((EFI_D_INFO
, "EMU Variable FVB: FV checksum was invalid\n"));
592 return EFI_NOT_FOUND
;
600 Initializes the FV Header and Variable Store Header
601 to support variable operations.
603 @param[in] Ptr - Location to initialize the headers
607 InitializeFvAndVariableStoreHeaders (
612 // Templates for authenticated variable FV header
614 STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate
= {
615 { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
616 // UINT8 ZeroVector[16];
617 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
619 // EFI_GUID FileSystemGuid;
620 EFI_SYSTEM_NV_DATA_FV_GUID
,
628 // EFI_FVB_ATTRIBUTES_2 Attributes;
631 // UINT16 HeaderLength;
632 EMU_FV_HEADER_LENGTH
,
637 // UINT16 ExtHeaderOffset;
640 // UINT8 Reserved[1];
646 // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
649 EMU_FVB_NUM_TOTAL_BLOCKS
, // UINT32 NumBlocks;
650 EMU_FVB_BLOCK_SIZE
// UINT32 Length;
654 // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
655 { 0, 0 }, // End of block map
656 { // VARIABLE_STORE_HEADER VarHdr;
657 // EFI_GUID Signature; // need authenticated variables for secure boot
658 EFI_AUTHENTICATED_VARIABLE_GUID
,
662 FixedPcdGet32 (PcdFlashNvStorageVariableSize
) -
663 OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE
, VarHdr
)
667 VARIABLE_STORE_FORMATTED
,
670 VARIABLE_STORE_HEALTHY
,
680 EFI_FIRMWARE_VOLUME_HEADER
*Fv
;
683 // Copy the template structure into the location
687 &FvAndAuthenticatedVarTemplate
,
688 sizeof FvAndAuthenticatedVarTemplate
692 // Update the checksum for the FV header
694 Fv
= (EFI_FIRMWARE_VOLUME_HEADER
*) Ptr
;
695 Fv
->Checksum
= CalculateCheckSum16 (Ptr
, Fv
->HeaderLength
);
701 @param[in] ImageHandle The firmware allocated handle for the EFI image.
702 @param[in] SystemTable A pointer to the EFI System Table.
704 @retval EFI_SUCCESS Successfully initialized.
710 IN EFI_HANDLE ImageHandle
,
711 IN EFI_SYSTEM_TABLE
*SystemTable
719 EFI_PHYSICAL_ADDRESS Address
;
720 RETURN_STATUS PcdStatus
;
722 DEBUG ((EFI_D_INFO
, "EMU Variable FVB Started\n"));
725 // Verify that the PCD's are set correctly.
727 ASSERT (FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize
) %
728 EMU_FVB_BLOCK_SIZE
== 0);
730 (PcdGet32 (PcdFlashNvStorageVariableSize
) +
731 PcdGet32 (PcdFlashNvStorageFtwWorkingSize
)
733 EMU_FVB_NUM_SPARE_BLOCKS
* EMU_FVB_BLOCK_SIZE
735 DEBUG ((EFI_D_ERROR
, "EMU Variable invalid PCD sizes\n"));
736 return EFI_INVALID_PARAMETER
;
739 if (PcdGet64 (PcdFlashNvStorageVariableBase64
) != 0) {
740 DEBUG ((EFI_D_INFO
, "Disabling EMU Variable FVB since "
741 "flash variables appear to be supported.\n"));
746 // By default we will initialize the FV contents. But, if
747 // PcdEmuVariableNvStoreReserved is non-zero, then we will
748 // use this location for our buffer.
750 // If this location does not have a proper FV header, then
751 // we will initialize it.
754 if (PcdGet64 (PcdEmuVariableNvStoreReserved
) != 0) {
755 Ptr
= (VOID
*)(UINTN
) PcdGet64 (PcdEmuVariableNvStoreReserved
);
758 "EMU Variable FVB: Using pre-reserved block at %p\n",
761 Status
= ValidateFvHeader (Ptr
);
762 if (!EFI_ERROR (Status
)) {
763 DEBUG ((EFI_D_INFO
, "EMU Variable FVB: Found valid pre-existing FV\n"));
767 Ptr
= AllocateRuntimePages (EFI_SIZE_TO_PAGES (EMU_FVB_SIZE
));
770 mEmuVarsFvb
.BufferPtr
= Ptr
;
773 // Initialize the main FV header and variable store header
776 SetMem (Ptr
, EMU_FVB_SIZE
, ERASED_UINT8
);
777 InitializeFvAndVariableStoreHeaders (Ptr
);
779 PcdStatus
= PcdSet64S (PcdFlashNvStorageVariableBase64
, (UINT32
)(UINTN
) Ptr
);
780 ASSERT_RETURN_ERROR (PcdStatus
);
783 // Initialize the Fault Tolerant Write data area
785 SubPtr
= (VOID
*) ((UINT8
*) Ptr
+ PcdGet32 (PcdFlashNvStorageVariableSize
));
786 PcdStatus
= PcdSet32S (PcdFlashNvStorageFtwWorkingBase
,
787 (UINT32
)(UINTN
) SubPtr
);
788 ASSERT_RETURN_ERROR (PcdStatus
);
791 // Initialize the Fault Tolerant Write spare block
793 SubPtr
= (VOID
*) ((UINT8
*) Ptr
+
794 EMU_FVB_NUM_SPARE_BLOCKS
* EMU_FVB_BLOCK_SIZE
);
795 PcdStatus
= PcdSet32S (PcdFlashNvStorageFtwSpareBase
,
796 (UINT32
)(UINTN
) SubPtr
);
797 ASSERT_RETURN_ERROR (PcdStatus
);
800 // Setup FVB device path
802 Address
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Ptr
;
803 mEmuVarsFvb
.DevicePath
.MemMapDevPath
.StartingAddress
= Address
;
804 mEmuVarsFvb
.DevicePath
.MemMapDevPath
.EndingAddress
= Address
+ EMU_FVB_SIZE
- 1;
807 // Install the protocols
809 DEBUG ((EFI_D_INFO
, "Installing FVB for EMU Variable support\n"));
811 Status
= gBS
->InstallMultipleProtocolInterfaces (
813 &gEfiFirmwareVolumeBlock2ProtocolGuid
,
814 &mEmuVarsFvb
.FwVolBlockInstance
,
815 &gEfiDevicePathProtocolGuid
,
816 &mEmuVarsFvb
.DevicePath
,
819 ASSERT_EFI_ERROR (Status
);
822 // Register for the virtual address change event
824 Status
= gBS
->CreateEventEx (
827 FvbVirtualAddressChangeEvent
,
829 &gEfiEventVirtualAddressChangeGuid
,
830 &mEmuVarsFvbAddrChangeEvent
832 ASSERT_EFI_ERROR (Status
);