3 Implement the Firmware Volume Block (FVB) services based on SMM FVB
4 module and install FVB protocol.
6 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved. <BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include "FvbSmmDxe.h"
16 EFI_HANDLE mHandle
= NULL
;
17 EFI_SMM_COMMUNICATION_PROTOCOL
*mSmmCommunication
= NULL
;
20 // Template structure used when installing FVB protocol.
22 EFI_FVB_DEVICE mFvbDeviceTemplate
= {
28 FvbGetPhysicalAddress
,
38 FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate
= {
44 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
)),
45 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
) >> 8)
49 (EFI_PHYSICAL_ADDRESS
) 0,
50 (EFI_PHYSICAL_ADDRESS
) 0,
54 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
56 END_DEVICE_PATH_LENGTH
,
62 FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate
= {
68 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
)),
69 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
) >> 8)
76 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
78 END_DEVICE_PATH_LENGTH
,
85 Initialize the communicate buffer using DataSize and Function.
87 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
90 @param[out] CommunicateBuffer The communicate buffer. Caller should free it after use.
91 @param[out] DataPtr Points to the data in the communicate buffer. Caller should not free it.
92 @param[in] DataSize The payload size.
93 @param[in] Function The function number used to initialize the communicate header.
95 @retval EFI_INVALID_PARAMETER The data size is too big.
96 @retval EFI_SUCCESS Find the specified variable.
100 InitCommunicateBuffer (
101 OUT VOID
**CommunicateBuffer
,
107 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
108 SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*SmmFvbFunctionHeader
;
111 // The whole buffer size: SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE + DataSize.
113 SmmCommunicateHeader
= AllocatePool (DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_FVB_COMMUNICATE_HEADER_SIZE
);
114 ASSERT (SmmCommunicateHeader
!= NULL
);
117 // Prepare data buffer.
119 CopyGuid (&SmmCommunicateHeader
->HeaderGuid
, &gEfiSmmFirmwareVolumeBlockProtocolGuid
);
120 SmmCommunicateHeader
->MessageLength
= DataSize
+ SMM_FVB_COMMUNICATE_HEADER_SIZE
;
122 SmmFvbFunctionHeader
= (SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*) SmmCommunicateHeader
->Data
;
123 SmmFvbFunctionHeader
->Function
= Function
;
125 *CommunicateBuffer
= SmmCommunicateHeader
;
126 *DataPtr
= SmmFvbFunctionHeader
->Data
;
133 Send the data in communicate buffer to SMM.
135 @param[out] SmmCommunicateHeader The communicate buffer.
136 @param[in] DataSize The payload size.
140 SendCommunicateBuffer (
141 IN EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
,
147 SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*SmmFvbFunctionHeader
;
149 CommSize
= DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_FVB_COMMUNICATE_HEADER_SIZE
;
150 Status
= mSmmCommunication
->Communicate (
152 SmmCommunicateHeader
,
155 ASSERT_EFI_ERROR (Status
);
157 SmmFvbFunctionHeader
= (SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*) SmmCommunicateHeader
->Data
;
158 return SmmFvbFunctionHeader
->ReturnStatus
;
162 This function retrieves the attributes and current settings of the block.
164 @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
166 @param[out] Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes
167 and current settings are returned. Type EFI_FVB_ATTRIBUTES_2
168 is defined in EFI_FIRMWARE_VOLUME_HEADER.
170 @retval EFI_SUCCESS The firmware volume attributes were returned.
171 @retval EFI_INVALID_PARAMETER Attributes is NULL.
176 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
177 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
182 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
183 SMM_FVB_ATTRIBUTES_HEADER
*SmmFvbAttributesHeader
;
184 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
185 EFI_FVB_DEVICE
*FvbDevice
;
187 if (Attributes
== NULL
) {
188 return EFI_INVALID_PARAMETER
;
191 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
192 SmmFvb
= FvbDevice
->SmmFvbInstance
;
195 // Initialize the communicate buffer.
197 PayloadSize
= sizeof (SMM_FVB_ATTRIBUTES_HEADER
);
198 Status
= InitCommunicateBuffer (
199 (VOID
**)&SmmCommunicateHeader
,
200 (VOID
**)&SmmFvbAttributesHeader
,
202 EFI_FUNCTION_GET_ATTRIBUTES
204 if (EFI_ERROR (Status
)) {
208 SmmFvbAttributesHeader
->SmmFvb
= SmmFvb
;
209 SmmFvbAttributesHeader
->Attributes
= 0;
214 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
217 // Get data from SMM.
219 *Attributes
= SmmFvbAttributesHeader
->Attributes
;
220 FreePool (SmmCommunicateHeader
);
227 Sets Volume attributes. No polarity translations are done.
229 @param[in] This Calling context.
230 @param[out] Attributes Output buffer which contains attributes.
232 @retval EFI_SUCCESS Set the Attributes successfully.
233 @retval EFI_INVALID_PARAMETER Attributes is NULL.
239 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
240 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
245 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
246 SMM_FVB_ATTRIBUTES_HEADER
*SmmFvbAttributesHeader
;
247 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
248 EFI_FVB_DEVICE
*FvbDevice
;
250 if (Attributes
== NULL
) {
251 return EFI_INVALID_PARAMETER
;
254 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
255 SmmFvb
= FvbDevice
->SmmFvbInstance
;
258 // Initialize the communicate buffer.
260 PayloadSize
= sizeof (SMM_FVB_ATTRIBUTES_HEADER
);
261 Status
= InitCommunicateBuffer (
262 (VOID
**)&SmmCommunicateHeader
,
263 (VOID
**)&SmmFvbAttributesHeader
,
265 EFI_FUNCTION_SET_ATTRIBUTES
267 if (EFI_ERROR (Status
)) {
271 SmmFvbAttributesHeader
->SmmFvb
= SmmFvb
;
272 SmmFvbAttributesHeader
->Attributes
= *Attributes
;
277 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
280 // Get data from SMM.
282 *Attributes
= SmmFvbAttributesHeader
->Attributes
;
283 FreePool (SmmCommunicateHeader
);
290 Retrieves the physical address of the FVB instance.
292 @param[in] SmmFvb A pointer to EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
293 @param[out] Address Output buffer containing the address.
295 @retval EFI_SUCCESS Get the address successfully.
296 @retval Others Failed to get address.
301 IN EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
,
302 OUT EFI_PHYSICAL_ADDRESS
*Address
307 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
308 SMM_FVB_PHYSICAL_ADDRESS_HEADER
*SmmFvbPhysicalAddressHeader
;
311 // Initialize the communicate buffer.
313 PayloadSize
= sizeof (SMM_FVB_PHYSICAL_ADDRESS_HEADER
);
314 Status
= InitCommunicateBuffer (
315 (VOID
**)&SmmCommunicateHeader
,
316 (VOID
**)&SmmFvbPhysicalAddressHeader
,
318 EFI_FUNCTION_GET_PHYSICAL_ADDRESS
320 if (EFI_ERROR (Status
)) {
324 SmmFvbPhysicalAddressHeader
->SmmFvb
= SmmFvb
;
325 SmmFvbPhysicalAddressHeader
->Address
= 0;
330 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
333 // Get data from SMM.
335 *Address
= SmmFvbPhysicalAddressHeader
->Address
;
336 FreePool (SmmCommunicateHeader
);
343 Retrieves the physical address of the FVB instance.
345 @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
346 @param[out] Address Output buffer containing the address.
348 @retval EFI_SUCCESS Get the address successfully.
349 @retval Others Failed to get the address.
354 FvbGetPhysicalAddress (
355 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
356 OUT EFI_PHYSICAL_ADDRESS
*Address
360 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
361 EFI_FVB_DEVICE
*FvbDevice
;
363 if (Address
== NULL
) {
364 return EFI_INVALID_PARAMETER
;
367 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
368 SmmFvb
= FvbDevice
->SmmFvbInstance
;
370 Status
= GetPhysicalAddress (SmmFvb
, Address
);
377 Retrieve the size of a logical block.
379 @param[in] This Calling context.
380 @param[in] Lba Indicates which block to return the size for.
381 @param[out] BlockSize A pointer to a caller allocated UINTN in which
382 the size of the block is returned.
383 @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the
384 number of consecutive blocks starting with Lba is
385 returned. All blocks in this range have a size of
388 @retval EFI_SUCCESS Get BlockSize and NumOfBlocks successfully.
389 @retval EFI_INVALID_PARAMETER BlockSize or NumOfBlocks are NULL.
394 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
396 OUT UINTN
*BlockSize
,
397 OUT UINTN
*NumOfBlocks
402 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
403 SMM_FVB_BLOCK_SIZE_HEADER
*SmmFvbBlockSizeHeader
;
404 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
405 EFI_FVB_DEVICE
*FvbDevice
;
407 if ((BlockSize
== NULL
) || (NumOfBlocks
== NULL
)) {
408 return EFI_INVALID_PARAMETER
;
411 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
412 SmmFvb
= FvbDevice
->SmmFvbInstance
;
415 // Initialize the communicate buffer.
417 PayloadSize
= sizeof (SMM_FVB_BLOCK_SIZE_HEADER
);
418 Status
= InitCommunicateBuffer (
419 (VOID
**)&SmmCommunicateHeader
,
420 (VOID
**)&SmmFvbBlockSizeHeader
,
422 EFI_FUNCTION_GET_BLOCK_SIZE
424 if (EFI_ERROR (Status
)) {
428 SmmFvbBlockSizeHeader
->SmmFvb
= SmmFvb
;
429 SmmFvbBlockSizeHeader
->Lba
= Lba
;
434 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
437 // Get data from SMM.
439 *BlockSize
= SmmFvbBlockSizeHeader
->BlockSize
;
440 *NumOfBlocks
= SmmFvbBlockSizeHeader
->NumOfBlocks
;
441 FreePool (SmmCommunicateHeader
);
448 Reads data beginning at Lba:Offset from FV. The Read terminates either
449 when *NumBytes of data have been read, or when a block boundary is
450 reached. *NumBytes is updated to reflect the actual number of bytes
451 written. The write opertion does not include erase. This routine will
452 attempt to write only the specified bytes. If the writes do not stick,
453 it will return an error.
455 @param[in] This Calling context
456 @param[in] Lba Block in which to begin write
457 @param[in] Offset Offset in the block at which to begin write
458 @param[in,out] NumBytes On input, indicates the requested write size. On
459 output, indicates the actual number of bytes written
460 @param[in] Buffer Buffer containing source data for the write.
462 @retval EFI_SUCCESS The firmware volume was read successfully and
463 contents are in Buffer.
464 @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output,
465 NumBytes contains the total number of bytes returned
467 @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state
468 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
470 @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL.
476 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
479 IN OUT UINTN
*NumBytes
,
485 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
486 SMM_FVB_READ_WRITE_HEADER
*SmmFvbReadWriteHeader
;
487 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
488 EFI_FVB_DEVICE
*FvbDevice
;
490 if ((NumBytes
== NULL
) || (Buffer
== NULL
)) {
491 return EFI_INVALID_PARAMETER
;
494 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
495 SmmFvb
= FvbDevice
->SmmFvbInstance
;
498 // Initialize the communicate buffer.
500 PayloadSize
= sizeof (SMM_FVB_READ_WRITE_HEADER
) + *NumBytes
;
501 Status
= InitCommunicateBuffer (
502 (VOID
**)&SmmCommunicateHeader
,
503 (VOID
**)&SmmFvbReadWriteHeader
,
504 PayloadSize
, EFI_FUNCTION_READ
506 if (EFI_ERROR (Status
)) {
510 SmmFvbReadWriteHeader
->SmmFvb
= SmmFvb
;
511 SmmFvbReadWriteHeader
->Lba
= Lba
;
512 SmmFvbReadWriteHeader
->Offset
= Offset
;
513 SmmFvbReadWriteHeader
->NumBytes
= *NumBytes
;
518 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
521 // Get data from SMM.
523 *NumBytes
= SmmFvbReadWriteHeader
->NumBytes
;
524 if (!EFI_ERROR (Status
)) {
525 CopyMem (Buffer
, (UINT8
*)(SmmFvbReadWriteHeader
+ 1), *NumBytes
);
527 FreePool (SmmCommunicateHeader
);
534 Writes data beginning at Lba:Offset from FV. The write terminates either
535 when *NumBytes of data have been written, or when a block boundary is
536 reached. *NumBytes is updated to reflect the actual number of bytes
537 written. The write opertion does not include erase. This routine will
538 attempt to write only the specified bytes. If the writes do not stick,
539 it will return an error.
541 @param[in] This Calling context.
542 @param[in] Lba Block in which to begin write.
543 @param[in] Offset Offset in the block at which to begin write.
544 @param[in,out] NumBytes On input, indicates the requested write size. On
545 output, indicates the actual number of bytes written.
546 @param[in] Buffer Buffer containing source data for the write.
548 @retval EFI_SUCCESS The firmware volume was written successfully.
549 @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output,
550 NumBytes contains the total number of bytes
552 @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
553 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
554 could not be written.
555 @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL.
561 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
564 IN OUT UINTN
*NumBytes
,
570 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
571 SMM_FVB_READ_WRITE_HEADER
*SmmFvbReadWriteHeader
;
572 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
573 EFI_FVB_DEVICE
*FvbDevice
;
575 if ((NumBytes
== NULL
) || (Buffer
== NULL
)) {
576 return EFI_INVALID_PARAMETER
;
579 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
580 SmmFvb
= FvbDevice
->SmmFvbInstance
;
583 // Initialize the communicate buffer.
585 PayloadSize
= sizeof (SMM_FVB_READ_WRITE_HEADER
) + *NumBytes
;
586 Status
= InitCommunicateBuffer (
587 (VOID
**)&SmmCommunicateHeader
,
588 (VOID
**)&SmmFvbReadWriteHeader
,
592 if (EFI_ERROR (Status
)) {
596 SmmFvbReadWriteHeader
->SmmFvb
= SmmFvb
;
597 SmmFvbReadWriteHeader
->Lba
= Lba
;
598 SmmFvbReadWriteHeader
->Offset
= Offset
;
599 SmmFvbReadWriteHeader
->NumBytes
= *NumBytes
;
600 CopyMem ((UINT8
*)(SmmFvbReadWriteHeader
+ 1), Buffer
, *NumBytes
);
605 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
608 // Get data from SMM.
610 *NumBytes
= SmmFvbReadWriteHeader
->NumBytes
;
611 FreePool (SmmCommunicateHeader
);
618 The EraseBlock() function erases NumOfLba blocks started from StartingLba.
620 @param[in] This Calling context.
621 @param[in] StartingLba Starting LBA followed to erase.
622 @param[in] NumOfLba Number of block to erase.
624 @retval EFI_SUCCESS The erase request was successfully completed.
625 @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
626 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
627 could not be written. Firmware device may have been
633 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
634 IN EFI_LBA StartingLba
,
640 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
641 SMM_FVB_BLOCKS_HEADER
*SmmFvbBlocksHeader
;
642 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
643 EFI_FVB_DEVICE
*FvbDevice
;
645 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
646 SmmFvb
= FvbDevice
->SmmFvbInstance
;
649 // Initialize the communicate buffer.
651 PayloadSize
= sizeof (SMM_FVB_BLOCKS_HEADER
);
652 Status
= InitCommunicateBuffer (
653 (VOID
**)&SmmCommunicateHeader
,
654 (VOID
**)&SmmFvbBlocksHeader
,
656 EFI_FUNCTION_ERASE_BLOCKS
658 if (EFI_ERROR (Status
)) {
662 SmmFvbBlocksHeader
->SmmFvb
= SmmFvb
;
663 SmmFvbBlocksHeader
->StartLba
= StartingLba
;
664 SmmFvbBlocksHeader
->NumOfLba
= NumOfLba
;
669 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
672 // Get data from SMM.
674 FreePool (SmmCommunicateHeader
);
681 The EraseBlocks() function erases one or more blocks as denoted by the
682 variable argument list. The entire parameter list of blocks must be verified
683 prior to erasing any blocks. If a block is requested that does not exist
684 within the associated firmware volume (it has a larger index than the last
685 block of the firmware volume), the EraseBlock() function must return
686 EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
688 @param[in] This Calling context/
689 @param[in] ... Starting LBA followed by Number of Lba to erase.
690 a -1 to terminate the list.
692 @retval EFI_SUCCESS The erase request was successfully completed
693 @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state/
694 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
695 could not be written. Firmware device may have been
702 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
711 Status
= EFI_SUCCESS
;
714 // Check the parameter.
716 VA_START (Marker
, This
);
718 StartingLba
= VA_ARG (Marker
, EFI_LBA
);
719 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
723 NumOfLba
= VA_ARG (Marker
, UINTN
);
725 return EFI_INVALID_PARAMETER
;
734 VA_START (Marker
, This
);
736 StartingLba
= VA_ARG (Marker
, EFI_LBA
);
737 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
740 NumOfLba
= VA_ARG (Marker
, UINTN
);
741 Status
= EraseBlock (This
, StartingLba
, NumOfLba
);
742 if (EFI_ERROR (Status
)) {
753 Install the FVB protocol which based on SMM FVB protocol.
755 @param[in] SmmFvb The SMM FVB protocol.
760 IN EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
764 EFI_HANDLE FvbHandle
;
765 EFI_FVB_DEVICE
*FvbDevice
;
766 EFI_FIRMWARE_VOLUME_HEADER
*VolumeHeader
;
767 EFI_PHYSICAL_ADDRESS Address
;
768 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*OldFvbInterface
;
770 FvbDevice
= AllocateRuntimeCopyPool (sizeof (EFI_FVB_DEVICE
), &mFvbDeviceTemplate
);
771 ASSERT (FvbDevice
!= NULL
);
772 FvbDevice
->SmmFvbInstance
= SmmFvb
;
774 Status
= gBS
->LocateProtocol (
775 &gEfiSmmCommunicationProtocolGuid
,
777 (VOID
**) &mSmmCommunication
779 ASSERT_EFI_ERROR (Status
);
781 Status
= GetPhysicalAddress (SmmFvb
, &Address
);
782 ASSERT_EFI_ERROR (Status
);
784 VolumeHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
)Address
;
787 // Set up the devicepath.
789 if (VolumeHeader
->ExtHeaderOffset
== 0) {
791 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH.
793 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH
), &mFvMemmapDevicePathTemplate
);
794 ((FV_MEMMAP_DEVICE_PATH
*) FvbDevice
->DevicePath
)->MemMapDevPath
.StartingAddress
= (UINTN
)Address
;
795 ((FV_MEMMAP_DEVICE_PATH
*) FvbDevice
->DevicePath
)->MemMapDevPath
.EndingAddress
= (UINTN
)Address
+ VolumeHeader
->FvLength
- 1;
797 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH
), &mFvPIWGDevicePathTemplate
);
799 &((FV_PIWG_DEVICE_PATH
*)FvbDevice
->DevicePath
)->FvDevPath
.FvName
,
800 (GUID
*)(UINTN
)((UINTN
)Address
+ VolumeHeader
->ExtHeaderOffset
)
805 // Find a handle with a matching device path that has supports FW Block protocol.
807 Status
= gBS
->LocateDevicePath (
808 &gEfiFirmwareVolumeBlockProtocolGuid
,
809 &FvbDevice
->DevicePath
,
812 if (EFI_ERROR (Status
) ) {
814 // LocateDevicePath fails so install a new interface and device path.
817 Status
= gBS
->InstallMultipleProtocolInterfaces (
819 &gEfiFirmwareVolumeBlockProtocolGuid
,
820 &FvbDevice
->FvbInstance
,
821 &gEfiDevicePathProtocolGuid
,
822 FvbDevice
->DevicePath
,
825 ASSERT_EFI_ERROR (Status
);
826 } else if (IsDevicePathEnd (FvbDevice
->DevicePath
)) {
828 // Device allready exists, so reinstall the FVB protocol.
830 Status
= gBS
->HandleProtocol (
832 &gEfiFirmwareVolumeBlockProtocolGuid
,
833 (VOID
**) &OldFvbInterface
835 ASSERT_EFI_ERROR (Status
);
837 Status
= gBS
->ReinstallProtocolInterface (
839 &gEfiFirmwareVolumeBlockProtocolGuid
,
841 &FvbDevice
->FvbInstance
843 ASSERT_EFI_ERROR (Status
);
846 // There was a FVB protocol on an End Device Path node.
854 SMM Firmware Volume Block Protocol notification event handler.
856 Discover NV Variable Store and install Variable Write Arch Protocol.
858 @param[in] Event Event whose notification function is being invoked.
859 @param[in] Context Pointer to the notification function's context.
869 EFI_HANDLE
*HandleBuffer
;
872 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
875 // Locate all handles of Smm Fvb protocol.
877 Status
= gBS
->LocateHandleBuffer (
879 &gEfiSmmFirmwareVolumeBlockProtocolGuid
,
884 if (EFI_ERROR (Status
)) {
889 // Install FVB protocol.
891 for (Index
= 0; Index
< HandleCount
; Index
++) {
893 Status
= gBS
->HandleProtocol (
895 &gEfiSmmFirmwareVolumeBlockProtocolGuid
,
898 if (EFI_ERROR (Status
)) {
905 FreePool (HandleBuffer
);
910 The driver entry point for Firmware Volume Block Driver.
912 The function does the necessary initialization work
913 Firmware Volume Block Driver.
915 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
916 @param[in] SystemTable A pointer to the EFI system table.
918 @retval EFI_SUCCESS This funtion always return EFI_SUCCESS.
919 It will ASSERT on errors.
924 FvbSmmDxeInitialize (
925 IN EFI_HANDLE ImageHandle
,
926 IN EFI_SYSTEM_TABLE
*SystemTable
929 VOID
*SmmFvbRegistration
;
932 // Smm FVB driver is ready.
934 EfiCreateProtocolNotifyEvent (
935 &gEfiSmmFirmwareVolumeBlockProtocolGuid
,