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 This program and the accompanying materials are licensed and made available under
9 the terms and conditions of the BSD License that accompanies this distribution.
10 The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php.
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include "FvbSmmDxe.h"
21 EFI_HANDLE mHandle
= NULL
;
22 EFI_SMM_COMMUNICATION_PROTOCOL
*mSmmCommunication
= NULL
;
25 // Template structure used when installing FVB protocol.
27 EFI_FVB_DEVICE mFvbDeviceTemplate
= {
33 FvbGetPhysicalAddress
,
43 FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate
= {
49 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
)),
50 (UINT8
)(sizeof (MEMMAP_DEVICE_PATH
) >> 8)
54 (EFI_PHYSICAL_ADDRESS
) 0,
55 (EFI_PHYSICAL_ADDRESS
) 0,
59 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
61 END_DEVICE_PATH_LENGTH
,
67 FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate
= {
73 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
)),
74 (UINT8
)(sizeof (MEDIA_FW_VOL_DEVICE_PATH
) >> 8)
81 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
83 END_DEVICE_PATH_LENGTH
,
90 Initialize the communicate buffer using DataSize and Function.
92 The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
95 @param[out] CommunicateBuffer The communicate buffer. Caller should free it after use.
96 @param[out] DataPtr Points to the data in the communicate buffer. Caller should not free it.
97 @param[in] DataSize The payload size.
98 @param[in] Function The function number used to initialize the communicate header.
100 @retval EFI_INVALID_PARAMETER The data size is too big.
101 @retval EFI_SUCCESS Find the specified variable.
105 InitCommunicateBuffer (
106 OUT VOID
**CommunicateBuffer
,
112 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
113 SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*SmmFvbFunctionHeader
;
116 // The whole buffer size: SMM_COMMUNICATE_HEADER_SIZE + SMM_FVB_COMMUNICATE_HEADER_SIZE + DataSize.
118 SmmCommunicateHeader
= AllocatePool (DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_FVB_COMMUNICATE_HEADER_SIZE
);
119 ASSERT (SmmCommunicateHeader
!= NULL
);
122 // Prepare data buffer.
124 CopyGuid (&SmmCommunicateHeader
->HeaderGuid
, &gEfiSmmFirmwareVolumeBlockProtocolGuid
);
125 SmmCommunicateHeader
->MessageLength
= DataSize
+ SMM_FVB_COMMUNICATE_HEADER_SIZE
;
127 SmmFvbFunctionHeader
= (SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*) SmmCommunicateHeader
->Data
;
128 SmmFvbFunctionHeader
->Function
= Function
;
130 *CommunicateBuffer
= SmmCommunicateHeader
;
131 *DataPtr
= SmmFvbFunctionHeader
->Data
;
138 Send the data in communicate buffer to SMM.
140 @param[out] SmmCommunicateHeader The communicate buffer.
141 @param[in] DataSize The payload size.
145 SendCommunicateBuffer (
146 IN EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
,
152 SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*SmmFvbFunctionHeader
;
154 CommSize
= DataSize
+ SMM_COMMUNICATE_HEADER_SIZE
+ SMM_FVB_COMMUNICATE_HEADER_SIZE
;
155 Status
= mSmmCommunication
->Communicate (
157 SmmCommunicateHeader
,
160 ASSERT_EFI_ERROR (Status
);
162 SmmFvbFunctionHeader
= (SMM_FVB_COMMUNICATE_FUNCTION_HEADER
*) SmmCommunicateHeader
->Data
;
163 return SmmFvbFunctionHeader
->ReturnStatus
;
167 This function retrieves the attributes and current settings of the block.
169 @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
171 @param[out] Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes
172 and current settings are returned. Type EFI_FVB_ATTRIBUTES_2
173 is defined in EFI_FIRMWARE_VOLUME_HEADER.
175 @retval EFI_SUCCESS The firmware volume attributes were returned.
176 @retval EFI_INVALID_PARAMETER Attributes is NULL.
181 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
182 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
187 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
188 SMM_FVB_ATTRIBUTES_HEADER
*SmmFvbAttributesHeader
;
189 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
190 EFI_FVB_DEVICE
*FvbDevice
;
192 if (Attributes
== NULL
) {
193 return EFI_INVALID_PARAMETER
;
196 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
197 SmmFvb
= FvbDevice
->SmmFvbInstance
;
200 // Initialize the communicate buffer.
202 PayloadSize
= sizeof (SMM_FVB_ATTRIBUTES_HEADER
);
203 Status
= InitCommunicateBuffer (
204 (VOID
**)&SmmCommunicateHeader
,
205 (VOID
**)&SmmFvbAttributesHeader
,
207 EFI_FUNCTION_GET_ATTRIBUTES
209 if (EFI_ERROR (Status
)) {
213 SmmFvbAttributesHeader
->SmmFvb
= SmmFvb
;
214 SmmFvbAttributesHeader
->Attributes
= 0;
219 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
222 // Get data from SMM.
224 *Attributes
= SmmFvbAttributesHeader
->Attributes
;
225 FreePool (SmmCommunicateHeader
);
232 Sets Volume attributes. No polarity translations are done.
234 @param[in] This Calling context.
235 @param[out] Attributes Output buffer which contains attributes.
237 @retval EFI_SUCCESS Set the Attributes successfully.
238 @retval EFI_INVALID_PARAMETER Attributes is NULL.
244 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
245 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
250 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
251 SMM_FVB_ATTRIBUTES_HEADER
*SmmFvbAttributesHeader
;
252 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
253 EFI_FVB_DEVICE
*FvbDevice
;
255 if (Attributes
== NULL
) {
256 return EFI_INVALID_PARAMETER
;
259 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
260 SmmFvb
= FvbDevice
->SmmFvbInstance
;
263 // Initialize the communicate buffer.
265 PayloadSize
= sizeof (SMM_FVB_ATTRIBUTES_HEADER
);
266 Status
= InitCommunicateBuffer (
267 (VOID
**)&SmmCommunicateHeader
,
268 (VOID
**)&SmmFvbAttributesHeader
,
270 EFI_FUNCTION_SET_ATTRIBUTES
272 if (EFI_ERROR (Status
)) {
276 SmmFvbAttributesHeader
->SmmFvb
= SmmFvb
;
277 SmmFvbAttributesHeader
->Attributes
= *Attributes
;
282 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
285 // Get data from SMM.
287 *Attributes
= SmmFvbAttributesHeader
->Attributes
;
288 FreePool (SmmCommunicateHeader
);
295 Retrieves the physical address of the FVB instance.
297 @param[in] SmmFvb A pointer to EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
298 @param[out] Address Output buffer containing the address.
300 @retval EFI_SUCCESS Get the address successfully.
301 @retval Others Failed to get address.
306 IN EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
,
307 OUT EFI_PHYSICAL_ADDRESS
*Address
312 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
313 SMM_FVB_PHYSICAL_ADDRESS_HEADER
*SmmFvbPhysicalAddressHeader
;
316 // Initialize the communicate buffer.
318 PayloadSize
= sizeof (SMM_FVB_PHYSICAL_ADDRESS_HEADER
);
319 Status
= InitCommunicateBuffer (
320 (VOID
**)&SmmCommunicateHeader
,
321 (VOID
**)&SmmFvbPhysicalAddressHeader
,
323 EFI_FUNCTION_GET_PHYSICAL_ADDRESS
325 if (EFI_ERROR (Status
)) {
329 SmmFvbPhysicalAddressHeader
->SmmFvb
= SmmFvb
;
330 SmmFvbPhysicalAddressHeader
->Address
= 0;
335 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
338 // Get data from SMM.
340 *Address
= SmmFvbPhysicalAddressHeader
->Address
;
341 FreePool (SmmCommunicateHeader
);
348 Retrieves the physical address of the FVB instance.
350 @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL.
351 @param[out] Address Output buffer containing the address.
353 @retval EFI_SUCCESS Get the address successfully.
354 @retval Others Failed to get the address.
359 FvbGetPhysicalAddress (
360 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
361 OUT EFI_PHYSICAL_ADDRESS
*Address
365 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
366 EFI_FVB_DEVICE
*FvbDevice
;
368 if (Address
== NULL
) {
369 return EFI_INVALID_PARAMETER
;
372 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
373 SmmFvb
= FvbDevice
->SmmFvbInstance
;
375 Status
= GetPhysicalAddress (SmmFvb
, Address
);
382 Retrieve the size of a logical block.
384 @param[in] This Calling context.
385 @param[in] Lba Indicates which block to return the size for.
386 @param[out] BlockSize A pointer to a caller allocated UINTN in which
387 the size of the block is returned.
388 @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the
389 number of consecutive blocks starting with Lba is
390 returned. All blocks in this range have a size of
393 @retval EFI_SUCCESS Get BlockSize and NumOfBlocks successfully.
394 @retval EFI_INVALID_PARAMETER BlockSize or NumOfBlocks are NULL.
399 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
401 OUT UINTN
*BlockSize
,
402 OUT UINTN
*NumOfBlocks
407 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
408 SMM_FVB_BLOCK_SIZE_HEADER
*SmmFvbBlockSizeHeader
;
409 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
410 EFI_FVB_DEVICE
*FvbDevice
;
412 if ((BlockSize
== NULL
) || (NumOfBlocks
== NULL
)) {
413 return EFI_INVALID_PARAMETER
;
416 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
417 SmmFvb
= FvbDevice
->SmmFvbInstance
;
420 // Initialize the communicate buffer.
422 PayloadSize
= sizeof (SMM_FVB_BLOCK_SIZE_HEADER
);
423 Status
= InitCommunicateBuffer (
424 (VOID
**)&SmmCommunicateHeader
,
425 (VOID
**)&SmmFvbBlockSizeHeader
,
427 EFI_FUNCTION_GET_BLOCK_SIZE
429 if (EFI_ERROR (Status
)) {
433 SmmFvbBlockSizeHeader
->SmmFvb
= SmmFvb
;
434 SmmFvbBlockSizeHeader
->Lba
= Lba
;
439 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
442 // Get data from SMM.
444 *BlockSize
= SmmFvbBlockSizeHeader
->BlockSize
;
445 *NumOfBlocks
= SmmFvbBlockSizeHeader
->NumOfBlocks
;
446 FreePool (SmmCommunicateHeader
);
453 Reads data beginning at Lba:Offset from FV. The Read terminates either
454 when *NumBytes of data have been read, or when a block boundary is
455 reached. *NumBytes is updated to reflect the actual number of bytes
456 written. The write opertion does not include erase. This routine will
457 attempt to write only the specified bytes. If the writes do not stick,
458 it will return an error.
460 @param[in] This Calling context
461 @param[in] Lba Block in which to begin write
462 @param[in] Offset Offset in the block at which to begin write
463 @param[in,out] NumBytes On input, indicates the requested write size. On
464 output, indicates the actual number of bytes written
465 @param[in] Buffer Buffer containing source data for the write.
467 @retval EFI_SUCCESS The firmware volume was read successfully and
468 contents are in Buffer.
469 @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output,
470 NumBytes contains the total number of bytes returned
472 @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state
473 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
475 @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL.
481 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
484 IN OUT UINTN
*NumBytes
,
490 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
491 SMM_FVB_READ_WRITE_HEADER
*SmmFvbReadWriteHeader
;
492 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
493 EFI_FVB_DEVICE
*FvbDevice
;
495 if ((NumBytes
== NULL
) || (Buffer
== NULL
)) {
496 return EFI_INVALID_PARAMETER
;
499 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
500 SmmFvb
= FvbDevice
->SmmFvbInstance
;
503 // Initialize the communicate buffer.
505 PayloadSize
= sizeof (SMM_FVB_READ_WRITE_HEADER
) + *NumBytes
;
506 Status
= InitCommunicateBuffer (
507 (VOID
**)&SmmCommunicateHeader
,
508 (VOID
**)&SmmFvbReadWriteHeader
,
509 PayloadSize
, EFI_FUNCTION_READ
511 if (EFI_ERROR (Status
)) {
515 SmmFvbReadWriteHeader
->SmmFvb
= SmmFvb
;
516 SmmFvbReadWriteHeader
->Lba
= Lba
;
517 SmmFvbReadWriteHeader
->Offset
= Offset
;
518 SmmFvbReadWriteHeader
->NumBytes
= *NumBytes
;
523 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
526 // Get data from SMM.
528 *NumBytes
= SmmFvbReadWriteHeader
->NumBytes
;
529 if (!EFI_ERROR (Status
)) {
530 CopyMem (Buffer
, (UINT8
*)(SmmFvbReadWriteHeader
+ 1), *NumBytes
);
532 FreePool (SmmCommunicateHeader
);
539 Writes data beginning at Lba:Offset from FV. The write terminates either
540 when *NumBytes of data have been written, or when a block boundary is
541 reached. *NumBytes is updated to reflect the actual number of bytes
542 written. The write opertion does not include erase. This routine will
543 attempt to write only the specified bytes. If the writes do not stick,
544 it will return an error.
546 @param[in] This Calling context.
547 @param[in] Lba Block in which to begin write.
548 @param[in] Offset Offset in the block at which to begin write.
549 @param[in,out] NumBytes On input, indicates the requested write size. On
550 output, indicates the actual number of bytes written.
551 @param[in] Buffer Buffer containing source data for the write.
553 @retval EFI_SUCCESS The firmware volume was written successfully.
554 @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output,
555 NumBytes contains the total number of bytes
557 @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
558 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
559 could not be written.
560 @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL.
566 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
569 IN OUT UINTN
*NumBytes
,
575 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
576 SMM_FVB_READ_WRITE_HEADER
*SmmFvbReadWriteHeader
;
577 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
578 EFI_FVB_DEVICE
*FvbDevice
;
580 if ((NumBytes
== NULL
) || (Buffer
== NULL
)) {
581 return EFI_INVALID_PARAMETER
;
584 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
585 SmmFvb
= FvbDevice
->SmmFvbInstance
;
588 // Initialize the communicate buffer.
590 PayloadSize
= sizeof (SMM_FVB_READ_WRITE_HEADER
) + *NumBytes
;
591 Status
= InitCommunicateBuffer (
592 (VOID
**)&SmmCommunicateHeader
,
593 (VOID
**)&SmmFvbReadWriteHeader
,
597 if (EFI_ERROR (Status
)) {
601 SmmFvbReadWriteHeader
->SmmFvb
= SmmFvb
;
602 SmmFvbReadWriteHeader
->Lba
= Lba
;
603 SmmFvbReadWriteHeader
->Offset
= Offset
;
604 SmmFvbReadWriteHeader
->NumBytes
= *NumBytes
;
605 CopyMem ((UINT8
*)(SmmFvbReadWriteHeader
+ 1), Buffer
, *NumBytes
);
610 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
613 // Get data from SMM.
615 *NumBytes
= SmmFvbReadWriteHeader
->NumBytes
;
616 FreePool (SmmCommunicateHeader
);
623 The EraseBlock() function erases NumOfLba blocks started from StartingLba.
625 @param[in] This Calling context.
626 @param[in] StartingLba Starting LBA followed to erase.
627 @param[in] NumOfLba Number of block to erase.
629 @retval EFI_SUCCESS The erase request was successfully completed.
630 @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
631 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
632 could not be written. Firmware device may have been
638 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
639 IN EFI_LBA StartingLba
,
645 EFI_SMM_COMMUNICATE_HEADER
*SmmCommunicateHeader
;
646 SMM_FVB_BLOCKS_HEADER
*SmmFvbBlocksHeader
;
647 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
648 EFI_FVB_DEVICE
*FvbDevice
;
650 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
651 SmmFvb
= FvbDevice
->SmmFvbInstance
;
654 // Initialize the communicate buffer.
656 PayloadSize
= sizeof (SMM_FVB_BLOCKS_HEADER
);
657 Status
= InitCommunicateBuffer (
658 (VOID
**)&SmmCommunicateHeader
,
659 (VOID
**)&SmmFvbBlocksHeader
,
661 EFI_FUNCTION_ERASE_BLOCKS
663 if (EFI_ERROR (Status
)) {
667 SmmFvbBlocksHeader
->SmmFvb
= SmmFvb
;
668 SmmFvbBlocksHeader
->StartLba
= StartingLba
;
669 SmmFvbBlocksHeader
->NumOfLba
= NumOfLba
;
674 Status
= SendCommunicateBuffer (SmmCommunicateHeader
, PayloadSize
);
677 // Get data from SMM.
679 FreePool (SmmCommunicateHeader
);
686 The EraseBlocks() function erases one or more blocks as denoted by the
687 variable argument list. The entire parameter list of blocks must be verified
688 prior to erasing any blocks. If a block is requested that does not exist
689 within the associated firmware volume (it has a larger index than the last
690 block of the firmware volume), the EraseBlock() function must return
691 EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
693 @param[in] This Calling context/
694 @param[in] ... Starting LBA followed by Number of Lba to erase.
695 a -1 to terminate the list.
697 @retval EFI_SUCCESS The erase request was successfully completed
698 @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state/
699 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
700 could not be written. Firmware device may have been
707 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
716 Status
= EFI_SUCCESS
;
719 // Check the parameter.
721 VA_START (Marker
, This
);
723 StartingLba
= VA_ARG (Marker
, EFI_LBA
);
724 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
728 NumOfLba
= VA_ARG (Marker
, UINT32
);
730 return EFI_INVALID_PARAMETER
;
739 VA_START (Marker
, This
);
741 StartingLba
= VA_ARG (Marker
, EFI_LBA
);
742 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
745 NumOfLba
= VA_ARG (Marker
, UINT32
);
746 Status
= EraseBlock (This
, StartingLba
, NumOfLba
);
747 if (EFI_ERROR (Status
)) {
758 Install the FVB protocol which based on SMM FVB protocol.
760 @param[in] SmmFvb The SMM FVB protocol.
765 IN EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
769 EFI_HANDLE FvbHandle
;
770 EFI_FVB_DEVICE
*FvbDevice
;
771 EFI_FIRMWARE_VOLUME_HEADER
*VolumeHeader
;
772 EFI_PHYSICAL_ADDRESS Address
;
773 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*OldFvbInterface
;
775 FvbDevice
= AllocateRuntimeCopyPool (sizeof (EFI_FVB_DEVICE
), &mFvbDeviceTemplate
);
776 ASSERT (FvbDevice
!= NULL
);
777 FvbDevice
->SmmFvbInstance
= SmmFvb
;
779 Status
= gBS
->LocateProtocol (
780 &gEfiSmmCommunicationProtocolGuid
,
782 (VOID
**) &mSmmCommunication
784 ASSERT_EFI_ERROR (Status
);
786 Status
= GetPhysicalAddress (SmmFvb
, &Address
);
787 ASSERT_EFI_ERROR (Status
);
789 VolumeHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
)Address
;
792 // Set up the devicepath.
794 if (VolumeHeader
->ExtHeaderOffset
== 0) {
796 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH.
798 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH
), &mFvMemmapDevicePathTemplate
);
799 ((FV_MEMMAP_DEVICE_PATH
*) FvbDevice
->DevicePath
)->MemMapDevPath
.StartingAddress
= (UINTN
)Address
;
800 ((FV_MEMMAP_DEVICE_PATH
*) FvbDevice
->DevicePath
)->MemMapDevPath
.EndingAddress
= (UINTN
)Address
+ VolumeHeader
->FvLength
- 1;
802 FvbDevice
->DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH
), &mFvPIWGDevicePathTemplate
);
804 &((FV_PIWG_DEVICE_PATH
*)FvbDevice
->DevicePath
)->FvDevPath
.FvName
,
805 (GUID
*)(UINTN
)((UINTN
)Address
+ VolumeHeader
->ExtHeaderOffset
)
810 // Find a handle with a matching device path that has supports FW Block protocol.
812 Status
= gBS
->LocateDevicePath (
813 &gEfiFirmwareVolumeBlockProtocolGuid
,
814 &FvbDevice
->DevicePath
,
817 if (EFI_ERROR (Status
) ) {
819 // LocateDevicePath fails so install a new interface and device path.
822 Status
= gBS
->InstallMultipleProtocolInterfaces (
824 &gEfiFirmwareVolumeBlockProtocolGuid
,
825 &FvbDevice
->FvbInstance
,
826 &gEfiDevicePathProtocolGuid
,
827 FvbDevice
->DevicePath
,
830 ASSERT_EFI_ERROR (Status
);
831 } else if (IsDevicePathEnd (FvbDevice
->DevicePath
)) {
833 // Device allready exists, so reinstall the FVB protocol.
835 Status
= gBS
->HandleProtocol (
837 &gEfiFirmwareVolumeBlockProtocolGuid
,
838 (VOID
**) &OldFvbInterface
840 ASSERT_EFI_ERROR (Status
);
842 Status
= gBS
->ReinstallProtocolInterface (
844 &gEfiFirmwareVolumeBlockProtocolGuid
,
846 &FvbDevice
->FvbInstance
848 ASSERT_EFI_ERROR (Status
);
851 // There was a FVB protocol on an End Device Path node.
859 SMM Firmware Volume Block Protocol notification event handler.
861 Discover NV Variable Store and install Variable Write Arch Protocol.
863 @param[in] Event Event whose notification function is being invoked.
864 @param[in] Context Pointer to the notification function's context.
874 EFI_HANDLE
*HandleBuffer
;
877 EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*SmmFvb
;
880 // Locate all handles of Smm Fvb protocol.
882 Status
= gBS
->LocateHandleBuffer (
884 &gEfiSmmFirmwareVolumeBlockProtocolGuid
,
889 if (EFI_ERROR (Status
)) {
894 // Install FVB protocol.
896 for (Index
= 0; Index
< HandleCount
; Index
++) {
898 Status
= gBS
->HandleProtocol (
900 &gEfiSmmFirmwareVolumeBlockProtocolGuid
,
903 if (EFI_ERROR (Status
)) {
910 FreePool (HandleBuffer
);
915 The driver entry point for Firmware Volume Block Driver.
917 The function does the necessary initialization work
918 Firmware Volume Block Driver.
920 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
921 @param[in] SystemTable A pointer to the EFI system table.
923 @retval EFI_SUCCESS This funtion always return EFI_SUCCESS.
924 It will ASSERT on errors.
929 FvbSmmDxeInitialize (
930 IN EFI_HANDLE ImageHandle
,
931 IN EFI_SYSTEM_TABLE
*SystemTable
934 VOID
*SmmFvbRegistration
;
937 // Smm FVB driver is ready.
939 EfiCreateProtocolNotifyEvent (
940 &gEfiSmmFirmwareVolumeBlockProtocolGuid
,