3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
18 // The protocols, PPI and GUID definitions for this module
20 #include <Protocol/DevicePath.h>
21 #include <Protocol/FirmwareVolumeBlock.h>
24 // The Library classes this module consumes
26 #include <Library/BaseLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/DebugLib.h>
29 #include <Library/DevicePathLib.h>
30 #include <Library/DxeServicesTableLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/UefiBootServicesTableLib.h>
34 #include "FwBlockService.h"
35 #include "QemuFlash.h"
37 #define EFI_FVB2_STATUS \
38 (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
40 ESAL_FWB_GLOBAL
*mFvbModuleGlobal
;
42 FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate
= {
48 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
)),
49 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
) >> 8)
53 (EFI_PHYSICAL_ADDRESS
)0,
54 (EFI_PHYSICAL_ADDRESS
)0,
58 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
60 END_DEVICE_PATH_LENGTH
,
66 FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate
= {
72 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
)),
73 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
) >> 8)
80 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
82 END_DEVICE_PATH_LENGTH
,
88 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate
= {
93 FvbProtocolGetAttributes
,
94 FvbProtocolSetAttributes
,
95 FvbProtocolGetPhysicalAddress
,
96 FvbProtocolGetBlockSize
,
99 FvbProtocolEraseBlocks
,
107 IN ESAL_FWB_GLOBAL
*Global
,
108 OUT EFI_FW_VOL_INSTANCE
**FwhInstance
114 Retrieves the physical address of a memory mapped FV
117 Instance - The FV instance whose base address is going to be
119 Global - Pointer to ESAL_FWB_GLOBAL that contains all
121 FwhInstance - The EFI_FW_VOL_INSTANCE firmware instance structure
124 EFI_SUCCESS - Successfully returns
125 EFI_INVALID_PARAMETER - Instance not found
129 EFI_FW_VOL_INSTANCE
*FwhRecord
;
132 if (Instance
>= Global
->NumFv
) {
133 return EFI_INVALID_PARAMETER
;
137 // Find the right instance of the FVB private data
139 FwhRecord
= Global
->FvInstance
;
140 while (Instance
> 0) {
141 FwhRecord
= (EFI_FW_VOL_INSTANCE
*)
143 (UINTN
)((UINT8
*)FwhRecord
) + FwhRecord
->VolumeHeader
.HeaderLength
+
144 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
149 *FwhInstance
= FwhRecord
;
155 FvbGetPhysicalAddress (
157 OUT EFI_PHYSICAL_ADDRESS
*Address
,
158 IN ESAL_FWB_GLOBAL
*Global
164 Retrieves the physical address of a memory mapped FV
167 Instance - The FV instance whose base address is going to be
169 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
170 that on successful return, contains the base
171 address of the firmware volume.
172 Global - Pointer to ESAL_FWB_GLOBAL that contains all
176 EFI_SUCCESS - Successfully returns
177 EFI_INVALID_PARAMETER - Instance not found
181 EFI_FW_VOL_INSTANCE
*FwhInstance
;
185 // Find the right instance of the FVB private data
187 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
188 ASSERT_EFI_ERROR (Status
);
189 *Address
= FwhInstance
->FvBase
;
195 FvbGetVolumeAttributes (
197 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
198 IN ESAL_FWB_GLOBAL
*Global
204 Retrieves attributes, insures positive polarity of attribute bits, returns
205 resulting attributes in output parameter
208 Instance - The FV instance whose attributes is going to be
210 Attributes - Output buffer which contains attributes
211 Global - Pointer to ESAL_FWB_GLOBAL that contains all
215 EFI_SUCCESS - Successfully returns
216 EFI_INVALID_PARAMETER - Instance not found
220 EFI_FW_VOL_INSTANCE
*FwhInstance
;
224 // Find the right instance of the FVB private data
226 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
227 ASSERT_EFI_ERROR (Status
);
228 *Attributes
= FwhInstance
->VolumeHeader
.Attributes
;
237 OUT UINTN
*LbaAddress
,
238 OUT UINTN
*LbaLength
,
239 OUT UINTN
*NumOfBlocks
,
240 IN ESAL_FWB_GLOBAL
*Global
246 Retrieves the starting address of an LBA in an FV
249 Instance - The FV instance which the Lba belongs to
250 Lba - The logical block address
251 LbaAddress - On output, contains the physical starting address
253 LbaLength - On output, contains the length of the block
254 NumOfBlocks - A pointer to a caller allocated UINTN in which the
255 number of consecutive blocks starting with Lba is
256 returned. All blocks in this range have a size of
258 Global - Pointer to ESAL_FWB_GLOBAL that contains all
262 EFI_SUCCESS - Successfully returns
263 EFI_INVALID_PARAMETER - Instance not found
272 EFI_FW_VOL_INSTANCE
*FwhInstance
;
273 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
277 // Find the right instance of the FVB private data
279 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
280 ASSERT_EFI_ERROR (Status
);
284 BlockMap
= &(FwhInstance
->VolumeHeader
.BlockMap
[0]);
287 // Parse the blockmap of the FV to find which map entry the Lba belongs to
290 NumBlocks
= BlockMap
->NumBlocks
;
291 BlockLength
= BlockMap
->Length
;
293 if ((NumBlocks
== 0) || (BlockLength
== 0)) {
294 return EFI_INVALID_PARAMETER
;
297 NextLba
= StartLba
+ NumBlocks
;
300 // The map entry found
302 if ((Lba
>= StartLba
) && (Lba
< NextLba
)) {
303 Offset
= Offset
+ (UINTN
)MultU64x32 ((Lba
- StartLba
), BlockLength
);
304 if (LbaAddress
!= NULL
) {
305 *LbaAddress
= FwhInstance
->FvBase
+ Offset
;
308 if (LbaLength
!= NULL
) {
309 *LbaLength
= BlockLength
;
312 if (NumOfBlocks
!= NULL
) {
313 *NumOfBlocks
= (UINTN
)(NextLba
- Lba
);
320 Offset
= Offset
+ NumBlocks
* BlockLength
;
326 FvbSetVolumeAttributes (
328 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
329 IN ESAL_FWB_GLOBAL
*Global
335 Modifies the current settings of the firmware volume according to the
336 input parameter, and returns the new setting of the volume
339 Instance - The FV instance whose attributes is going to be
341 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
342 containing the desired firmware volume settings.
343 On successful return, it contains the new settings
344 of the firmware volume
345 Global - Pointer to ESAL_FWB_GLOBAL that contains all
349 EFI_SUCCESS - Successfully returns
350 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
351 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
352 in conflict with the capabilities as declared in
353 the firmware volume header
357 EFI_FW_VOL_INSTANCE
*FwhInstance
;
358 EFI_FVB_ATTRIBUTES_2 OldAttributes
;
359 EFI_FVB_ATTRIBUTES_2
*AttribPtr
;
364 EFI_FVB_ATTRIBUTES_2 UnchangedAttributes
;
367 // Find the right instance of the FVB private data
369 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
370 ASSERT_EFI_ERROR (Status
);
373 (EFI_FVB_ATTRIBUTES_2
*)&(FwhInstance
->VolumeHeader
.Attributes
);
374 OldAttributes
= *AttribPtr
;
375 Capabilities
= OldAttributes
& (EFI_FVB2_READ_DISABLED_CAP
| \
376 EFI_FVB2_READ_ENABLED_CAP
| \
377 EFI_FVB2_WRITE_DISABLED_CAP
| \
378 EFI_FVB2_WRITE_ENABLED_CAP
| \
381 OldStatus
= OldAttributes
& EFI_FVB2_STATUS
;
382 NewStatus
= *Attributes
& EFI_FVB2_STATUS
;
384 UnchangedAttributes
= EFI_FVB2_READ_DISABLED_CAP
| \
385 EFI_FVB2_READ_ENABLED_CAP
| \
386 EFI_FVB2_WRITE_DISABLED_CAP
| \
387 EFI_FVB2_WRITE_ENABLED_CAP
| \
388 EFI_FVB2_LOCK_CAP
| \
389 EFI_FVB2_STICKY_WRITE
| \
390 EFI_FVB2_MEMORY_MAPPED
| \
391 EFI_FVB2_ERASE_POLARITY
| \
392 EFI_FVB2_READ_LOCK_CAP
| \
393 EFI_FVB2_WRITE_LOCK_CAP
| \
397 // Some attributes of FV is read only can *not* be set
399 if ((OldAttributes
& UnchangedAttributes
) ^
400 (*Attributes
& UnchangedAttributes
))
402 return EFI_INVALID_PARAMETER
;
406 // If firmware volume is locked, no status bit can be updated
408 if (OldAttributes
& EFI_FVB2_LOCK_STATUS
) {
409 if (OldStatus
^ NewStatus
) {
410 return EFI_ACCESS_DENIED
;
417 if ((Capabilities
& EFI_FVB2_READ_DISABLED_CAP
) == 0) {
418 if ((NewStatus
& EFI_FVB2_READ_STATUS
) == 0) {
419 return EFI_INVALID_PARAMETER
;
426 if ((Capabilities
& EFI_FVB2_READ_ENABLED_CAP
) == 0) {
427 if (NewStatus
& EFI_FVB2_READ_STATUS
) {
428 return EFI_INVALID_PARAMETER
;
433 // Test write disable
435 if ((Capabilities
& EFI_FVB2_WRITE_DISABLED_CAP
) == 0) {
436 if ((NewStatus
& EFI_FVB2_WRITE_STATUS
) == 0) {
437 return EFI_INVALID_PARAMETER
;
444 if ((Capabilities
& EFI_FVB2_WRITE_ENABLED_CAP
) == 0) {
445 if (NewStatus
& EFI_FVB2_WRITE_STATUS
) {
446 return EFI_INVALID_PARAMETER
;
453 if ((Capabilities
& EFI_FVB2_LOCK_CAP
) == 0) {
454 if (NewStatus
& EFI_FVB2_LOCK_STATUS
) {
455 return EFI_INVALID_PARAMETER
;
459 *AttribPtr
= (*AttribPtr
) & (0xFFFFFFFF & (~EFI_FVB2_STATUS
));
460 *AttribPtr
= (*AttribPtr
) | NewStatus
;
461 *Attributes
= *AttribPtr
;
471 FvbProtocolGetPhysicalAddress (
472 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
473 OUT EFI_PHYSICAL_ADDRESS
*Address
480 Retrieves the physical address of the device.
484 This - Calling context
485 Address - Output buffer containing the address.
488 EFI_SUCCESS - Successfully returns
492 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
494 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
496 return FvbGetPhysicalAddress (
505 FvbProtocolGetBlockSize (
506 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
507 IN CONST EFI_LBA Lba
,
508 OUT UINTN
*BlockSize
,
509 OUT UINTN
*NumOfBlocks
515 Retrieve the size of a logical block
518 This - Calling context
519 Lba - Indicates which block to return the size for.
520 BlockSize - A pointer to a caller allocated UINTN in which
521 the size of the block is returned
522 NumOfBlocks - a pointer to a caller allocated UINTN in which the
523 number of consecutive blocks starting with Lba is
524 returned. All blocks in this range have a size of
528 EFI_SUCCESS - The firmware volume was read successfully and
529 contents are in Buffer
533 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
535 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
537 return FvbGetLbaAddress (
549 FvbProtocolGetAttributes (
550 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
551 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
557 Retrieves Volume attributes. No polarity translations are done.
560 This - Calling context
561 Attributes - output buffer which contains attributes
564 EFI_SUCCESS - Successfully returns
568 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
570 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
572 return FvbGetVolumeAttributes (
581 FvbProtocolSetAttributes (
582 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
583 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
589 Sets Volume attributes. No polarity translations are done.
592 This - Calling context
593 Attributes - output buffer which contains attributes
596 EFI_SUCCESS - Successfully returns
600 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
602 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
604 return FvbSetVolumeAttributes (
613 FvbProtocolEraseBlocks (
614 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
622 The EraseBlock() function erases one or more blocks as denoted by the
623 variable argument list. The entire parameter list of blocks must be
624 verified prior to erasing any blocks. If a block is requested that does
625 not exist within the associated firmware volume (it has a larger index than
626 the last block of the firmware volume), the EraseBlock() function must
627 return EFI_INVALID_PARAMETER without modifying the contents of the firmware
631 This - Calling context
632 ... - Starting LBA followed by Number of Lba to erase.
633 a -1 to terminate the list.
636 EFI_SUCCESS - The erase request was successfully completed
637 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
638 EFI_DEVICE_ERROR - The block device is not functioning correctly and
639 could not be written. Firmware device may have been
644 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
645 EFI_FW_VOL_INSTANCE
*FwhInstance
;
652 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
654 Status
= GetFvbInstance (
659 ASSERT_EFI_ERROR (Status
);
661 NumOfBlocks
= FwhInstance
->NumOfBlocks
;
663 VA_START (args
, This
);
666 StartingLba
= VA_ARG (args
, EFI_LBA
);
667 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
671 NumOfLba
= VA_ARG (args
, UINTN
);
674 // Check input parameters
676 if ((NumOfLba
== 0) || ((StartingLba
+ NumOfLba
) > NumOfBlocks
)) {
678 return EFI_INVALID_PARAMETER
;
684 VA_START (args
, This
);
686 StartingLba
= VA_ARG (args
, EFI_LBA
);
687 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
691 NumOfLba
= VA_ARG (args
, UINTN
);
693 while (NumOfLba
> 0) {
694 Status
= QemuFlashEraseBlock (StartingLba
);
695 if (EFI_ERROR (Status
)) {
713 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
716 IN OUT UINTN
*NumBytes
,
724 Writes data beginning at Lba:Offset from FV. The write terminates either
725 when *NumBytes of data have been written, or when a block boundary is
726 reached. *NumBytes is updated to reflect the actual number of bytes
727 written. The write operation does not include erase. This routine will
728 attempt to write only the specified bytes. If the writes do not stick,
729 it will return an error.
732 This - Calling context
733 Lba - Block in which to begin write
734 Offset - Offset in the block at which to begin write
735 NumBytes - On input, indicates the requested write size. On
736 output, indicates the actual number of bytes
738 Buffer - Buffer containing source data for the write.
741 EFI_SUCCESS - The firmware volume was written successfully
742 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
743 NumBytes contains the total number of bytes
745 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
746 EFI_DEVICE_ERROR - The block device is not functioning correctly and
748 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
752 return QemuFlashWrite (
763 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
764 IN CONST EFI_LBA Lba
,
765 IN CONST UINTN Offset
,
766 IN OUT UINTN
*NumBytes
,
774 Reads data beginning at Lba:Offset from FV. The Read terminates either
775 when *NumBytes of data have been read, or when a block boundary is
776 reached. *NumBytes is updated to reflect the actual number of bytes
777 written. The write operation does not include erase. This routine will
778 attempt to write only the specified bytes. If the writes do not stick,
779 it will return an error.
782 This - Calling context
783 Lba - Block in which to begin Read
784 Offset - Offset in the block at which to begin Read
785 NumBytes - On input, indicates the requested write size. On
786 output, indicates the actual number of bytes Read
787 Buffer - Buffer containing source data for the Read.
790 EFI_SUCCESS - The firmware volume was read successfully and
791 contents are in Buffer
792 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
793 NumBytes contains the total number of bytes
795 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
796 EFI_DEVICE_ERROR - The block device is not functioning correctly and
798 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
802 return QemuFlashRead (
812 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
818 Check the integrity of firmware volume header
821 FwVolHeader - A pointer to a firmware volume header
824 EFI_SUCCESS - The firmware volume is consistent
825 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an
833 // Verify the header revision, header signature, length
834 // Length of FvBlock cannot be 2**64-1
835 // HeaderLength cannot be an odd number
837 if ((FwVolHeader
->Revision
!= EFI_FVH_REVISION
) ||
838 (FwVolHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
839 (FwVolHeader
->FvLength
== ((UINTN
)-1)) ||
840 ((FwVolHeader
->HeaderLength
& 0x01) != 0)
843 return EFI_NOT_FOUND
;
847 // Verify the header checksum
850 Checksum
= CalculateSum16 (
851 (UINT16
*)FwVolHeader
,
852 FwVolHeader
->HeaderLength
858 (UINT16
)(((UINTN
)FwVolHeader
->Checksum
+ 0x10000 - Checksum
) & 0xffff);
862 "FV@%p Checksum is 0x%x, expected 0x%x\n",
864 FwVolHeader
->Checksum
,
867 return EFI_NOT_FOUND
;
875 InitializeVariableFvHeader (
880 EFI_FIRMWARE_VOLUME_HEADER
*GoodFwVolHeader
;
881 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
887 (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)
888 PcdGet32 (PcdOvmfFlashNvStorageVariableBase
);
891 (FixedPcdGet32 (PcdFlashNvStorageVariableSize
) +
892 FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize
) +
893 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize
) +
894 FixedPcdGet32 (PcdOvmfFlashNvStorageEventLogSize
));
896 BlockSize
= PcdGet32 (PcdOvmfFirmwareBlockSize
);
898 Status
= ValidateFvHeader (FwVolHeader
);
899 if (!EFI_ERROR (Status
)) {
900 if ((FwVolHeader
->FvLength
!= Length
) ||
901 (FwVolHeader
->BlockMap
[0].Length
!= BlockSize
))
903 Status
= EFI_VOLUME_CORRUPTED
;
907 if (EFI_ERROR (Status
)) {
913 "Variable FV header is not valid. It will be reinitialized.\n"
917 // Get FvbInfo to provide in FwhInstance.
919 Status
= GetFvbInfo (Length
, &GoodFwVolHeader
);
920 ASSERT (!EFI_ERROR (Status
));
922 Start
= (UINTN
)(UINT8
*)FwVolHeader
- PcdGet32 (PcdOvmfFdBaseAddress
);
923 ASSERT (Start
% BlockSize
== 0 && Length
% BlockSize
== 0);
924 ASSERT (GoodFwVolHeader
->HeaderLength
<= BlockSize
);
927 // Erase all the blocks
929 for (Offset
= Start
; Offset
< Start
+ Length
; Offset
+= BlockSize
) {
930 Status
= QemuFlashEraseBlock (Offset
/ BlockSize
);
931 ASSERT_EFI_ERROR (Status
);
935 // Write good FV header
937 WriteLength
= GoodFwVolHeader
->HeaderLength
;
938 Status
= QemuFlashWrite (
942 (UINT8
*)GoodFwVolHeader
944 ASSERT_EFI_ERROR (Status
);
945 ASSERT (WriteLength
== GoodFwVolHeader
->HeaderLength
);
954 IN EFI_HANDLE ImageHandle
,
955 IN EFI_SYSTEM_TABLE
*SystemTable
961 This function does common initialization for FVB services
970 EFI_FW_VOL_INSTANCE
*FwhInstance
;
971 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
973 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
974 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
976 EFI_PHYSICAL_ADDRESS BaseAddress
;
979 RETURN_STATUS PcdStatus
;
981 if (EFI_ERROR (QemuFlashInitialize ())) {
983 // Return an error so image will be unloaded
987 "QEMU flash was not detected. Writable FVB is not being installed.\n"
989 return EFI_WRITE_PROTECTED
;
993 // Allocate runtime services data for global variable, which contains
994 // the private data of all firmware volume block instances
996 mFvbModuleGlobal
= AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL
));
997 ASSERT (mFvbModuleGlobal
!= NULL
);
999 BaseAddress
= (UINTN
)PcdGet32 (PcdOvmfFdBaseAddress
);
1000 Length
= PcdGet32 (PcdOvmfFirmwareFdSize
);
1002 Status
= InitializeVariableFvHeader ();
1003 if (EFI_ERROR (Status
)) {
1006 "QEMU Flash: Unable to initialize variable FV header\n"
1008 return EFI_WRITE_PROTECTED
;
1011 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)BaseAddress
;
1012 Status
= ValidateFvHeader (FwVolHeader
);
1013 if (EFI_ERROR (Status
)) {
1017 Status
= GetFvbInfo (Length
, &FwVolHeader
);
1018 if (EFI_ERROR (Status
)) {
1019 DEBUG ((DEBUG_INFO
, "EFI_ERROR (GetFvbInfo (Length, &FwVolHeader))\n"));
1020 return EFI_WRITE_PROTECTED
;
1024 BufferSize
= (sizeof (EFI_FW_VOL_INSTANCE
) +
1025 FwVolHeader
->HeaderLength
-
1026 sizeof (EFI_FIRMWARE_VOLUME_HEADER
)
1028 mFvbModuleGlobal
->FvInstance
= AllocateRuntimePool (BufferSize
);
1029 ASSERT (mFvbModuleGlobal
->FvInstance
!= NULL
);
1031 FwhInstance
= mFvbModuleGlobal
->FvInstance
;
1033 mFvbModuleGlobal
->NumFv
= 0;
1037 (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)
1038 PcdGet32 (PcdOvmfFlashNvStorageVariableBase
);
1040 FwhInstance
->FvBase
= (UINTN
)BaseAddress
;
1043 (UINTN
*)&(FwhInstance
->VolumeHeader
),
1044 (UINTN
*)FwVolHeader
,
1045 FwVolHeader
->HeaderLength
1047 FwVolHeader
= &(FwhInstance
->VolumeHeader
);
1051 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
;
1052 PtrBlockMapEntry
->NumBlocks
!= 0;
1056 // Get the maximum size of a block.
1058 if (MaxLbaSize
< PtrBlockMapEntry
->Length
) {
1059 MaxLbaSize
= PtrBlockMapEntry
->Length
;
1062 NumOfBlocks
= NumOfBlocks
+ PtrBlockMapEntry
->NumBlocks
;
1066 // The total number of blocks in the FV.
1068 FwhInstance
->NumOfBlocks
= NumOfBlocks
;
1071 // Add a FVB Protocol Instance
1073 FvbDevice
= AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE
));
1074 ASSERT (FvbDevice
!= NULL
);
1076 CopyMem (FvbDevice
, &mFvbDeviceTemplate
, sizeof (EFI_FW_VOL_BLOCK_DEVICE
));
1078 FvbDevice
->Instance
= mFvbModuleGlobal
->NumFv
;
1079 mFvbModuleGlobal
->NumFv
++;
1082 // Set up the devicepath
1084 if (FwVolHeader
->ExtHeaderOffset
== 0) {
1085 FV_MEMMAP_DEVICE_PATH
*FvMemmapDevicePath
;
1088 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
1090 FvMemmapDevicePath
= AllocateCopyPool (
1091 sizeof (FV_MEMMAP_DEVICE_PATH
),
1092 &mFvMemmapDevicePathTemplate
1094 FvMemmapDevicePath
->MemMapDevPath
.StartingAddress
= BaseAddress
;
1095 FvMemmapDevicePath
->MemMapDevPath
.EndingAddress
=
1096 BaseAddress
+ FwVolHeader
->FvLength
- 1;
1097 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)FvMemmapDevicePath
;
1099 FV_PIWG_DEVICE_PATH
*FvPiwgDevicePath
;
1101 FvPiwgDevicePath
= AllocateCopyPool (
1102 sizeof (FV_PIWG_DEVICE_PATH
),
1103 &mFvPIWGDevicePathTemplate
1106 &FvPiwgDevicePath
->FvDevPath
.FvName
,
1107 (GUID
*)(UINTN
)(BaseAddress
+ FwVolHeader
->ExtHeaderOffset
)
1109 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)FvPiwgDevicePath
;
1113 // Module type specific hook.
1115 InstallProtocolInterfaces (FvbDevice
);
1117 MarkIoMemoryRangeForRuntimeAccess (BaseAddress
, Length
);
1119 SetPcdFlashNvStorageBaseAddresses ();
1121 FwhInstance
= (EFI_FW_VOL_INSTANCE
*)
1123 (UINTN
)((UINT8
*)FwhInstance
) + FwVolHeader
->HeaderLength
+
1124 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
1128 // Module type specific hook.
1130 InstallVirtualAddressChangeHandler ();
1132 PcdStatus
= PcdSetBoolS (PcdOvmfFlashVariablesEnable
, TRUE
);
1133 ASSERT_RETURN_ERROR (PcdStatus
);