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 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Guid/EventGroup.h>
18 #include <Guid/SystemNvDataGuid.h>
19 #include <Guid/VariableFormat.h>
21 #include <Protocol/FirmwareVolumeBlock.h>
22 #include <Protocol/DevicePath.h>
24 #include <Library/UefiLib.h>
25 #include <Library/UefiDriverEntryPoint.h>
26 #include <Library/BaseLib.h>
27 #include <Library/UefiRuntimeLib.h>
28 #include <Library/DebugLib.h>
29 #include <Library/BaseMemoryLib.h>
30 #include <Library/MemoryAllocationLib.h>
31 #include <Library/UefiBootServicesTableLib.h>
32 #include <Library/DevicePathLib.h>
33 #include <Library/PcdLib.h>
34 #include <Library/PlatformFvbLib.h>
37 #define EFI_AUTHENTICATED_VARIABLE_GUID \
38 { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
41 // Virtual Address Change Event
43 // This is needed for runtime variable access.
45 EFI_EVENT mEmuVarsFvbAddrChangeEvent
= NULL
;
48 // This is the single instance supported by this driver. It
49 // supports the FVB and Device Path protocols.
51 EFI_FW_VOL_BLOCK_DEVICE mEmuVarsFvb
= {
59 sizeof (MEMMAP_DEVICE_PATH
),
69 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
71 sizeof (EFI_DEVICE_PATH_PROTOCOL
),
77 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize
), // BlockSize
78 2 * FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize
), // Size
79 { // FwVolBlockInstance
80 FvbProtocolGetAttributes
,
81 FvbProtocolSetAttributes
,
82 FvbProtocolGetPhysicalAddress
,
83 FvbProtocolGetBlockSize
,
86 FvbProtocolEraseBlocks
,
93 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
95 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
96 It converts pointer to new virtual address.
98 @param Event Event whose notification function is being invoked.
99 @param Context Pointer to the notification function's context.
104 FvbVirtualAddressChangeEvent (
109 EfiConvertPointer (0x0, &mEmuVarsFvb
.BufferPtr
);
118 The GetPhysicalAddress() function retrieves the base address of
119 a memory-mapped firmware volume. This function should be called
120 only for memory-mapped firmware volumes.
122 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
124 @param Address Pointer to a caller-allocated
125 EFI_PHYSICAL_ADDRESS that, on successful
126 return from GetPhysicalAddress(), contains the
127 base address of the firmware volume.
129 @retval EFI_SUCCESS The firmware volume base address is returned.
131 @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
136 FvbProtocolGetPhysicalAddress (
137 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
138 OUT EFI_PHYSICAL_ADDRESS
*Address
141 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
143 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
145 *Address
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) FvbDevice
->BufferPtr
;
152 The GetBlockSize() function retrieves the size of the requested
153 block. It also returns the number of additional blocks with
154 the identical size. The GetBlockSize() function is used to
155 retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
158 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
160 @param Lba Indicates the block for which to return the size.
162 @param BlockSize Pointer to a caller-allocated UINTN in which
163 the size of the block is returned.
165 @param NumberOfBlocks Pointer to a caller-allocated UINTN in
166 which the number of consecutive blocks,
167 starting with Lba, is returned. All
168 blocks in this range have a size of
172 @retval EFI_SUCCESS The firmware volume base address is returned.
174 @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
179 FvbProtocolGetBlockSize (
180 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
182 OUT UINTN
*BlockSize
,
183 OUT UINTN
*NumberOfBlocks
186 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
189 return EFI_INVALID_PARAMETER
;
192 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
194 *BlockSize
= FvbDevice
->BlockSize
;
195 *NumberOfBlocks
= (UINTN
) (2 - (UINTN
) Lba
);
202 The GetAttributes() function retrieves the attributes and
203 current settings of the block. Status Codes Returned
205 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
207 @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the
208 attributes and current settings are
209 returned. Type EFI_FVB_ATTRIBUTES_2 is defined
210 in EFI_FIRMWARE_VOLUME_HEADER.
212 @retval EFI_SUCCESS The firmware volume attributes were
218 FvbProtocolGetAttributes (
219 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
220 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
224 (EFI_FVB_ATTRIBUTES_2
) (
225 EFI_FVB2_READ_ENABLED_CAP
|
226 EFI_FVB2_READ_STATUS
|
227 EFI_FVB2_WRITE_ENABLED_CAP
|
228 EFI_FVB2_WRITE_STATUS
|
229 EFI_FVB2_ERASE_POLARITY
237 The SetAttributes() function sets configurable firmware volume
238 attributes and returns the new settings of the firmware volume.
240 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
242 @param Attributes On input, Attributes is a pointer to
243 EFI_FVB_ATTRIBUTES_2 that contains the
244 desired firmware volume settings. On
245 successful return, it contains the new
246 settings of the firmware volume. Type
247 EFI_FVB_ATTRIBUTES_2 is defined in
248 EFI_FIRMWARE_VOLUME_HEADER.
250 @retval EFI_SUCCESS The firmware volume attributes were returned.
252 @retval EFI_INVALID_PARAMETER The attributes requested are in
253 conflict with the capabilities
254 as declared in the firmware
260 FvbProtocolSetAttributes (
261 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
262 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
265 return EFI_ACCESS_DENIED
;
270 Erases and initializes a firmware volume block.
272 The EraseBlocks() function erases one or more blocks as denoted
273 by the variable argument list. The entire parameter list of
274 blocks must be verified before erasing any blocks. If a block is
275 requested that does not exist within the associated firmware
276 volume (it has a larger index than the last block of the
277 firmware volume), the EraseBlocks() function must return the
278 status code EFI_INVALID_PARAMETER without modifying the contents
279 of the firmware volume. Implementations should be mindful that
280 the firmware volume might be in the WriteDisabled state. If it
281 is in this state, the EraseBlocks() function must return the
282 status code EFI_ACCESS_DENIED without modifying the contents of
283 the firmware volume. All calls to EraseBlocks() must be fully
284 flushed to the hardware before the EraseBlocks() service
287 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
290 @param ... The variable argument list is a list of tuples.
291 Each tuple describes a range of LBAs to erase
292 and consists of the following:
293 - An EFI_LBA that indicates the starting LBA
294 - A UINTN that indicates the number of blocks to
297 The list is terminated with an
298 EFI_LBA_LIST_TERMINATOR. For example, the
299 following indicates that two ranges of blocks
300 (5-7 and 10-11) are to be erased: EraseBlocks
301 (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
303 @retval EFI_SUCCESS The erase request was successfully
306 @retval EFI_ACCESS_DENIED The firmware volume is in the
308 @retval EFI_DEVICE_ERROR The block device is not functioning
309 correctly and could not be written.
310 The firmware device may have been
312 @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
313 in the variable argument list do
314 not exist in the firmware volume.
319 FvbProtocolEraseBlocks (
320 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
324 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
332 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
335 VA_START (args
, This
);
338 StartingLba
= VA_ARG (args
, EFI_LBA
);
339 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
343 NumOfLba
= VA_ARG (args
, UINT32
);
346 // Check input parameters
348 if ((NumOfLba
== 0) || (StartingLba
> 1) || ((StartingLba
+ NumOfLba
) > 2)) {
350 return EFI_INVALID_PARAMETER
;
353 if (StartingLba
== 0) {
354 Erase
= (UINT8
) (Erase
| BIT0
);
356 if ((StartingLba
+ NumOfLba
) == 2) {
357 Erase
= (UINT8
) (Erase
| BIT1
);
364 ErasePtr
= (UINT8
*) FvbDevice
->BufferPtr
;
367 if ((Erase
& BIT0
) != 0) {
368 EraseSize
= EraseSize
+ FvbDevice
->BlockSize
;
370 ErasePtr
= (VOID
*) ((UINT8
*)ErasePtr
+ FvbDevice
->BlockSize
);
373 if ((Erase
& BIT1
) != 0) {
374 EraseSize
= EraseSize
+ FvbDevice
->BlockSize
;
377 if (EraseSize
!= 0) {
383 VA_START (args
, This
);
384 PlatformFvbBlocksErased (This
, args
);
393 Writes the specified number of bytes from the input buffer to the block.
395 The Write() function writes the specified number of bytes from
396 the provided buffer to the specified block and offset. If the
397 firmware volume is sticky write, the caller must ensure that
398 all the bits of the specified range to write are in the
399 EFI_FVB_ERASE_POLARITY state before calling the Write()
400 function, or else the result will be unpredictable. This
401 unpredictability arises because, for a sticky-write firmware
402 volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
403 state but cannot flip it back again. In general, before
404 calling the Write() function, the caller should call the
405 EraseBlocks() function first to erase the specified block to
406 write. A block erase cycle will transition bits from the
407 (NOT)EFI_FVB_ERASE_POLARITY state back to the
408 EFI_FVB_ERASE_POLARITY state. Implementations should be
409 mindful that the firmware volume might be in the WriteDisabled
410 state. If it is in this state, the Write() function must
411 return the status code EFI_ACCESS_DENIED without modifying the
412 contents of the firmware volume. The Write() function must
413 also prevent spanning block boundaries. If a write is
414 requested that spans a block boundary, the write must store up
415 to the boundary but not beyond. The output parameter NumBytes
416 must be set to correctly indicate the number of bytes actually
417 written. The caller must be aware that a write may be
418 partially completed. All writes, partial or otherwise, must be
419 fully flushed to the hardware before the Write() service
422 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
424 @param Lba The starting logical block index to write to.
426 @param Offset Offset into the block at which to begin writing.
428 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
429 contains the total size of the buffer. At
430 exit, *NumBytes contains the total number of
431 bytes actually written.
433 @param Buffer Pointer to a caller-allocated buffer that
434 contains the source for the write.
436 @retval EFI_SUCCESS The firmware volume was written successfully.
438 @retval EFI_BAD_BUFFER_SIZE The write was attempted across an
439 LBA boundary. On output, NumBytes
440 contains the total number of bytes
443 @retval EFI_ACCESS_DENIED The firmware volume is in the
446 @retval EFI_DEVICE_ERROR The block device is malfunctioning
447 and could not be written.
454 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
457 IN OUT UINTN
*NumBytes
,
462 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
465 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
467 if ((Lba
> 1) || (Offset
> FvbDevice
->BlockSize
)) {
468 return EFI_INVALID_PARAMETER
;
471 if ((Offset
+ *NumBytes
) > FvbDevice
->BlockSize
) {
472 *NumBytes
= FvbDevice
->BlockSize
- Offset
;
476 (UINT8
*) FvbDevice
->BufferPtr
+
477 MultU64x32 (Lba
, (UINT32
) FvbDevice
->BlockSize
) +
481 CopyMem (FvbDataPtr
, Buffer
, *NumBytes
);
482 PlatformFvbDataWritten (This
, Lba
, Offset
, *NumBytes
, Buffer
);
490 Reads the specified number of bytes into a buffer from the specified block.
492 The Read() function reads the requested number of bytes from the
493 requested block and stores them in the provided buffer.
494 Implementations should be mindful that the firmware volume
495 might be in the ReadDisabled state. If it is in this state,
496 the Read() function must return the status code
497 EFI_ACCESS_DENIED without modifying the contents of the
498 buffer. The Read() function must also prevent spanning block
499 boundaries. If a read is requested that would span a block
500 boundary, the read must read up to the boundary but not
501 beyond. The output parameter NumBytes must be set to correctly
502 indicate the number of bytes actually read. The caller must be
503 aware that a read may be partially completed.
505 @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
507 @param Lba The starting logical block index
510 @param Offset Offset into the block at which to begin reading.
512 @param NumBytes Pointer to a UINTN. At entry, *NumBytes
513 contains the total size of the buffer. At
514 exit, *NumBytes contains the total number of
517 @param Buffer Pointer to a caller-allocated buffer that will
518 be used to hold the data that is read.
520 @retval EFI_SUCCESS The firmware volume was read successfully
521 and contents are in Buffer.
523 @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA
524 boundary. On output, NumBytes
525 contains the total number of bytes
528 @retval EFI_ACCESS_DENIED The firmware volume is in the
531 @retval EFI_DEVICE_ERROR The block device is not
532 functioning correctly and could
539 IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
*This
,
542 IN OUT UINTN
*NumBytes
,
546 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
549 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
551 if ((Lba
> 1) || (Offset
> FvbDevice
->BlockSize
)) {
552 return EFI_INVALID_PARAMETER
;
555 if ((Offset
+ *NumBytes
) > FvbDevice
->BlockSize
) {
556 *NumBytes
= FvbDevice
->BlockSize
- Offset
;
560 (UINT8
*) FvbDevice
->BufferPtr
+
561 MultU64x32 (Lba
, (UINT32
) FvbDevice
->BlockSize
) +
565 CopyMem (Buffer
, FvbDataPtr
, *NumBytes
);
566 PlatformFvbDataRead (This
, Lba
, Offset
, *NumBytes
, Buffer
);
574 Check the integrity of firmware volume header.
576 @param[in] FwVolHeader - A pointer to a firmware volume header
578 @retval EFI_SUCCESS - The firmware volume is consistent
579 @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
584 IN EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
590 // Verify the header revision, header signature, length
591 // Length of FvBlock cannot be 2**64-1
592 // HeaderLength cannot be an odd number
594 if ((FwVolHeader
->Revision
!= EFI_FVH_REVISION
) ||
595 (FwVolHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
596 (FwVolHeader
->FvLength
!= EMU_FVB_SIZE
) ||
597 (FwVolHeader
->HeaderLength
!= EMU_FV_HEADER_LENGTH
)
599 DEBUG ((EFI_D_INFO
, "EMU Variable FVB: Basic FV headers were invalid\n"));
600 return EFI_NOT_FOUND
;
603 // Verify the header checksum
605 Checksum
= CalculateSum16((VOID
*) FwVolHeader
, FwVolHeader
->HeaderLength
);
608 DEBUG ((EFI_D_INFO
, "EMU Variable FVB: FV checksum was invalid\n"));
609 return EFI_NOT_FOUND
;
617 Initializes the FV Header and Variable Store Header
618 to support variable operations.
620 @param[in] Ptr - Location to initialize the headers
624 InitializeFvAndVariableStoreHeaders (
629 // Templates for standard (non-authenticated) variable FV header
631 STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndVarTemplate
= {
632 { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
633 // UINT8 ZeroVector[16];
634 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
636 // EFI_GUID FileSystemGuid;
637 EFI_SYSTEM_NV_DATA_FV_GUID
,
645 // EFI_FVB_ATTRIBUTES_2 Attributes;
648 // UINT16 HeaderLength;
649 EMU_FV_HEADER_LENGTH
,
654 // UINT16 ExtHeaderOffset;
657 // UINT8 Reserved[1];
663 // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
666 2, // UINT32 NumBlocks;
667 EMU_FVB_BLOCK_SIZE
// UINT32 Length;
671 // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
672 { 0, 0 }, // End of block map
673 { // VARIABLE_STORE_HEADER VarHdr;
674 // EFI_GUID Signature;
679 FixedPcdGet32 (PcdVariableStoreSize
) -
680 OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE
, VarHdr
)
684 VARIABLE_STORE_FORMATTED
,
687 VARIABLE_STORE_HEALTHY
,
698 // Templates for authenticated variable FV header
700 STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate
= {
701 { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
702 // UINT8 ZeroVector[16];
703 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
705 // EFI_GUID FileSystemGuid;
706 EFI_SYSTEM_NV_DATA_FV_GUID
,
714 // EFI_FVB_ATTRIBUTES_2 Attributes;
717 // UINT16 HeaderLength;
718 EMU_FV_HEADER_LENGTH
,
723 // UINT16 ExtHeaderOffset;
726 // UINT8 Reserved[1];
732 // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
735 2, // UINT32 NumBlocks;
736 EMU_FVB_BLOCK_SIZE
// UINT32 Length;
740 // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
741 { 0, 0 }, // End of block map
742 { // VARIABLE_STORE_HEADER VarHdr;
743 // EFI_GUID Signature; // need authenticated variables for secure boot
744 EFI_AUTHENTICATED_VARIABLE_GUID
,
748 FixedPcdGet32 (PcdVariableStoreSize
) -
749 OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE
, VarHdr
)
753 VARIABLE_STORE_FORMATTED
,
756 VARIABLE_STORE_HEALTHY
,
766 EFI_FIRMWARE_VOLUME_HEADER
*Fv
;
769 // Copy the template structure into the location
771 if (FeaturePcdGet (PcdSecureBootEnable
) == FALSE
) {
772 CopyMem (Ptr
, (VOID
*)&FvAndVarTemplate
, sizeof (FvAndVarTemplate
));
774 CopyMem (Ptr
, (VOID
*)&FvAndAuthenticatedVarTemplate
, sizeof (FvAndAuthenticatedVarTemplate
));
778 // Update the checksum for the FV header
780 Fv
= (EFI_FIRMWARE_VOLUME_HEADER
*) Ptr
;
781 Fv
->Checksum
= CalculateCheckSum16 (Ptr
, Fv
->HeaderLength
);
786 Initializes the Fault Tolerant Write data structure
788 This data structure is used by the Fault Tolerant Write driver.
790 @param[in] Buffer - Location for the FTW data structure
798 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*Hdr
;
800 STATIC EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER DefaultFtw
= {
801 EFI_SYSTEM_NV_DATA_FV_GUID
, // EFI_GUID Signature;
802 ERASED_UINT32
, // UINT32 Crc;
803 ERASED_BIT
, // UINT8 WorkingBlockValid : 1;
804 ERASED_BIT
, // UINT8 WorkingBlockInvalid : 1;
805 0, // UINT8 Reserved : 6;
806 { 0, 0, 0 }, // UINT8 Reserved3[3];
807 FTW_WRITE_QUEUE_SIZE
// UINT64 WriteQueueSize;
810 CopyMem (Buffer
, (VOID
*) &DefaultFtw
, sizeof (DefaultFtw
));
812 Hdr
= (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*) Buffer
;
815 // Calculate checksum.
817 // The Crc, WorkingBlockValid and WorkingBlockInvalid bits should
818 // be set to the erased state before computing the checksum.
820 gBS
->CalculateCrc32 (Buffer
, sizeof (DefaultFtw
), &TempCrc
);
826 Hdr
->WorkingBlockValid
= NOT_ERASED_BIT
;
833 @param[in] ImageHandle The firmware allocated handle for the EFI image.
834 @param[in] SystemTable A pointer to the EFI System Table.
836 @retval EFI_SUCCESS Successfully initialized.
842 IN EFI_HANDLE ImageHandle
,
843 IN EFI_SYSTEM_TABLE
*SystemTable
851 EFI_PHYSICAL_ADDRESS Address
;
853 DEBUG ((EFI_D_INFO
, "EMU Variable FVB Started\n"));
856 // Verify that the PCD's are set correctly.
859 (PcdGet32 (PcdVariableStoreSize
) +
860 PcdGet32 (PcdFlashNvStorageFtwWorkingSize
)
864 DEBUG ((EFI_D_ERROR
, "EMU Variable invalid PCD sizes\n"));
865 return EFI_INVALID_PARAMETER
;
869 // By default we will initialize the FV contents. But, if
870 // PcdEmuVariableNvStoreReserved is non-zero, then we will
871 // use this location for our buffer.
873 // If this location does not have a proper FV header, then
874 // we will initialize it.
877 if (PcdGet64 (PcdEmuVariableNvStoreReserved
) != 0) {
878 Ptr
= (VOID
*)(UINTN
) PcdGet64 (PcdEmuVariableNvStoreReserved
);
881 "EMU Variable FVB: Using pre-reserved block at %p\n",
884 Status
= ValidateFvHeader (Ptr
);
885 if (!EFI_ERROR (Status
)) {
886 DEBUG ((EFI_D_INFO
, "EMU Variable FVB: Found valid pre-existing FV\n"));
890 Ptr
= AllocateAlignedRuntimePages (
891 EFI_SIZE_TO_PAGES (EMU_FVB_SIZE
),
896 mEmuVarsFvb
.BufferPtr
= Ptr
;
899 // Initialize the main FV header and variable store header
902 SetMem (Ptr
, EMU_FVB_SIZE
, ERASED_UINT8
);
903 InitializeFvAndVariableStoreHeaders (Ptr
);
905 PcdSet64 (PcdFlashNvStorageVariableBase64
, (UINT32
)(UINTN
) Ptr
);
908 // Initialize the Fault Tolerant Write data area
910 SubPtr
= (VOID
*) ((UINT8
*) Ptr
+ PcdGet32 (PcdVariableStoreSize
));
912 InitializeFtwState (SubPtr
);
914 PcdSet32 (PcdFlashNvStorageFtwWorkingBase
, (UINT32
)(UINTN
) SubPtr
);
917 // Initialize the Fault Tolerant Write spare block
919 SubPtr
= (VOID
*) ((UINT8
*) Ptr
+ EMU_FVB_BLOCK_SIZE
);
920 PcdSet32 (PcdFlashNvStorageFtwSpareBase
, (UINT32
)(UINTN
) SubPtr
);
923 // Setup FVB device path
925 Address
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Ptr
;
926 mEmuVarsFvb
.DevicePath
.MemMapDevPath
.StartingAddress
= Address
;
927 mEmuVarsFvb
.DevicePath
.MemMapDevPath
.EndingAddress
= Address
+ EMU_FVB_SIZE
- 1;
930 // Install the protocols
932 DEBUG ((EFI_D_INFO
, "Installing FVB for EMU Variable support\n"));
934 Status
= gBS
->InstallMultipleProtocolInterfaces (
936 &gEfiFirmwareVolumeBlock2ProtocolGuid
,
937 &mEmuVarsFvb
.FwVolBlockInstance
,
938 &gEfiDevicePathProtocolGuid
,
939 &mEmuVarsFvb
.DevicePath
,
942 ASSERT_EFI_ERROR (Status
);
945 // Register for the virtual address change event
947 Status
= gBS
->CreateEventEx (
950 FvbVirtualAddressChangeEvent
,
952 &gEfiEventVirtualAddressChangeGuid
,
953 &mEmuVarsFvbAddrChangeEvent
955 ASSERT_EFI_ERROR (Status
);