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 protocols, PPI and GUID defintions for this module
26 #include <Protocol/DevicePath.h>
27 #include <Protocol/FirmwareVolumeBlock.h>
30 // The Library classes this module consumes
32 #include <Library/BaseLib.h>
33 #include <Library/BaseMemoryLib.h>
34 #include <Library/DebugLib.h>
35 #include <Library/DevicePathLib.h>
36 #include <Library/DxeServicesTableLib.h>
37 #include <Library/MemoryAllocationLib.h>
38 #include <Library/UefiBootServicesTableLib.h>
40 #include "FwBlockService.h"
41 #include "QemuFlash.h"
43 #define EFI_FVB2_STATUS \
44 (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
46 ESAL_FWB_GLOBAL
*mFvbModuleGlobal
;
48 FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate
= {
54 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
)),
55 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
) >> 8)
59 (EFI_PHYSICAL_ADDRESS
) 0,
60 (EFI_PHYSICAL_ADDRESS
) 0,
64 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
66 END_DEVICE_PATH_LENGTH
,
72 FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate
= {
78 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
)),
79 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
) >> 8)
86 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
88 END_DEVICE_PATH_LENGTH
,
94 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate
= {
99 FvbProtocolGetAttributes
,
100 FvbProtocolSetAttributes
,
101 FvbProtocolGetPhysicalAddress
,
102 FvbProtocolGetBlockSize
,
105 FvbProtocolEraseBlocks
,
114 IN ESAL_FWB_GLOBAL
*Global
,
115 OUT EFI_FW_VOL_INSTANCE
**FwhInstance
120 Retrieves the physical address of a memory mapped FV
123 Instance - The FV instance whose base address is going to be
125 Global - Pointer to ESAL_FWB_GLOBAL that contains all
127 FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure
130 EFI_SUCCESS - Successfully returns
131 EFI_INVALID_PARAMETER - Instance not found
135 EFI_FW_VOL_INSTANCE
*FwhRecord
;
138 if (Instance
>= Global
->NumFv
) {
139 return EFI_INVALID_PARAMETER
;
142 // Find the right instance of the FVB private data
144 FwhRecord
= Global
->FvInstance
;
145 while (Instance
> 0) {
146 FwhRecord
= (EFI_FW_VOL_INSTANCE
*)
148 (UINTN
) ((UINT8
*) FwhRecord
) + FwhRecord
->VolumeHeader
.HeaderLength
+
149 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
154 *FwhInstance
= FwhRecord
;
160 FvbGetPhysicalAddress (
162 OUT EFI_PHYSICAL_ADDRESS
*Address
,
163 IN ESAL_FWB_GLOBAL
*Global
168 Retrieves the physical address of a memory mapped FV
171 Instance - The FV instance whose base address is going to be
173 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
174 that on successful return, contains the base
175 address of the firmware volume.
176 Global - Pointer to ESAL_FWB_GLOBAL that contains all
180 EFI_SUCCESS - Successfully returns
181 EFI_INVALID_PARAMETER - Instance not found
185 EFI_FW_VOL_INSTANCE
*FwhInstance
;
189 // Find the right instance of the FVB private data
191 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
192 ASSERT_EFI_ERROR (Status
);
193 *Address
= FwhInstance
->FvBase
;
199 FvbGetVolumeAttributes (
201 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
202 IN ESAL_FWB_GLOBAL
*Global
207 Retrieves attributes, insures positive polarity of attribute bits, returns
208 resulting attributes in output parameter
211 Instance - The FV instance whose attributes is going to be
213 Attributes - Output buffer which contains attributes
214 Global - Pointer to ESAL_FWB_GLOBAL that contains all
218 EFI_SUCCESS - Successfully returns
219 EFI_INVALID_PARAMETER - Instance not found
223 EFI_FW_VOL_INSTANCE
*FwhInstance
;
227 // Find the right instance of the FVB private data
229 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
230 ASSERT_EFI_ERROR (Status
);
231 *Attributes
= FwhInstance
->VolumeHeader
.Attributes
;
240 OUT UINTN
*LbaAddress
,
241 OUT UINTN
*LbaLength
,
242 OUT UINTN
*NumOfBlocks
,
243 IN ESAL_FWB_GLOBAL
*Global
248 Retrieves the starting address of an LBA in an FV
251 Instance - The FV instance which the Lba belongs to
252 Lba - The logical block address
253 LbaAddress - On output, contains the physical starting address
255 LbaLength - On output, contains the length of the block
256 NumOfBlocks - A pointer to a caller allocated UINTN in which the
257 number of consecutive blocks starting with Lba is
258 returned. All blocks in this range have a size of
260 Global - Pointer to ESAL_FWB_GLOBAL that contains all
264 EFI_SUCCESS - Successfully returns
265 EFI_INVALID_PARAMETER - Instance not found
274 EFI_FW_VOL_INSTANCE
*FwhInstance
;
275 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
279 // Find the right instance of the FVB private data
281 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
282 ASSERT_EFI_ERROR (Status
);
286 BlockMap
= &(FwhInstance
->VolumeHeader
.BlockMap
[0]);
289 // Parse the blockmap of the FV to find which map entry the Lba belongs to
292 NumBlocks
= BlockMap
->NumBlocks
;
293 BlockLength
= BlockMap
->Length
;
295 if (NumBlocks
== 0 || BlockLength
== 0) {
296 return EFI_INVALID_PARAMETER
;
299 NextLba
= StartLba
+ NumBlocks
;
302 // The map entry found
304 if (Lba
>= StartLba
&& Lba
< NextLba
) {
305 Offset
= Offset
+ (UINTN
) MultU64x32 ((Lba
- StartLba
), BlockLength
);
306 if (LbaAddress
!= NULL
) {
307 *LbaAddress
= FwhInstance
->FvBase
+ Offset
;
310 if (LbaLength
!= NULL
) {
311 *LbaLength
= BlockLength
;
314 if (NumOfBlocks
!= NULL
) {
315 *NumOfBlocks
= (UINTN
) (NextLba
- Lba
);
322 Offset
= Offset
+ NumBlocks
* BlockLength
;
328 FvbSetVolumeAttributes (
330 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
331 IN ESAL_FWB_GLOBAL
*Global
336 Modifies the current settings of the firmware volume according to the
337 input parameter, and returns the new setting of the volume
340 Instance - The FV instance whose attributes is going to be
342 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
343 containing the desired firmware volume settings.
344 On successful return, it contains the new settings
345 of the firmware volume
346 Global - Pointer to ESAL_FWB_GLOBAL that contains all
350 EFI_SUCCESS - Successfully returns
351 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
352 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
353 in conflict with the capabilities as declared in
354 the firmware volume header
358 EFI_FW_VOL_INSTANCE
*FwhInstance
;
359 EFI_FVB_ATTRIBUTES_2 OldAttributes
;
360 EFI_FVB_ATTRIBUTES_2
*AttribPtr
;
365 EFI_FVB_ATTRIBUTES_2 UnchangedAttributes
;
368 // Find the right instance of the FVB private data
370 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
);
371 ASSERT_EFI_ERROR (Status
);
374 (EFI_FVB_ATTRIBUTES_2
*) &(FwhInstance
->VolumeHeader
.Attributes
);
375 OldAttributes
= *AttribPtr
;
376 Capabilities
= OldAttributes
& (EFI_FVB2_READ_DISABLED_CAP
| \
377 EFI_FVB2_READ_ENABLED_CAP
| \
378 EFI_FVB2_WRITE_DISABLED_CAP
| \
379 EFI_FVB2_WRITE_ENABLED_CAP
| \
382 OldStatus
= OldAttributes
& EFI_FVB2_STATUS
;
383 NewStatus
= *Attributes
& EFI_FVB2_STATUS
;
385 UnchangedAttributes
= EFI_FVB2_READ_DISABLED_CAP
| \
386 EFI_FVB2_READ_ENABLED_CAP
| \
387 EFI_FVB2_WRITE_DISABLED_CAP
| \
388 EFI_FVB2_WRITE_ENABLED_CAP
| \
389 EFI_FVB2_LOCK_CAP
| \
390 EFI_FVB2_STICKY_WRITE
| \
391 EFI_FVB2_MEMORY_MAPPED
| \
392 EFI_FVB2_ERASE_POLARITY
| \
393 EFI_FVB2_READ_LOCK_CAP
| \
394 EFI_FVB2_WRITE_LOCK_CAP
| \
398 // Some attributes of FV is read only can *not* be set
400 if ((OldAttributes
& UnchangedAttributes
) ^
401 (*Attributes
& UnchangedAttributes
)) {
402 return EFI_INVALID_PARAMETER
;
405 // If firmware volume is locked, no status bit can be updated
407 if (OldAttributes
& EFI_FVB2_LOCK_STATUS
) {
408 if (OldStatus
^ NewStatus
) {
409 return EFI_ACCESS_DENIED
;
415 if ((Capabilities
& EFI_FVB2_READ_DISABLED_CAP
) == 0) {
416 if ((NewStatus
& EFI_FVB2_READ_STATUS
) == 0) {
417 return EFI_INVALID_PARAMETER
;
423 if ((Capabilities
& EFI_FVB2_READ_ENABLED_CAP
) == 0) {
424 if (NewStatus
& EFI_FVB2_READ_STATUS
) {
425 return EFI_INVALID_PARAMETER
;
429 // Test write disable
431 if ((Capabilities
& EFI_FVB2_WRITE_DISABLED_CAP
) == 0) {
432 if ((NewStatus
& EFI_FVB2_WRITE_STATUS
) == 0) {
433 return EFI_INVALID_PARAMETER
;
439 if ((Capabilities
& EFI_FVB2_WRITE_ENABLED_CAP
) == 0) {
440 if (NewStatus
& EFI_FVB2_WRITE_STATUS
) {
441 return EFI_INVALID_PARAMETER
;
447 if ((Capabilities
& EFI_FVB2_LOCK_CAP
) == 0) {
448 if (NewStatus
& EFI_FVB2_LOCK_STATUS
) {
449 return EFI_INVALID_PARAMETER
;
453 *AttribPtr
= (*AttribPtr
) & (0xFFFFFFFF & (~EFI_FVB2_STATUS
));
454 *AttribPtr
= (*AttribPtr
) | NewStatus
;
455 *Attributes
= *AttribPtr
;
465 FvbProtocolGetPhysicalAddress (
466 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
467 OUT EFI_PHYSICAL_ADDRESS
*Address
473 Retrieves the physical address of the device.
477 This - Calling context
478 Address - Output buffer containing the address.
481 EFI_SUCCESS - Successfully returns
485 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
487 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
489 return FvbGetPhysicalAddress (FvbDevice
->Instance
, Address
,
495 FvbProtocolGetBlockSize (
496 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
497 IN CONST EFI_LBA Lba
,
498 OUT UINTN
*BlockSize
,
499 OUT UINTN
*NumOfBlocks
504 Retrieve the size of a logical block
507 This - Calling context
508 Lba - Indicates which block to return the size for.
509 BlockSize - A pointer to a caller allocated UINTN in which
510 the size of the block is returned
511 NumOfBlocks - a pointer to a caller allocated UINTN in which the
512 number of consecutive blocks starting with Lba is
513 returned. All blocks in this range have a size of
517 EFI_SUCCESS - The firmware volume was read successfully and
518 contents are in Buffer
522 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
524 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
526 return FvbGetLbaAddress (
538 FvbProtocolGetAttributes (
539 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
540 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
545 Retrieves Volume attributes. No polarity translations are done.
548 This - Calling context
549 Attributes - output buffer which contains attributes
552 EFI_SUCCESS - Successfully returns
556 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
558 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
560 return FvbGetVolumeAttributes (FvbDevice
->Instance
, Attributes
,
566 FvbProtocolSetAttributes (
567 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
568 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
573 Sets Volume attributes. No polarity translations are done.
576 This - Calling context
577 Attributes - output buffer which contains attributes
580 EFI_SUCCESS - Successfully returns
584 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
586 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
588 return FvbSetVolumeAttributes (FvbDevice
->Instance
, Attributes
,
594 FvbProtocolEraseBlocks (
595 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
602 The EraseBlock() function erases one or more blocks as denoted by the
603 variable argument list. The entire parameter list of blocks must be
604 verified prior to erasing any blocks. If a block is requested that does
605 not exist within the associated firmware volume (it has a larger index than
606 the last block of the firmware volume), the EraseBlock() function must
607 return EFI_INVALID_PARAMETER without modifying the contents of the firmware
611 This - Calling context
612 ... - Starting LBA followed by Number of Lba to erase.
613 a -1 to terminate the list.
616 EFI_SUCCESS - The erase request was successfully completed
617 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
618 EFI_DEVICE_ERROR - The block device is not functioning correctly and
619 could not be written. Firmware device may have been
624 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
625 EFI_FW_VOL_INSTANCE
*FwhInstance
;
632 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
634 Status
= GetFvbInstance (FvbDevice
->Instance
, mFvbModuleGlobal
,
636 ASSERT_EFI_ERROR (Status
);
638 NumOfBlocks
= FwhInstance
->NumOfBlocks
;
640 VA_START (args
, This
);
643 StartingLba
= VA_ARG (args
, EFI_LBA
);
644 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
648 NumOfLba
= VA_ARG (args
, UINTN
);
651 // Check input parameters
653 if ((NumOfLba
== 0) || ((StartingLba
+ NumOfLba
) > NumOfBlocks
)) {
655 return EFI_INVALID_PARAMETER
;
661 VA_START (args
, This
);
663 StartingLba
= VA_ARG (args
, EFI_LBA
);
664 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
668 NumOfLba
= VA_ARG (args
, UINTN
);
670 while (NumOfLba
> 0) {
671 Status
= QemuFlashEraseBlock (StartingLba
);
672 if (EFI_ERROR (Status
)) {
691 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
694 IN OUT UINTN
*NumBytes
,
701 Writes data beginning at Lba:Offset from FV. The write terminates either
702 when *NumBytes of data have been written, or when a block boundary is
703 reached. *NumBytes is updated to reflect the actual number of bytes
704 written. The write opertion does not include erase. This routine will
705 attempt to write only the specified bytes. If the writes do not stick,
706 it will return an error.
709 This - Calling context
710 Lba - Block in which to begin write
711 Offset - Offset in the block at which to begin write
712 NumBytes - On input, indicates the requested write size. On
713 output, indicates the actual number of bytes
715 Buffer - Buffer containing source data for the write.
718 EFI_SUCCESS - The firmware volume was written successfully
719 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
720 NumBytes contains the total number of bytes
722 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
723 EFI_DEVICE_ERROR - The block device is not functioning correctly and
725 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
729 return QemuFlashWrite ((EFI_LBA
)Lba
, (UINTN
)Offset
, NumBytes
,
736 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
737 IN CONST EFI_LBA Lba
,
738 IN CONST UINTN Offset
,
739 IN OUT UINTN
*NumBytes
,
746 Reads data beginning at Lba:Offset from FV. The Read terminates either
747 when *NumBytes of data have been read, or when a block boundary is
748 reached. *NumBytes is updated to reflect the actual number of bytes
749 written. The write opertion does not include erase. This routine will
750 attempt to write only the specified bytes. If the writes do not stick,
751 it will return an error.
754 This - Calling context
755 Lba - Block in which to begin Read
756 Offset - Offset in the block at which to begin Read
757 NumBytes - On input, indicates the requested write size. On
758 output, indicates the actual number of bytes Read
759 Buffer - Buffer containing source data for the Read.
762 EFI_SUCCESS - The firmware volume was read successfully and
763 contents are in Buffer
764 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
765 NumBytes contains the total number of bytes
767 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
768 EFI_DEVICE_ERROR - The block device is not functioning correctly and
770 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
774 return QemuFlashRead ((EFI_LBA
)Lba
, (UINTN
)Offset
, NumBytes
,
780 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
785 Check the integrity of firmware volume header
788 FwVolHeader - A pointer to a firmware volume header
791 EFI_SUCCESS - The firmware volume is consistent
792 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an
800 // Verify the header revision, header signature, length
801 // Length of FvBlock cannot be 2**64-1
802 // HeaderLength cannot be an odd number
804 if ((FwVolHeader
->Revision
!= EFI_FVH_REVISION
) ||
805 (FwVolHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
806 (FwVolHeader
->FvLength
== ((UINTN
) -1)) ||
807 ((FwVolHeader
->HeaderLength
& 0x01) != 0)
809 return EFI_NOT_FOUND
;
813 // Verify the header checksum
816 Checksum
= CalculateSum16 ((UINT16
*) FwVolHeader
,
817 FwVolHeader
->HeaderLength
);
822 (UINT16
) (((UINTN
) FwVolHeader
->Checksum
+ 0x10000 - Checksum
) & 0xffff);
824 DEBUG ((EFI_D_INFO
, "FV@%p Checksum is 0x%x, expected 0x%x\n",
825 FwVolHeader
, FwVolHeader
->Checksum
, Expected
));
826 return EFI_NOT_FOUND
;
834 MarkMemoryRangeForRuntimeAccess (
835 EFI_PHYSICAL_ADDRESS BaseAddress
,
842 // Mark flash region as runtime memory
844 Status
= gDS
->RemoveMemorySpace (
849 Status
= gDS
->AddMemorySpace (
850 EfiGcdMemoryTypeSystemMemory
,
853 EFI_MEMORY_UC
| EFI_MEMORY_RUNTIME
855 ASSERT_EFI_ERROR (Status
);
857 Status
= gBS
->AllocatePages (
859 EfiRuntimeServicesData
,
860 EFI_SIZE_TO_PAGES (Length
),
863 ASSERT_EFI_ERROR (Status
);
870 InitializeVariableFvHeader (
875 EFI_FIRMWARE_VOLUME_HEADER
*GoodFwVolHeader
;
876 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
882 (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
)
883 PcdGet32 (PcdOvmfFlashNvStorageVariableBase
);
886 (FixedPcdGet32 (PcdFlashNvStorageVariableSize
) +
887 FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize
) +
888 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize
) +
889 FixedPcdGet32 (PcdOvmfFlashNvStorageEventLogSize
));
891 BlockSize
= PcdGet32 (PcdOvmfFirmwareBlockSize
);
893 Status
= ValidateFvHeader (FwVolHeader
);
894 if (!EFI_ERROR (Status
)) {
895 if (FwVolHeader
->FvLength
!= Length
||
896 FwVolHeader
->BlockMap
[0].Length
!= BlockSize
) {
897 Status
= EFI_VOLUME_CORRUPTED
;
900 if (EFI_ERROR (Status
)) {
905 "Variable FV header is not valid. It will be reinitialized.\n"));
908 // Get FvbInfo to provide in FwhInstance.
910 Status
= GetFvbInfo (Length
, &GoodFwVolHeader
);
911 ASSERT (!EFI_ERROR (Status
));
913 Start
= (UINTN
)(UINT8
*) FwVolHeader
- PcdGet32 (PcdOvmfFdBaseAddress
);
914 ASSERT (Start
% BlockSize
== 0 && Length
% BlockSize
== 0);
915 ASSERT (GoodFwVolHeader
->HeaderLength
<= BlockSize
);
918 // Erase all the blocks
920 for (Offset
= Start
; Offset
< Start
+ Length
; Offset
+= BlockSize
) {
921 Status
= QemuFlashEraseBlock (Offset
/ BlockSize
);
922 ASSERT_EFI_ERROR (Status
);
926 // Write good FV header
928 WriteLength
= GoodFwVolHeader
->HeaderLength
;
929 Status
= QemuFlashWrite (
933 (UINT8
*) GoodFwVolHeader
);
934 ASSERT_EFI_ERROR (Status
);
935 ASSERT (WriteLength
== GoodFwVolHeader
->HeaderLength
);
944 IN EFI_HANDLE ImageHandle
,
945 IN EFI_SYSTEM_TABLE
*SystemTable
950 This function does common initialization for FVB services
959 EFI_FW_VOL_INSTANCE
*FwhInstance
;
960 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
962 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
963 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
965 EFI_PHYSICAL_ADDRESS BaseAddress
;
968 RETURN_STATUS PcdStatus
;
970 if (EFI_ERROR (QemuFlashInitialize ())) {
972 // Return an error so image will be unloaded
975 "QEMU flash was not detected. Writable FVB is not being installed.\n"));
976 return EFI_WRITE_PROTECTED
;
980 // Allocate runtime services data for global variable, which contains
981 // the private data of all firmware volume block instances
983 mFvbModuleGlobal
= AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL
));
984 ASSERT (mFvbModuleGlobal
!= NULL
);
986 BaseAddress
= (UINTN
) PcdGet32 (PcdOvmfFdBaseAddress
);
987 Length
= PcdGet32 (PcdOvmfFirmwareFdSize
);
989 Status
= InitializeVariableFvHeader ();
990 if (EFI_ERROR (Status
)) {
992 "QEMU Flash: Unable to initialize variable FV header\n"));
993 return EFI_WRITE_PROTECTED
;
996 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) BaseAddress
;
997 Status
= ValidateFvHeader (FwVolHeader
);
998 if (EFI_ERROR (Status
)) {
1002 Status
= GetFvbInfo (Length
, &FwVolHeader
);
1003 if (EFI_ERROR (Status
)) {
1004 DEBUG ((EFI_D_INFO
, "EFI_ERROR (GetFvbInfo (Length, &FwVolHeader))\n"));
1005 return EFI_WRITE_PROTECTED
;
1009 BufferSize
= (sizeof (EFI_FW_VOL_INSTANCE
) +
1010 FwVolHeader
->HeaderLength
-
1011 sizeof (EFI_FIRMWARE_VOLUME_HEADER
)
1013 mFvbModuleGlobal
->FvInstance
= AllocateRuntimePool (BufferSize
);
1014 ASSERT (mFvbModuleGlobal
->FvInstance
!= NULL
);
1016 FwhInstance
= mFvbModuleGlobal
->FvInstance
;
1018 mFvbModuleGlobal
->NumFv
= 0;
1022 (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
)
1023 PcdGet32 (PcdOvmfFlashNvStorageVariableBase
);
1025 FwhInstance
->FvBase
= (UINTN
) BaseAddress
;
1027 CopyMem ((UINTN
*) &(FwhInstance
->VolumeHeader
), (UINTN
*) FwVolHeader
,
1028 FwVolHeader
->HeaderLength
);
1029 FwVolHeader
= &(FwhInstance
->VolumeHeader
);
1033 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
;
1034 PtrBlockMapEntry
->NumBlocks
!= 0;
1035 PtrBlockMapEntry
++) {
1037 // Get the maximum size of a block.
1039 if (MaxLbaSize
< PtrBlockMapEntry
->Length
) {
1040 MaxLbaSize
= PtrBlockMapEntry
->Length
;
1043 NumOfBlocks
= NumOfBlocks
+ PtrBlockMapEntry
->NumBlocks
;
1047 // The total number of blocks in the FV.
1049 FwhInstance
->NumOfBlocks
= NumOfBlocks
;
1052 // Add a FVB Protocol Instance
1054 FvbDevice
= AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE
));
1055 ASSERT (FvbDevice
!= NULL
);
1057 CopyMem (FvbDevice
, &mFvbDeviceTemplate
, sizeof (EFI_FW_VOL_BLOCK_DEVICE
));
1059 FvbDevice
->Instance
= mFvbModuleGlobal
->NumFv
;
1060 mFvbModuleGlobal
->NumFv
++;
1063 // Set up the devicepath
1065 if (FwVolHeader
->ExtHeaderOffset
== 0) {
1066 FV_MEMMAP_DEVICE_PATH
*FvMemmapDevicePath
;
1069 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
1071 FvMemmapDevicePath
= AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH
),
1072 &mFvMemmapDevicePathTemplate
);
1073 FvMemmapDevicePath
->MemMapDevPath
.StartingAddress
= BaseAddress
;
1074 FvMemmapDevicePath
->MemMapDevPath
.EndingAddress
=
1075 BaseAddress
+ FwVolHeader
->FvLength
- 1;
1076 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)FvMemmapDevicePath
;
1078 FV_PIWG_DEVICE_PATH
*FvPiwgDevicePath
;
1080 FvPiwgDevicePath
= AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH
),
1081 &mFvPIWGDevicePathTemplate
);
1083 &FvPiwgDevicePath
->FvDevPath
.FvName
,
1084 (GUID
*)(UINTN
)(BaseAddress
+ FwVolHeader
->ExtHeaderOffset
)
1086 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)FvPiwgDevicePath
;
1090 // Module type specific hook.
1092 InstallProtocolInterfaces (FvbDevice
);
1094 MarkMemoryRangeForRuntimeAccess (BaseAddress
, Length
);
1097 // Set several PCD values to point to flash
1099 PcdStatus
= PcdSet64S (
1100 PcdFlashNvStorageVariableBase64
,
1101 (UINTN
) PcdGet32 (PcdOvmfFlashNvStorageVariableBase
)
1103 ASSERT_RETURN_ERROR (PcdStatus
);
1104 PcdStatus
= PcdSet32S (
1105 PcdFlashNvStorageFtwWorkingBase
,
1106 PcdGet32 (PcdOvmfFlashNvStorageFtwWorkingBase
)
1108 ASSERT_RETURN_ERROR (PcdStatus
);
1109 PcdStatus
= PcdSet32S (
1110 PcdFlashNvStorageFtwSpareBase
,
1111 PcdGet32 (PcdOvmfFlashNvStorageFtwSpareBase
)
1113 ASSERT_RETURN_ERROR (PcdStatus
);
1115 FwhInstance
= (EFI_FW_VOL_INSTANCE
*)
1117 (UINTN
) ((UINT8
*) FwhInstance
) + FwVolHeader
->HeaderLength
+
1118 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
1122 // Module type specific hook.
1124 InstallVirtualAddressChangeHandler ();
1126 PcdStatus
= PcdSetBoolS (PcdOvmfFlashVariablesEnable
, TRUE
);
1127 ASSERT_RETURN_ERROR (PcdStatus
);