3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 // The package level header files this module uses
29 // The protocols, PPI and GUID defintions for this module
31 #include <Guid/EventGroup.h>
32 #include <Protocol/FirmwareVolumeBlock.h>
33 #include <Protocol/DevicePath.h>
36 // The Library classes this module consumes
38 #include <Library/UefiLib.h>
39 #include <Library/UefiDriverEntryPoint.h>
40 #include <Library/BaseLib.h>
41 #include <Library/DxeServicesTableLib.h>
42 #include <Library/UefiRuntimeLib.h>
43 #include <Library/DebugLib.h>
44 #include <Library/BaseMemoryLib.h>
45 #include <Library/MemoryAllocationLib.h>
46 #include <Library/UefiBootServicesTableLib.h>
47 #include <Library/DevicePathLib.h>
49 #include "FwBlockService.h"
50 #include "QemuFlash.h"
52 #define EFI_FVB2_STATUS \
53 (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
55 ESAL_FWB_GLOBAL
*mFvbModuleGlobal
;
57 FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate
= {
63 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
)),
64 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
) >> 8)
68 (EFI_PHYSICAL_ADDRESS
) 0,
69 (EFI_PHYSICAL_ADDRESS
) 0,
73 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
75 END_DEVICE_PATH_LENGTH
,
81 FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate
= {
87 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
)),
88 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
) >> 8)
95 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
97 END_DEVICE_PATH_LENGTH
,
103 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate
= {
104 FVB_DEVICE_SIGNATURE
,
108 FvbProtocolGetAttributes
,
109 FvbProtocolSetAttributes
,
110 FvbProtocolGetPhysicalAddress
,
111 FvbProtocolGetBlockSize
,
114 FvbProtocolEraseBlocks
,
123 FvbVirtualddressChangeEvent (
131 Fixup internal data so that EFI and SAL can be call in virtual mode.
132 Call the passed in Child Notify event and convert the mFvbModuleGlobal
133 date items to there virtual address.
137 (Standard EFI notify event - EFI_EVENT_NOTIFY)
145 EFI_FW_VOL_INSTANCE
*FwhInstance
;
148 FwhInstance
= mFvbModuleGlobal
->FvInstance
;
149 EfiConvertPointer (0x0, (VOID
**) &mFvbModuleGlobal
->FvInstance
);
152 // Convert the base address of all the instances
155 while (Index
< mFvbModuleGlobal
->NumFv
) {
156 EfiConvertPointer (0x0, (VOID
**) &FwhInstance
->FvBase
);
157 FwhInstance
= (EFI_FW_VOL_INSTANCE
*)
159 (UINTN
) ((UINT8
*) FwhInstance
) +
160 FwhInstance
->VolumeHeader
.HeaderLength
+
161 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
166 EfiConvertPointer (0x0, (VOID
**) &mFvbModuleGlobal
);
167 QemuFlashConvertPointers ();
173 IN ESAL_FWB_GLOBAL
*Global
,
174 OUT EFI_FW_VOL_INSTANCE
**FwhInstance
179 Retrieves the physical address of a memory mapped FV
182 Instance - The FV instance whose base address is going to be
184 Global - Pointer to ESAL_FWB_GLOBAL that contains all
186 FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure
189 EFI_SUCCESS - Successfully returns
190 EFI_INVALID_PARAMETER - Instance not found
194 EFI_FW_VOL_INSTANCE
*FwhRecord
;
197 if (Instance
>= Global
->NumFv
) {
198 return EFI_INVALID_PARAMETER
;
201 // Find the right instance of the FVB private data
203 FwhRecord
= Global
->FvInstance
;
204 while (Instance
> 0) {
205 FwhRecord
= (EFI_FW_VOL_INSTANCE
*)
207 (UINTN
) ((UINT8
*) FwhRecord
) + FwhRecord
->VolumeHeader
.HeaderLength
+
208 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
213 *FwhInstance
= FwhRecord
;
219 FvbGetPhysicalAddress (
221 OUT EFI_PHYSICAL_ADDRESS
*Address
,
222 IN ESAL_FWB_GLOBAL
*Global
227 Retrieves the physical address of a memory mapped FV
230 Instance - The FV instance whose base address is going to be
232 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
233 that on successful return, contains the base
234 address of the firmware volume.
235 Global - Pointer to ESAL_FWB_GLOBAL that contains all
239 EFI_SUCCESS - Successfully returns
240 EFI_INVALID_PARAMETER - Instance not found
244 EFI_FW_VOL_INSTANCE
*FwhInstance
;
248 // Find the right instance of the FVB private data
250 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
251 ASSERT_EFI_ERROR (Status
);
252 *Address
= FwhInstance
->FvBase
;
258 FvbGetVolumeAttributes (
260 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
261 IN ESAL_FWB_GLOBAL
*Global
266 Retrieves attributes, insures positive polarity of attribute bits, returns
267 resulting attributes in output parameter
270 Instance - The FV instance whose attributes is going to be
272 Attributes - Output buffer which contains attributes
273 Global - Pointer to ESAL_FWB_GLOBAL that contains all
277 EFI_SUCCESS - Successfully returns
278 EFI_INVALID_PARAMETER - Instance not found
282 EFI_FW_VOL_INSTANCE
*FwhInstance
;
286 // Find the right instance of the FVB private data
288 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
289 ASSERT_EFI_ERROR (Status
);
290 *Attributes
= FwhInstance
->VolumeHeader
.Attributes
;
299 OUT UINTN
*LbaAddress
,
300 OUT UINTN
*LbaLength
,
301 OUT UINTN
*NumOfBlocks
,
302 IN ESAL_FWB_GLOBAL
*Global
307 Retrieves the starting address of an LBA in an FV
310 Instance - The FV instance which the Lba belongs to
311 Lba - The logical block address
312 LbaAddress - On output, contains the physical starting address
314 LbaLength - On output, contains the length of the block
315 NumOfBlocks - A pointer to a caller allocated UINTN in which the
316 number of consecutive blocks starting with Lba is
317 returned. All blocks in this range have a size of
319 Global - Pointer to ESAL_FWB_GLOBAL that contains all
323 EFI_SUCCESS - Successfully returns
324 EFI_INVALID_PARAMETER - Instance not found
333 EFI_FW_VOL_INSTANCE
*FwhInstance
;
334 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
338 // Find the right instance of the FVB private data
340 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
341 ASSERT_EFI_ERROR (Status
);
345 BlockMap
= &(FwhInstance
->VolumeHeader
.BlockMap
[0]);
348 // Parse the blockmap of the FV to find which map entry the Lba belongs to
351 NumBlocks
= BlockMap
->NumBlocks
;
352 BlockLength
= BlockMap
->Length
;
354 if (NumBlocks
== 0 || BlockLength
== 0) {
355 return EFI_INVALID_PARAMETER
;
358 NextLba
= StartLba
+ NumBlocks
;
361 // The map entry found
363 if (Lba
>= StartLba
&& Lba
< NextLba
) {
364 Offset
= Offset
+ (UINTN
) MultU64x32 ((Lba
- StartLba
), BlockLength
);
365 if (LbaAddress
!= NULL
) {
366 *LbaAddress
= FwhInstance
->FvBase
+ Offset
;
369 if (LbaLength
!= NULL
) {
370 *LbaLength
= BlockLength
;
373 if (NumOfBlocks
!= NULL
) {
374 *NumOfBlocks
= (UINTN
) (NextLba
- Lba
);
381 Offset
= Offset
+ NumBlocks
* BlockLength
;
387 FvbSetVolumeAttributes (
389 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
390 IN ESAL_FWB_GLOBAL
*Global
395 Modifies the current settings of the firmware volume according to the
396 input parameter, and returns the new setting of the volume
399 Instance - The FV instance whose attributes is going to be
401 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
402 containing the desired firmware volume settings.
403 On successful return, it contains the new settings
404 of the firmware volume
405 Global - Pointer to ESAL_FWB_GLOBAL that contains all
409 EFI_SUCCESS - Successfully returns
410 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
411 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
412 in conflict with the capabilities as declared in
413 the firmware volume header
417 EFI_FW_VOL_INSTANCE
*FwhInstance
;
418 EFI_FVB_ATTRIBUTES_2 OldAttributes
;
419 EFI_FVB_ATTRIBUTES_2
*AttribPtr
;
424 EFI_FVB_ATTRIBUTES_2 UnchangedAttributes
;
427 // Find the right instance of the FVB private data
429 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
430 ASSERT_EFI_ERROR (Status
);
433 (EFI_FVB_ATTRIBUTES_2
*) &(FwhInstance
->VolumeHeader
.Attributes
);
434 OldAttributes
= *AttribPtr
;
435 Capabilities
= OldAttributes
& (EFI_FVB2_READ_DISABLED_CAP
| \
436 EFI_FVB2_READ_ENABLED_CAP
| \
437 EFI_FVB2_WRITE_DISABLED_CAP
| \
438 EFI_FVB2_WRITE_ENABLED_CAP
| \
441 OldStatus
= OldAttributes
& EFI_FVB2_STATUS
;
442 NewStatus
= *Attributes
& EFI_FVB2_STATUS
;
444 UnchangedAttributes
= EFI_FVB2_READ_DISABLED_CAP
| \
445 EFI_FVB2_READ_ENABLED_CAP
| \
446 EFI_FVB2_WRITE_DISABLED_CAP
| \
447 EFI_FVB2_WRITE_ENABLED_CAP
| \
448 EFI_FVB2_LOCK_CAP
| \
449 EFI_FVB2_STICKY_WRITE
| \
450 EFI_FVB2_MEMORY_MAPPED
| \
451 EFI_FVB2_ERASE_POLARITY
| \
452 EFI_FVB2_READ_LOCK_CAP
| \
453 EFI_FVB2_WRITE_LOCK_CAP
| \
457 // Some attributes of FV is read only can *not* be set
459 if ((OldAttributes
& UnchangedAttributes
) ^
460 (*Attributes
& UnchangedAttributes
)) {
461 return EFI_INVALID_PARAMETER
;
464 // If firmware volume is locked, no status bit can be updated
466 if (OldAttributes
& EFI_FVB2_LOCK_STATUS
) {
467 if (OldStatus
^ NewStatus
) {
468 return EFI_ACCESS_DENIED
;
474 if ((Capabilities
& EFI_FVB2_READ_DISABLED_CAP
) == 0) {
475 if ((NewStatus
& EFI_FVB2_READ_STATUS
) == 0) {
476 return EFI_INVALID_PARAMETER
;
482 if ((Capabilities
& EFI_FVB2_READ_ENABLED_CAP
) == 0) {
483 if (NewStatus
& EFI_FVB2_READ_STATUS
) {
484 return EFI_INVALID_PARAMETER
;
488 // Test write disable
490 if ((Capabilities
& EFI_FVB2_WRITE_DISABLED_CAP
) == 0) {
491 if ((NewStatus
& EFI_FVB2_WRITE_STATUS
) == 0) {
492 return EFI_INVALID_PARAMETER
;
498 if ((Capabilities
& EFI_FVB2_WRITE_ENABLED_CAP
) == 0) {
499 if (NewStatus
& EFI_FVB2_WRITE_STATUS
) {
500 return EFI_INVALID_PARAMETER
;
506 if ((Capabilities
& EFI_FVB2_LOCK_CAP
) == 0) {
507 if (NewStatus
& EFI_FVB2_LOCK_STATUS
) {
508 return EFI_INVALID_PARAMETER
;
512 *AttribPtr
= (*AttribPtr
) & (0xFFFFFFFF & (~EFI_FVB2_STATUS
));
513 *AttribPtr
= (*AttribPtr
) | NewStatus
;
514 *Attributes
= *AttribPtr
;
524 FvbProtocolGetPhysicalAddress (
525 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
526 OUT EFI_PHYSICAL_ADDRESS
*Address
532 Retrieves the physical address of the device.
536 This - Calling context
537 Address - Output buffer containing the address.
540 EFI_SUCCESS - Successfully returns
544 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
546 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
548 return FvbGetPhysicalAddress (FvbDevice
->Instance
, Address
,
554 FvbProtocolGetBlockSize (
555 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
556 IN CONST EFI_LBA Lba
,
557 OUT UINTN
*BlockSize
,
558 OUT UINTN
*NumOfBlocks
563 Retrieve the size of a logical block
566 This - Calling context
567 Lba - Indicates which block to return the size for.
568 BlockSize - A pointer to a caller allocated UINTN in which
569 the size of the block is returned
570 NumOfBlocks - a pointer to a caller allocated UINTN in which the
571 number of consecutive blocks starting with Lba is
572 returned. All blocks in this range have a size of
576 EFI_SUCCESS - The firmware volume was read successfully and
577 contents are in Buffer
581 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
583 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
585 return FvbGetLbaAddress (
597 FvbProtocolGetAttributes (
598 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
599 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
604 Retrieves Volume attributes. No polarity translations are done.
607 This - Calling context
608 Attributes - output buffer which contains attributes
611 EFI_SUCCESS - Successfully returns
615 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
617 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
619 return FvbGetVolumeAttributes (FvbDevice
->Instance
, Attributes
,
625 FvbProtocolSetAttributes (
626 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
627 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
632 Sets Volume attributes. No polarity translations are done.
635 This - Calling context
636 Attributes - output buffer which contains attributes
639 EFI_SUCCESS - Successfully returns
643 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
645 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
647 return FvbSetVolumeAttributes (FvbDevice
->Instance
, Attributes
,
653 FvbProtocolEraseBlocks (
654 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
661 The EraseBlock() function erases one or more blocks as denoted by the
662 variable argument list. The entire parameter list of blocks must be
663 verified prior to erasing any blocks. If a block is requested that does
664 not exist within the associated firmware volume (it has a larger index than
665 the last block of the firmware volume), the EraseBlock() function must
666 return EFI_INVALID_PARAMETER without modifying the contents of the firmware
670 This - Calling context
671 ... - Starting LBA followed by Number of Lba to erase.
672 a -1 to terminate the list.
675 EFI_SUCCESS - The erase request was successfully completed
676 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
677 EFI_DEVICE_ERROR - The block device is not functioning correctly and
678 could not be written. Firmware device may have been
683 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
684 EFI_FW_VOL_INSTANCE
*FwhInstance
;
691 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
693 Status
= GetFvbInstance (FvbDevice
->Instance
, mFvbModuleGlobal
,
695 ASSERT_EFI_ERROR (Status
);
697 NumOfBlocks
= FwhInstance
->NumOfBlocks
;
699 VA_START (args
, This
);
702 StartingLba
= VA_ARG (args
, EFI_LBA
);
703 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
707 NumOfLba
= VA_ARG (args
, UINT32
);
710 // Check input parameters
712 if ((NumOfLba
== 0) || ((StartingLba
+ NumOfLba
) > NumOfBlocks
)) {
714 return EFI_INVALID_PARAMETER
;
720 VA_START (args
, This
);
722 StartingLba
= VA_ARG (args
, EFI_LBA
);
723 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
727 NumOfLba
= VA_ARG (args
, UINT32
);
729 while (NumOfLba
> 0) {
730 Status
= QemuFlashEraseBlock (StartingLba
);
731 if (EFI_ERROR (Status
)) {
750 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
753 IN OUT UINTN
*NumBytes
,
760 Writes data beginning at Lba:Offset from FV. The write terminates either
761 when *NumBytes of data have been written, or when a block boundary is
762 reached. *NumBytes is updated to reflect the actual number of bytes
763 written. The write opertion does not include erase. This routine will
764 attempt to write only the specified bytes. If the writes do not stick,
765 it will return an error.
768 This - Calling context
769 Lba - Block in which to begin write
770 Offset - Offset in the block at which to begin write
771 NumBytes - On input, indicates the requested write size. On
772 output, indicates the actual number of bytes
774 Buffer - Buffer containing source data for the write.
777 EFI_SUCCESS - The firmware volume was written successfully
778 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
779 NumBytes contains the total number of bytes
781 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
782 EFI_DEVICE_ERROR - The block device is not functioning correctly and
784 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
788 return QemuFlashWrite ((EFI_LBA
)Lba
, (UINTN
)Offset
, NumBytes
,
795 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
796 IN CONST EFI_LBA Lba
,
797 IN CONST UINTN Offset
,
798 IN OUT UINTN
*NumBytes
,
805 Reads data beginning at Lba:Offset from FV. The Read terminates either
806 when *NumBytes of data have been read, or when a block boundary is
807 reached. *NumBytes is updated to reflect the actual number of bytes
808 written. The write opertion does not include erase. This routine will
809 attempt to write only the specified bytes. If the writes do not stick,
810 it will return an error.
813 This - Calling context
814 Lba - Block in which to begin Read
815 Offset - Offset in the block at which to begin Read
816 NumBytes - On input, indicates the requested write size. On
817 output, indicates the actual number of bytes Read
818 Buffer - Buffer containing source data for the Read.
821 EFI_SUCCESS - The firmware volume was read successfully and
822 contents are in Buffer
823 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
824 NumBytes contains the total number of bytes
826 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
827 EFI_DEVICE_ERROR - The block device is not functioning correctly and
829 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
833 return QemuFlashRead ((EFI_LBA
)Lba
, (UINTN
)Offset
, NumBytes
,
839 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
844 Check the integrity of firmware volume header
847 FwVolHeader - A pointer to a firmware volume header
850 EFI_SUCCESS - The firmware volume is consistent
851 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an
859 // Verify the header revision, header signature, length
860 // Length of FvBlock cannot be 2**64-1
861 // HeaderLength cannot be an odd number
863 if ((FwVolHeader
->Revision
!= EFI_FVH_REVISION
) ||
864 (FwVolHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
865 (FwVolHeader
->FvLength
== ((UINTN
) -1)) ||
866 ((FwVolHeader
->HeaderLength
& 0x01) != 0)
868 return EFI_NOT_FOUND
;
872 // Verify the header checksum
875 Checksum
= CalculateSum16 ((UINT16
*) FwVolHeader
,
876 FwVolHeader
->HeaderLength
);
881 (UINT16
) (((UINTN
) FwVolHeader
->Checksum
+ 0x10000 - Checksum
) & 0xffff);
883 DEBUG ((EFI_D_INFO
, "FV@%p Checksum is 0x%x, expected 0x%x\n",
884 FwVolHeader
, FwVolHeader
->Checksum
, Expected
));
885 return EFI_NOT_FOUND
;
893 MarkMemoryRangeForRuntimeAccess (
894 EFI_PHYSICAL_ADDRESS BaseAddress
,
901 // Mark flash region as runtime memory
903 Status
= gDS
->RemoveMemorySpace (
908 Status
= gDS
->AddMemorySpace (
909 EfiGcdMemoryTypeSystemMemory
,
912 EFI_MEMORY_UC
| EFI_MEMORY_RUNTIME
914 ASSERT_EFI_ERROR (Status
);
916 Status
= gBS
->AllocatePages (
918 EfiRuntimeServicesData
,
919 EFI_SIZE_TO_PAGES (Length
),
922 ASSERT_EFI_ERROR (Status
);
929 InitializeVariableFvHeader (
934 EFI_FIRMWARE_VOLUME_HEADER
*GoodFwVolHeader
;
935 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
941 (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
)
942 PcdGet32 (PcdOvmfFlashNvStorageVariableBase
);
945 (FixedPcdGet32 (PcdFlashNvStorageVariableSize
) +
946 FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize
) +
947 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize
) +
948 FixedPcdGet32 (PcdOvmfFlashNvStorageEventLogSize
));
950 BlockSize
= PcdGet32 (PcdOvmfFirmwareBlockSize
);
952 Status
= ValidateFvHeader (FwVolHeader
);
953 if (!EFI_ERROR (Status
)) {
954 if (FwVolHeader
->FvLength
!= Length
||
955 FwVolHeader
->BlockMap
[0].Length
!= BlockSize
) {
956 Status
= EFI_VOLUME_CORRUPTED
;
959 if (EFI_ERROR (Status
)) {
964 "Variable FV header is not valid. It will be reinitialized.\n"));
967 // Get FvbInfo to provide in FwhInstance.
969 Status
= GetFvbInfo (Length
, &GoodFwVolHeader
);
970 ASSERT (!EFI_ERROR (Status
));
972 Start
= (UINTN
)(UINT8
*) FwVolHeader
- PcdGet32 (PcdOvmfFdBaseAddress
);
973 ASSERT (Start
% BlockSize
== 0 && Length
% BlockSize
== 0);
974 ASSERT (GoodFwVolHeader
->HeaderLength
<= BlockSize
);
977 // Erase all the blocks
979 for (Offset
= Start
; Offset
< Start
+ Length
; Offset
+= BlockSize
) {
980 Status
= QemuFlashEraseBlock (Offset
/ BlockSize
);
981 ASSERT_EFI_ERROR (Status
);
985 // Write good FV header
987 WriteLength
= GoodFwVolHeader
->HeaderLength
;
988 Status
= QemuFlashWrite (
992 (UINT8
*) GoodFwVolHeader
);
993 ASSERT_EFI_ERROR (Status
);
994 ASSERT (WriteLength
== GoodFwVolHeader
->HeaderLength
);
1003 IN EFI_HANDLE ImageHandle
,
1004 IN EFI_SYSTEM_TABLE
*SystemTable
1008 Routine Description:
1009 This function does common initialization for FVB services
1018 EFI_FW_VOL_INSTANCE
*FwhInstance
;
1019 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1021 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
1022 EFI_HANDLE FwbHandle
;
1023 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1024 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*OldFwbInterface
;
1026 EFI_PHYSICAL_ADDRESS BaseAddress
;
1029 EFI_EVENT VirtualAddressChangeEvent
;
1031 if (EFI_ERROR (QemuFlashInitialize ())) {
1033 // Return an error so image will be unloaded
1036 "QEMU flash was not detected. Writable FVB is not being installed.\n"));
1037 return EFI_WRITE_PROTECTED
;
1041 // Allocate runtime services data for global variable, which contains
1042 // the private data of all firmware volume block instances
1044 mFvbModuleGlobal
= AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL
));
1045 ASSERT (mFvbModuleGlobal
!= NULL
);
1047 BaseAddress
= (UINTN
) PcdGet32 (PcdOvmfFdBaseAddress
);
1048 Length
= PcdGet32 (PcdOvmfFirmwareFdSize
);
1050 Status
= InitializeVariableFvHeader ();
1051 if (EFI_ERROR (Status
)) {
1053 "QEMU Flash: Unable to initialize variable FV header\n"));
1054 return EFI_WRITE_PROTECTED
;
1057 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) BaseAddress
;
1058 Status
= ValidateFvHeader (FwVolHeader
);
1059 if (EFI_ERROR (Status
)) {
1063 Status
= GetFvbInfo (Length
, &FwVolHeader
);
1064 if (EFI_ERROR (Status
)) {
1065 DEBUG ((EFI_D_INFO
, "EFI_ERROR (GetFvbInfo (Length, &FwVolHeader))\n"));
1066 return EFI_WRITE_PROTECTED
;
1070 BufferSize
= (sizeof (EFI_FW_VOL_INSTANCE
) +
1071 FwVolHeader
->HeaderLength
-
1072 sizeof (EFI_FIRMWARE_VOLUME_HEADER
)
1074 mFvbModuleGlobal
->FvInstance
= AllocateRuntimePool (BufferSize
);
1075 ASSERT (mFvbModuleGlobal
->FvInstance
!= NULL
);
1077 FwhInstance
= mFvbModuleGlobal
->FvInstance
;
1079 mFvbModuleGlobal
->NumFv
= 0;
1083 (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
)
1084 PcdGet32 (PcdOvmfFlashNvStorageVariableBase
);
1086 FwhInstance
->FvBase
= (UINTN
) BaseAddress
;
1088 CopyMem ((UINTN
*) &(FwhInstance
->VolumeHeader
), (UINTN
*) FwVolHeader
,
1089 FwVolHeader
->HeaderLength
);
1090 FwVolHeader
= &(FwhInstance
->VolumeHeader
);
1094 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
;
1095 PtrBlockMapEntry
->NumBlocks
!= 0;
1096 PtrBlockMapEntry
++) {
1098 // Get the maximum size of a block.
1100 if (MaxLbaSize
< PtrBlockMapEntry
->Length
) {
1101 MaxLbaSize
= PtrBlockMapEntry
->Length
;
1104 NumOfBlocks
= NumOfBlocks
+ PtrBlockMapEntry
->NumBlocks
;
1108 // The total number of blocks in the FV.
1110 FwhInstance
->NumOfBlocks
= NumOfBlocks
;
1113 // Add a FVB Protocol Instance
1115 FvbDevice
= AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE
));
1116 ASSERT (FvbDevice
!= NULL
);
1118 CopyMem (FvbDevice
, &mFvbDeviceTemplate
, sizeof (EFI_FW_VOL_BLOCK_DEVICE
));
1120 FvbDevice
->Instance
= mFvbModuleGlobal
->NumFv
;
1121 mFvbModuleGlobal
->NumFv
++;
1124 // Set up the devicepath
1126 if (FwVolHeader
->ExtHeaderOffset
== 0) {
1127 FV_MEMMAP_DEVICE_PATH
*FvMemmapDevicePath
;
1130 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
1132 FvMemmapDevicePath
= AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH
),
1133 &mFvMemmapDevicePathTemplate
);
1134 FvMemmapDevicePath
->MemMapDevPath
.StartingAddress
= BaseAddress
;
1135 FvMemmapDevicePath
->MemMapDevPath
.EndingAddress
=
1136 BaseAddress
+ FwVolHeader
->FvLength
- 1;
1137 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)FvMemmapDevicePath
;
1139 FV_PIWG_DEVICE_PATH
*FvPiwgDevicePath
;
1141 FvPiwgDevicePath
= AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH
),
1142 &mFvPIWGDevicePathTemplate
);
1144 &FvPiwgDevicePath
->FvDevPath
.FvName
,
1145 (GUID
*)(UINTN
)(BaseAddress
+ FwVolHeader
->ExtHeaderOffset
)
1147 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)FvPiwgDevicePath
;
1151 // Find a handle with a matching device path that has supports FW Block
1154 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid
,
1155 &FvbDevice
->DevicePath
, &FwbHandle
);
1156 if (EFI_ERROR (Status
)) {
1158 // LocateDevicePath fails so install a new interface and device path
1161 DEBUG ((EFI_D_INFO
, "Installing QEMU flash FVB\n"));
1162 Status
= gBS
->InstallMultipleProtocolInterfaces (
1164 &gEfiFirmwareVolumeBlockProtocolGuid
,
1165 &FvbDevice
->FwVolBlockInstance
,
1166 &gEfiDevicePathProtocolGuid
,
1167 FvbDevice
->DevicePath
,
1170 ASSERT_EFI_ERROR (Status
);
1171 } else if (IsDevicePathEnd (FvbDevice
->DevicePath
)) {
1173 // Device already exists, so reinstall the FVB protocol
1175 Status
= gBS
->HandleProtocol (
1177 &gEfiFirmwareVolumeBlockProtocolGuid
,
1178 (VOID
**)&OldFwbInterface
1180 ASSERT_EFI_ERROR (Status
);
1182 DEBUG ((EFI_D_INFO
, "Reinstalling FVB for QEMU flash region\n"));
1183 Status
= gBS
->ReinstallProtocolInterface (
1185 &gEfiFirmwareVolumeBlockProtocolGuid
,
1187 &FvbDevice
->FwVolBlockInstance
1189 ASSERT_EFI_ERROR (Status
);
1192 // There was a FVB protocol on an End Device Path node
1197 MarkMemoryRangeForRuntimeAccess (BaseAddress
, Length
);
1200 // Set several PCD values to point to flash
1203 PcdFlashNvStorageVariableBase64
,
1204 (UINTN
) PcdGet32 (PcdOvmfFlashNvStorageVariableBase
)
1207 PcdFlashNvStorageFtwWorkingBase
,
1208 PcdGet32 (PcdOvmfFlashNvStorageFtwWorkingBase
)
1211 PcdFlashNvStorageFtwSpareBase
,
1212 PcdGet32 (PcdOvmfFlashNvStorageFtwSpareBase
)
1215 FwhInstance
= (EFI_FW_VOL_INSTANCE
*)
1217 (UINTN
) ((UINT8
*) FwhInstance
) + FwVolHeader
->HeaderLength
+
1218 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
1221 VirtualAddressChangeEvent
= NULL
;
1222 Status
= gBS
->CreateEventEx (
1225 FvbVirtualddressChangeEvent
,
1227 &gEfiEventVirtualAddressChangeGuid
,
1228 &VirtualAddressChangeEvent
1230 ASSERT_EFI_ERROR (Status
);
1232 PcdSetBool (PcdOvmfFlashVariablesEnable
, TRUE
);