2 Copyright (c) 2007, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include "FWBlockService.h"
21 #include "EfiFlashMap.h"
23 #include "FlashLayout.h"
25 ESAL_FWB_GLOBAL
*mFvbModuleGlobal
;
26 VOID
*mSFSRegistration
;
27 #define TRY_ASSIGN(var, value) if(var != NULL) {*var = value;}
29 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate
= {
37 sizeof (MEMMAP_DEVICE_PATH
),
47 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
49 sizeof (EFI_DEVICE_PATH_PROTOCOL
),
56 FvbProtocolGetAttributes
,
57 FvbProtocolSetAttributes
,
58 FvbProtocolGetPhysicalAddress
,
59 FvbProtocolGetBlockSize
,
62 FvbProtocolEraseBlocks
,
66 FvbExtendProtocolEraseCustomBlockRange
74 IN EFI_FW_VOL_INSTANCE
*FwhInstance
,
75 IN OUT UINTN
*NumBytes
,
81 Writes specified number of bytes from the input buffer to the address
96 CopyMem ((VOID
*) Address
, Buffer
, *NumBytes
);
98 if (!EfiAtRuntime () && (FwhInstance
->Device
!= NULL
)) {
99 Status
= FileOpen (FwhInstance
->Device
, FwhInstance
->MappedFile
, &File
, EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
);
100 ASSERT_EFI_ERROR (Status
);
101 if (!EFI_ERROR (Status
)) {
102 if (Address
- FwhInstance
->FvBase
[FVB_PHYSICAL
] < FwhInstance
->Offset
) {
104 BufferForFile
= FwhInstance
->FvBase
[FVB_PHYSICAL
] + FwhInstance
->Offset
;
105 Length
= *NumBytes
- (FwhInstance
->Offset
- (Address
- FwhInstance
->FvBase
[FVB_PHYSICAL
]));
107 FileOffset
= Address
- FwhInstance
->FvBase
[FVB_PHYSICAL
] - FwhInstance
->Offset
;
108 BufferForFile
= Address
;
112 Status
= FileWrite (File
, FileOffset
, BufferForFile
, Length
);
113 ASSERT_EFI_ERROR (Status
);
123 IN EFI_FW_VOL_INSTANCE
*FwhInstance
,
129 Erase a certain block from address LbaWriteAddress
143 Status
= EFI_SUCCESS
;
145 SetMem ((VOID
*)Address
, LbaLength
, 0xff);
147 if (!EfiAtRuntime () && (FwhInstance
->Device
!= NULL
)) {
148 Status
= FileOpen (FwhInstance
->Device
, FwhInstance
->MappedFile
, &File
, EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
);
149 ASSERT_EFI_ERROR (Status
);
150 if (!EFI_ERROR (Status
)) {
151 if (Address
- FwhInstance
->FvBase
[FVB_PHYSICAL
] < FwhInstance
->Offset
) {
153 BufferForFile
= FwhInstance
->FvBase
[FVB_PHYSICAL
] + FwhInstance
->Offset
;
154 Length
= LbaLength
- (FwhInstance
->Offset
- (Address
- FwhInstance
->FvBase
[FVB_PHYSICAL
]));
156 FileOffset
= Address
- FwhInstance
->FvBase
[FVB_PHYSICAL
] - FwhInstance
->Offset
;
157 BufferForFile
= Address
;
161 Status
= FileWrite (File
, FileOffset
, BufferForFile
, Length
);
162 ASSERT_EFI_ERROR (Status
);
171 FvbVirtualddressChangeEvent (
179 Fixup internal data so that EFI and SAL can be call in virtual mode.
180 Call the passed in Child Notify event and convert the mFvbModuleGlobal
181 date items to there virtual address.
183 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data
184 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common
189 (Standard EFI notify event - EFI_EVENT_NOTIFY)
197 EFI_FW_VOL_INSTANCE
*FwhInstance
;
200 EfiConvertPointer (0, (VOID
**) &mFvbModuleGlobal
->FvInstance
[FVB_VIRTUAL
]);
203 // Convert the base address of all the instances
206 FwhInstance
= mFvbModuleGlobal
->FvInstance
[FVB_PHYSICAL
];
207 while (Index
< mFvbModuleGlobal
->NumFv
) {
208 EfiConvertPointer (0, (VOID
**) &FwhInstance
->FvBase
[FVB_VIRTUAL
]);
209 FwhInstance
= (EFI_FW_VOL_INSTANCE
*) ((UINTN
)((UINT8
*)FwhInstance
) + FwhInstance
->VolumeHeader
.HeaderLength
210 + (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
)));
214 EfiConvertPointer (0, (VOID
**) &mFvbModuleGlobal
->FvbScratchSpace
[FVB_VIRTUAL
]);
215 EfiConvertPointer (0, (VOID
**) &mFvbModuleGlobal
);
221 IN ESAL_FWB_GLOBAL
*Global
,
222 OUT EFI_FW_VOL_INSTANCE
**FwhInstance
,
228 Retrieves the physical address of a memory mapped FV
231 Instance - The FV instance whose base address is going to be
233 Global - Pointer to ESAL_FWB_GLOBAL that contains all
235 FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure
236 Virtual - Whether CPU is in virtual or physical mode
239 EFI_SUCCESS - Successfully returns
240 EFI_INVALID_PARAMETER - Instance not found
244 EFI_FW_VOL_INSTANCE
*FwhRecord
;
246 if (Instance
>= Global
->NumFv
) {
247 return EFI_INVALID_PARAMETER
;
250 // Find the right instance of the FVB private data
252 FwhRecord
= Global
->FvInstance
[Virtual
];
253 while (Instance
> 0) {
254 FwhRecord
= (EFI_FW_VOL_INSTANCE
*) ((UINTN
)((UINT8
*)FwhRecord
) + FwhRecord
->VolumeHeader
.HeaderLength
255 + (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
)));
259 *FwhInstance
= FwhRecord
;
265 FvbGetPhysicalAddress (
267 OUT EFI_PHYSICAL_ADDRESS
*Address
,
268 IN ESAL_FWB_GLOBAL
*Global
,
274 Retrieves the physical address of a memory mapped FV
277 Instance - The FV instance whose base address is going to be
279 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
280 that on successful return, contains the base address
281 of the firmware volume.
282 Global - Pointer to ESAL_FWB_GLOBAL that contains all
284 Virtual - Whether CPU is in virtual or physical mode
287 EFI_SUCCESS - Successfully returns
288 EFI_INVALID_PARAMETER - Instance not found
292 EFI_FW_VOL_INSTANCE
*FwhInstance
;
296 // Find the right instance of the FVB private data
298 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
, Virtual
);
299 ASSERT_EFI_ERROR (Status
);
300 *Address
= FwhInstance
->FvBase
[Virtual
];
306 FvbGetVolumeAttributes (
308 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
309 IN ESAL_FWB_GLOBAL
*Global
,
315 Retrieves attributes, insures positive polarity of attribute bits, returns
316 resulting attributes in output parameter
319 Instance - The FV instance whose attributes is going to be
321 Attributes - Output buffer which contains attributes
322 Global - Pointer to ESAL_FWB_GLOBAL that contains all
324 Virtual - Whether CPU is in virtual or physical mode
327 EFI_SUCCESS - Successfully returns
328 EFI_INVALID_PARAMETER - Instance not found
332 EFI_FW_VOL_INSTANCE
*FwhInstance
;
336 // Find the right instance of the FVB private data
338 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
, Virtual
);
339 ASSERT_EFI_ERROR (Status
);
340 *Attributes
= FwhInstance
->VolumeHeader
.Attributes
;
349 OUT UINTN
*LbaAddress OPTIONAL
,
350 OUT UINTN
*LbaLength OPTIONAL
,
351 OUT UINTN
*NumOfBlocks OPTIONAL
,
352 IN ESAL_FWB_GLOBAL
*Global
,
358 Retrieves the starting address of an LBA in an FV
361 Instance - The FV instance which the Lba belongs to
362 Lba - The logical block address
363 LbaAddress - On output, contains the physical starting address
364 of the Lba for writing
365 LbaLength - On output, contains the length of the block
366 NumOfBlocks - A pointer to a caller allocated UINTN in which the
367 number of consecutive blocks starting with Lba is
368 returned. All blocks in this range have a size of
370 Global - Pointer to ESAL_FWB_GLOBAL that contains all
372 Virtual - Whether CPU is in virtual or physical mode
375 EFI_SUCCESS - Successfully returns
376 EFI_INVALID_PARAMETER - Instance not found
385 EFI_FW_VOL_INSTANCE
*FwhInstance
;
386 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
390 // Find the right instance of the FVB private data
392 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
, Virtual
);
393 ASSERT_EFI_ERROR (Status
);
397 BlockMap
= &(FwhInstance
->VolumeHeader
.BlockMap
[0]);
400 // Parse the blockmap of the FV to find which map entry the Lba belongs to
403 NumBlocks
= BlockMap
->NumBlocks
;
404 BlockLength
= BlockMap
->Length
;
406 if (NumBlocks
== 0 || BlockLength
== 0) {
407 return EFI_INVALID_PARAMETER
;
410 NextLba
= StartLba
+ NumBlocks
;
413 // The map entry found
415 if (Lba
>= StartLba
&& Lba
< NextLba
) {
416 Offset
= Offset
+ (UINTN
) MultU64x32 ((Lba
- StartLba
), BlockLength
);
419 *LbaAddress
= FwhInstance
->FvBase
[Virtual
] + Offset
;
423 *LbaLength
= BlockLength
;
427 *NumOfBlocks
= (UINTN
) (NextLba
- Lba
);
434 Offset
= Offset
+ NumBlocks
* BlockLength
;
443 IN UINTN BlockOffset
,
444 IN OUT UINTN
*NumBytes
,
446 IN ESAL_FWB_GLOBAL
*Global
,
452 Reads specified number of bytes into a buffer from the specified block
455 Instance - The FV instance to be read from
456 Lba - The logical block address to be read from
457 BlockOffset - Offset into the block at which to begin reading
458 NumBytes - Pointer that on input contains the total size of
459 the buffer. On output, it contains the total number
461 Buffer - Pointer to a caller allocated buffer that will be
462 used to hold the data read
463 Global - Pointer to ESAL_FWB_GLOBAL that contains all
465 Virtual - Whether CPU is in virtual or physical mode
468 EFI_SUCCESS - The firmware volume was read successfully and
469 contents are in Buffer
470 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
471 NumBytes contains the total number of bytes returned
473 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
474 EFI_DEVICE_ERROR - The block device is not functioning correctly and
476 EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
480 EFI_FVB_ATTRIBUTES_2 Attributes
;
486 // Check for invalid conditions
488 if ((NumBytes
== NULL
) || (Buffer
== NULL
)) {
489 return EFI_INVALID_PARAMETER
;
492 if (*NumBytes
== 0) {
493 return EFI_INVALID_PARAMETER
;
496 Status
= FvbGetLbaAddress (Instance
, Lba
, &LbaAddress
, &LbaLength
, NULL
, Global
, Virtual
);
497 if (EFI_ERROR (Status
)) {
501 // Check if the FV is read enabled
503 FvbGetVolumeAttributes (Instance
, &Attributes
, Global
, Virtual
);
505 if ((Attributes
& EFI_FVB2_READ_STATUS
) == 0) {
506 return EFI_ACCESS_DENIED
;
509 // Perform boundary checks and adjust NumBytes
511 if (BlockOffset
> LbaLength
) {
512 return EFI_INVALID_PARAMETER
;
515 if (LbaLength
< (*NumBytes
+ BlockOffset
)) {
516 *NumBytes
= (UINT32
) (LbaLength
- BlockOffset
);
517 Status
= EFI_BAD_BUFFER_SIZE
;
520 CopyMem (Buffer
, (VOID
*) (LbaAddress
+ BlockOffset
), (UINTN
) *NumBytes
);
528 IN UINTN BlockOffset
,
529 IN OUT UINTN
*NumBytes
,
531 IN ESAL_FWB_GLOBAL
*Global
,
537 Writes specified number of bytes from the input buffer to the block
540 Instance - The FV instance to be written to
541 Lba - The starting logical block index to write to
542 BlockOffset - Offset into the block at which to begin writing
543 NumBytes - Pointer that on input contains the total size of
544 the buffer. On output, it contains the total number
545 of bytes actually written
546 Buffer - Pointer to a caller allocated buffer that contains
547 the source for the write
548 Global - Pointer to ESAL_FWB_GLOBAL that contains all
550 Virtual - Whether CPU is in virtual or physical mode
553 EFI_SUCCESS - The firmware volume was written successfully
554 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
555 NumBytes contains the total number of bytes
557 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
558 EFI_DEVICE_ERROR - The block device is not functioning correctly and
560 EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
564 EFI_FVB_ATTRIBUTES_2 Attributes
;
567 EFI_FW_VOL_INSTANCE
*FwhInstance
;
569 EFI_STATUS ReturnStatus
;
572 // Find the right instance of the FVB private data
574 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
, Virtual
);
575 ASSERT_EFI_ERROR (Status
);
578 // Writes are enabled in the init routine itself
580 if (!FwhInstance
->WriteEnabled
) {
581 return EFI_ACCESS_DENIED
;
584 // Check for invalid conditions
586 if ((NumBytes
== NULL
) || (Buffer
== NULL
)) {
587 return EFI_INVALID_PARAMETER
;
590 if (*NumBytes
== 0) {
591 return EFI_INVALID_PARAMETER
;
594 Status
= FvbGetLbaAddress (Instance
, Lba
, &LbaAddress
, &LbaLength
, NULL
, Global
, Virtual
);
595 if (EFI_ERROR (Status
)) {
599 // Check if the FV is write enabled
601 FvbGetVolumeAttributes (Instance
, &Attributes
, Global
, Virtual
);
603 if ((Attributes
& EFI_FVB2_WRITE_STATUS
) == 0) {
604 return EFI_ACCESS_DENIED
;
607 // Perform boundary checks and adjust NumBytes
609 if (BlockOffset
> LbaLength
) {
610 return EFI_INVALID_PARAMETER
;
613 if (LbaLength
< (*NumBytes
+ BlockOffset
)) {
614 *NumBytes
= (UINT32
) (LbaLength
- BlockOffset
);
615 Status
= EFI_BAD_BUFFER_SIZE
;
618 ReturnStatus
= FlashFdWrite (
619 LbaAddress
+ BlockOffset
,
624 if (EFI_ERROR (ReturnStatus
)) {
635 IN ESAL_FWB_GLOBAL
*Global
,
641 Erases and initializes a firmware volume block
644 Instance - The FV instance to be erased
645 Lba - The logical block index to be erased
646 Global - Pointer to ESAL_FWB_GLOBAL that contains all
648 Virtual - Whether CPU is in virtual or physical mode
651 EFI_SUCCESS - The erase request was successfully completed
652 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
653 EFI_DEVICE_ERROR - The block device is not functioning correctly and
654 could not be written. Firmware device may have been
656 EFI_INVALID_PARAMETER - Instance not found
661 EFI_FVB_ATTRIBUTES_2 Attributes
;
663 EFI_FW_VOL_INSTANCE
*FwhInstance
;
668 // Find the right instance of the FVB private data
670 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
, Virtual
);
671 ASSERT_EFI_ERROR (Status
);
674 // Writes are enabled in the init routine itself
676 if (!FwhInstance
->WriteEnabled
) {
677 return EFI_ACCESS_DENIED
;
680 // Check if the FV is write enabled
682 FvbGetVolumeAttributes (Instance
, &Attributes
, Global
, Virtual
);
684 if ((Attributes
& EFI_FVB2_WRITE_STATUS
) == 0) {
685 return EFI_ACCESS_DENIED
;
688 // Get the starting address of the block for erase. For debug reasons,
689 // LbaWriteAddress may not be the same as LbaAddress.
691 Status
= FvbGetLbaAddress (Instance
, Lba
, &LbaAddress
, &LbaLength
, NULL
, Global
, Virtual
);
692 if (EFI_ERROR (Status
)) {
696 return FlashFdErase (
704 FvbEraseCustomBlockRange (
707 IN UINTN OffsetStartLba
,
709 IN UINTN OffsetLastLba
,
710 IN ESAL_FWB_GLOBAL
*Global
,
716 Erases and initializes a specified range of a firmware volume
719 Instance - The FV instance to be erased
720 StartLba - The starting logical block index to be erased
721 OffsetStartLba - Offset into the starting block at which to
723 LastLba - The last logical block index to be erased
724 OffsetStartLba - Offset into the last block at which to end erasing
725 Global - Pointer to ESAL_FWB_GLOBAL that contains all
727 Virtual - Whether CPU is in virtual or physical mode
730 EFI_SUCCESS - The firmware volume was erased successfully
731 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
732 EFI_DEVICE_ERROR - The block device is not functioning correctly and
733 could not be written. Firmware device may have been
735 EFI_INVALID_PARAMETER - Instance not found
741 UINTN ScratchLbaSizeData
;
746 FvbGetLbaAddress (Instance
, StartLba
, NULL
, &LbaSize
, NULL
, Global
, Virtual
);
749 // Use the scratch space as the intermediate buffer to transfer data
750 // Back up the first LBA in scratch space.
752 FvbReadBlock (Instance
, StartLba
, 0, &LbaSize
, Global
->FvbScratchSpace
[Virtual
], Global
, Virtual
);
757 FvbEraseBlock (Instance
, StartLba
, Global
, Virtual
);
758 ScratchLbaSizeData
= OffsetStartLba
;
761 // write the data back to the first block
763 if (ScratchLbaSizeData
> 0) {
764 FvbWriteBlock (Instance
, StartLba
, 0, &ScratchLbaSizeData
, Global
->FvbScratchSpace
[Virtual
], Global
, Virtual
);
769 if (LastLba
> (StartLba
+ 1)) {
770 for (Index
= (StartLba
+ 1); Index
<= (LastLba
- 1); Index
++) {
771 FvbEraseBlock (Instance
, Index
, Global
, Virtual
);
775 // Last LBAs, the same as first LBAs
777 if (LastLba
> StartLba
) {
778 FvbGetLbaAddress (Instance
, LastLba
, NULL
, &LbaSize
, NULL
, Global
, Virtual
);
779 FvbReadBlock (Instance
, LastLba
, 0, &LbaSize
, Global
->FvbScratchSpace
[Virtual
], Global
, Virtual
);
780 FvbEraseBlock (Instance
, LastLba
, Global
, Virtual
);
783 ScratchLbaSizeData
= LbaSize
- (OffsetStartLba
+ 1);
785 return FvbWriteBlock (
790 Global
->FvbScratchSpace
[Virtual
],
797 FvbSetVolumeAttributes (
799 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
,
800 IN ESAL_FWB_GLOBAL
*Global
,
806 Modifies the current settings of the firmware volume according to the
807 input parameter, and returns the new setting of the volume
810 Instance - The FV instance whose attributes is going to be
812 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
813 containing the desired firmware volume settings.
814 On successful return, it contains the new settings
815 of the firmware volume
816 Global - Pointer to ESAL_FWB_GLOBAL that contains all
818 Virtual - Whether CPU is in virtual or physical mode
821 EFI_SUCCESS - Successfully returns
822 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
823 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
824 in conflict with the capabilities as declared in the
825 firmware volume header
829 EFI_FW_VOL_INSTANCE
*FwhInstance
;
830 EFI_FVB_ATTRIBUTES_2 OldAttributes
;
831 EFI_FVB_ATTRIBUTES_2
*AttribPtr
;
838 // Find the right instance of the FVB private data
840 Status
= GetFvbInstance (Instance
, Global
, &FwhInstance
, Virtual
);
841 ASSERT_EFI_ERROR (Status
);
843 AttribPtr
= (EFI_FVB_ATTRIBUTES_2
*) &(FwhInstance
->VolumeHeader
.Attributes
);
844 OldAttributes
= *AttribPtr
;
845 Capabilities
= OldAttributes
& EFI_FVB2_CAPABILITIES
;
846 OldStatus
= OldAttributes
& EFI_FVB2_STATUS
;
847 NewStatus
= *Attributes
& EFI_FVB2_STATUS
;
850 // If firmware volume is locked, no status bit can be updated
852 if (OldAttributes
& EFI_FVB2_LOCK_STATUS
) {
853 if (OldStatus
^ NewStatus
) {
854 return EFI_ACCESS_DENIED
;
860 if ((Capabilities
& EFI_FVB2_READ_DISABLED_CAP
) == 0) {
861 if ((NewStatus
& EFI_FVB2_READ_STATUS
) == 0) {
862 return EFI_INVALID_PARAMETER
;
868 if ((Capabilities
& EFI_FVB2_READ_ENABLED_CAP
) == 0) {
869 if (NewStatus
& EFI_FVB2_READ_STATUS
) {
870 return EFI_INVALID_PARAMETER
;
874 // Test write disable
876 if ((Capabilities
& EFI_FVB2_WRITE_DISABLED_CAP
) == 0) {
877 if ((NewStatus
& EFI_FVB2_WRITE_STATUS
) == 0) {
878 return EFI_INVALID_PARAMETER
;
884 if ((Capabilities
& EFI_FVB2_WRITE_ENABLED_CAP
) == 0) {
885 if (NewStatus
& EFI_FVB2_WRITE_STATUS
) {
886 return EFI_INVALID_PARAMETER
;
892 if ((Capabilities
& EFI_FVB2_LOCK_CAP
) == 0) {
893 if (NewStatus
& EFI_FVB2_LOCK_STATUS
) {
894 return EFI_INVALID_PARAMETER
;
898 *AttribPtr
= (*AttribPtr
) & (0xFFFFFFFF & (~EFI_FVB2_STATUS
));
899 *AttribPtr
= (*AttribPtr
) | NewStatus
;
900 *Attributes
= *AttribPtr
;
909 FvbProtocolGetPhysicalAddress (
910 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
911 OUT EFI_PHYSICAL_ADDRESS
*Address
917 Retrieves the physical address of the device.
921 This - Calling context
922 Address - Output buffer containing the address.
927 EFI_SUCCESS - Successfully returns
931 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
933 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
935 return FvbGetPhysicalAddress (FvbDevice
->Instance
, Address
, mFvbModuleGlobal
, EfiGoneVirtual ());
940 FvbProtocolGetBlockSize (
941 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
943 OUT UINTN
*BlockSize
,
944 OUT UINTN
*NumOfBlocks
949 Retrieve the size of a logical block
952 This - Calling context
953 Lba - Indicates which block to return the size for.
954 BlockSize - A pointer to a caller allocated UINTN in which
955 the size of the block is returned
956 NumOfBlocks - a pointer to a caller allocated UINTN in which the
957 number of consecutive blocks starting with Lba is
958 returned. All blocks in this range have a size of
962 EFI_SUCCESS - The firmware volume was read successfully and
963 contents are in Buffer
967 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
969 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
971 return FvbGetLbaAddress (
984 FvbProtocolGetAttributes (
985 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
986 OUT EFI_FVB_ATTRIBUTES_2
*Attributes
991 Retrieves Volume attributes. No polarity translations are done.
994 This - Calling context
995 Attributes - output buffer which contains attributes
998 EFI_SUCCESS - Successfully returns
1002 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1004 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
1006 return FvbGetVolumeAttributes (FvbDevice
->Instance
, Attributes
, mFvbModuleGlobal
, EfiGoneVirtual ());
1011 FvbProtocolSetAttributes (
1012 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
1013 IN OUT EFI_FVB_ATTRIBUTES_2
*Attributes
1017 Routine Description:
1018 Sets Volume attributes. No polarity translations are done.
1021 This - Calling context
1022 Attributes - output buffer which contains attributes
1025 EFI_SUCCESS - Successfully returns
1029 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1031 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
1033 return FvbSetVolumeAttributes (FvbDevice
->Instance
, Attributes
, mFvbModuleGlobal
, EfiGoneVirtual ());
1038 FvbProtocolEraseBlocks (
1039 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
1044 Routine Description:
1046 The EraseBlock() function erases one or more blocks as denoted by the
1047 variable argument list. The entire parameter list of blocks must be verified
1048 prior to erasing any blocks. If a block is requested that does not exist
1049 within the associated firmware volume (it has a larger index than the last
1050 block of the firmware volume), the EraseBlock() function must return
1051 EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
1054 This - Calling context
1055 ... - Starting LBA followed by Number of Lba to erase.
1056 a -1 to terminate the list.
1059 EFI_SUCCESS - The erase request was successfully completed
1060 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
1061 EFI_DEVICE_ERROR - The block device is not functioning correctly and
1062 could not be written. Firmware device may have been
1067 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1068 EFI_FW_VOL_INSTANCE
*FwhInstance
;
1071 EFI_LBA StartingLba
;
1075 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
1077 Status
= GetFvbInstance (FvbDevice
->Instance
, mFvbModuleGlobal
, &FwhInstance
, EfiGoneVirtual ());
1078 ASSERT_EFI_ERROR (Status
);
1080 NumOfBlocks
= FwhInstance
->NumOfBlocks
;
1082 VA_START (args
, This
);
1085 StartingLba
= VA_ARG (args
, EFI_LBA
);
1086 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
1090 NumOfLba
= VA_ARG (args
, UINT32
);
1093 // Check input parameters
1095 if ((NumOfLba
== 0) || ((StartingLba
+ NumOfLba
) > NumOfBlocks
)) {
1097 return EFI_INVALID_PARAMETER
;
1103 VA_START (args
, This
);
1105 StartingLba
= VA_ARG (args
, EFI_LBA
);
1106 if (StartingLba
== EFI_LBA_LIST_TERMINATOR
) {
1110 NumOfLba
= VA_ARG (args
, UINT32
);
1112 while (NumOfLba
> 0) {
1113 Status
= FvbEraseBlock (FvbDevice
->Instance
, StartingLba
, mFvbModuleGlobal
, EfiGoneVirtual ());
1114 if (EFI_ERROR (Status
)) {
1133 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
1136 IN OUT UINTN
*NumBytes
,
1141 Routine Description:
1143 Writes data beginning at Lba:Offset from FV. The write terminates either
1144 when *NumBytes of data have been written, or when a block boundary is
1145 reached. *NumBytes is updated to reflect the actual number of bytes
1146 written. The write opertion does not include erase. This routine will
1147 attempt to write only the specified bytes. If the writes do not stick,
1148 it will return an error.
1151 This - Calling context
1152 Lba - Block in which to begin write
1153 Offset - Offset in the block at which to begin write
1154 NumBytes - On input, indicates the requested write size. On
1155 output, indicates the actual number of bytes written
1156 Buffer - Buffer containing source data for the write.
1159 EFI_SUCCESS - The firmware volume was written successfully
1160 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
1161 NumBytes contains the total number of bytes
1163 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
1164 EFI_DEVICE_ERROR - The block device is not functioning correctly and
1165 could not be written
1166 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
1171 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1173 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
1175 return FvbWriteBlock (FvbDevice
->Instance
, Lba
, Offset
, NumBytes
, Buffer
, mFvbModuleGlobal
, EfiGoneVirtual ());
1181 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*This
,
1184 IN OUT UINTN
*NumBytes
,
1189 Routine Description:
1191 Reads data beginning at Lba:Offset from FV. The Read terminates either
1192 when *NumBytes of data have been read, or when a block boundary is
1193 reached. *NumBytes is updated to reflect the actual number of bytes
1194 written. The write opertion does not include erase. This routine will
1195 attempt to write only the specified bytes. If the writes do not stick,
1196 it will return an error.
1199 This - Calling context
1200 Lba - Block in which to begin Read
1201 Offset - Offset in the block at which to begin Read
1202 NumBytes - On input, indicates the requested write size. On
1203 output, indicates the actual number of bytes Read
1204 Buffer - Buffer containing source data for the Read.
1207 EFI_SUCCESS - The firmware volume was read successfully and
1208 contents are in Buffer
1209 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
1210 NumBytes contains the total number of bytes returned
1212 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
1213 EFI_DEVICE_ERROR - The block device is not functioning correctly and
1215 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
1220 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1222 FvbDevice
= FVB_DEVICE_FROM_THIS (This
);
1224 return FvbReadBlock (FvbDevice
->Instance
, Lba
, Offset
, NumBytes
, Buffer
, mFvbModuleGlobal
, EfiGoneVirtual ());
1227 // FVB Extension Protocols
1231 FvbExtendProtocolEraseCustomBlockRange (
1232 IN EFI_FVB_EXTENSION_PROTOCOL
*This
,
1233 IN EFI_LBA StartLba
,
1234 IN UINTN OffsetStartLba
,
1236 IN UINTN OffsetLastLba
1240 Routine Description:
1241 Erases and initializes a specified range of a firmware volume
1244 This - Calling context
1245 StartLba - The starting logical block index to be erased
1246 OffsetStartLba - Offset into the starting block at which to
1248 LastLba - The last logical block index to be erased
1249 OffsetStartLba - Offset into the last block at which to end erasing
1252 EFI_SUCCESS - The firmware volume was erased successfully
1253 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
1254 EFI_DEVICE_ERROR - The block device is not functioning correctly and
1255 could not be written. Firmware device may have been
1260 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1262 FvbDevice
= FVB_EXTEND_DEVICE_FROM_THIS (This
);
1264 return FvbEraseCustomBlockRange (
1265 FvbDevice
->Instance
,
1277 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
1281 Routine Description:
1282 Check the integrity of firmware volume header
1285 FwVolHeader - A pointer to a firmware volume header
1288 EFI_SUCCESS - The firmware volume is consistent
1289 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV
1294 UINT16 HeaderLength
;
1298 // Verify the header revision, header signature, length
1299 // Length of FvBlock cannot be 2**64-1
1300 // HeaderLength cannot be an odd number
1302 if ((FwVolHeader
->Revision
!= EFI_FVH_REVISION
) ||
1303 (FwVolHeader
->Signature
!= EFI_FVH_SIGNATURE
) ||
1304 (FwVolHeader
->FvLength
== ((UINTN
) -1)) ||
1305 ((FwVolHeader
->HeaderLength
& 0x01) != 0)
1307 return EFI_NOT_FOUND
;
1310 // Verify the header checksum
1312 HeaderLength
= (UINT16
) (FwVolHeader
->HeaderLength
/ 2);
1313 Ptr
= (UINT16
*) FwVolHeader
;
1315 while (HeaderLength
> 0) {
1316 Checksum
= Checksum
+ (*Ptr
);
1321 if (Checksum
!= 0) {
1322 return EFI_NOT_FOUND
;
1331 IN OUT EFI_PEI_HOB_POINTERS
*HobList
,
1332 OUT EFI_FIRMWARE_VOLUME_HEADER
**FwVolHeader
,
1333 OUT EFI_PHYSICAL_ADDRESS
*BaseAddress OPTIONAL
,
1334 OUT UINT32
*VolumeId OPTIONAL
,
1335 OUT CHAR16
**MappedFile OPTIONAL
,
1336 OUT UINT32
*ActuralSize OPTIONAL
,
1337 OUT UINT32
*Offset OPTIONAL
,
1338 OUT BOOLEAN
*WriteBack OPTIONAL
1342 EFI_FLASH_MAP_FS_ENTRY_DATA
*FlashMapEntry
;
1343 EFI_FLASH_SUBAREA_ENTRY
*FlashMapSubEntry
;
1345 Status
= EFI_SUCCESS
;
1346 *FwVolHeader
= NULL
;
1347 TRY_ASSIGN (WriteBack
, FALSE
);
1349 DEBUG ((EFI_D_INFO
, "Hob start is 0x%x\n", (UINTN
)(*HobList
).Raw
));
1350 (*HobList
).Raw
= GetNextGuidHob (&gEfiFlashMapHobGuid
, (*HobList
).Raw
);
1351 if ((*HobList
).Raw
== NULL
) {
1352 return EFI_NOT_FOUND
;
1355 FlashMapEntry
= (EFI_FLASH_MAP_FS_ENTRY_DATA
*) GET_GUID_HOB_DATA ((*HobList
).Guid
);
1356 FlashMapSubEntry
= &FlashMapEntry
->Entries
[0];
1359 // Check if it is a "FVB" area
1361 if (!CompareGuid (&FlashMapSubEntry
->FileSystem
, &gEfiFirmwareVolumeBlockProtocolGuid
)) {
1365 // Check if it is a "real" flash
1367 if (FlashMapSubEntry
->Attributes
!= (EFI_FLASH_AREA_FV
| EFI_FLASH_AREA_MEMMAPPED_FV
)) {
1371 TRY_ASSIGN (BaseAddress
, FlashMapSubEntry
->Base
);
1374 // Cast buffer to FLASH_AREA_INFO to get extra information related to the special FVB driver
1376 TRY_ASSIGN (VolumeId
, FlashMapEntry
->VolumeId
);
1377 TRY_ASSIGN (ActuralSize
, FlashMapEntry
->ActuralSize
);
1378 TRY_ASSIGN (MappedFile
, ((CHAR16
*) FlashMapEntry
->FilePath
));
1379 TRY_ASSIGN (Offset
, FlashMapEntry
->Offset
);
1383 "FlashMap HOB: BaseAddress = 0x%x, Length = 0x%x, ActuralLength = 0x%x, Offset = 0x%x\n",
1384 (UINTN
) FlashMapSubEntry
->Base
, (UINTN
) FlashMapSubEntry
->Length
,
1385 (UINTN
) FlashMapEntry
->ActuralSize
, (UINTN
) FlashMapEntry
->Offset
1389 "FlashMap HOB: VolumeId = 0x%lx, MappedFile = %s\n",
1390 (UINTN
) FlashMapEntry
->VolumeId
, (UINTN
) FlashMapEntry
->FilePath
1392 *FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) (FlashMapSubEntry
->Base
);
1393 Status
= ValidateFvHeader (*FwVolHeader
);
1394 if (EFI_ERROR (Status
)) {
1398 TRY_ASSIGN (WriteBack
, TRUE
);
1399 Status
= GetFvbInfo (FlashMapSubEntry
->Length
, FwVolHeader
);
1400 DEBUG ((EFI_D_ERROR
, "Fvb: FV header invalid, GetFvbInfo - %r\n", Status
));
1401 ASSERT_EFI_ERROR (Status
);
1409 OnSimpleFileSystemInstall (
1418 EFI_DEVICE_PATH_PROTOCOL
*Device
;
1420 EFI_FW_VOL_INSTANCE
*FwhInstance
;
1422 HandleSize
= sizeof (EFI_HANDLE
);
1423 Status
= gBS
->LocateHandle (
1430 if (Status
== EFI_NOT_FOUND
) {
1433 DEBUG ((EFI_D_ERROR
, "Fwh: New FileSystem Installed!\n"));
1434 ASSERT_EFI_ERROR (Status
);
1436 // Check if this is the storage we care about, and store it in FwhInstance
1438 for (Instance
= 0; Instance
< mFvbModuleGlobal
->NumFv
; ++Instance
) {
1439 Status
= GetFvbInstance (Instance
, mFvbModuleGlobal
, &FwhInstance
, FALSE
);
1440 ASSERT_EFI_ERROR (Status
);
1442 if (FwhInstance
->MappedFile
[0] == L
'\0') {
1444 // The instance of FVB isn't mapped to file.
1449 if ((FwhInstance
->Device
!= NULL
) &&
1450 !EFI_ERROR (CheckStoreExists (FwhInstance
->Device
))
1453 // The instance of FVB has already associated to a device
1454 // and the device is not removed from system.
1457 EFI_D_ERROR
, "Fwh: MappedFile FVB (0x%x:0x%x) - Already mapped, Skip!\n",
1458 (UINTN
) FwhInstance
->FvBase
[FVB_PHYSICAL
],
1459 (UINTN
) FwhInstance
->Offset
1464 Status
= CheckStore (Handle
, FwhInstance
->VolumeId
, &Device
);
1465 if (!EFI_ERROR (Status
)) {
1467 // Write back memory content to file
1469 Status
= FileOpen (Device
, FwhInstance
->MappedFile
, &File
, EFI_FILE_MODE_WRITE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_CREATE
);
1470 ASSERT_EFI_ERROR (Status
);
1471 if (!EFI_ERROR (Status
)) {
1473 EFI_D_ERROR
, "Fwh: MappedFile FVB (0x%x:0x%x) - Write back to mapped file!\n",
1474 (UINTN
) FwhInstance
->FvBase
[FVB_PHYSICAL
],
1475 (UINTN
) FwhInstance
->Offset
1477 Status
= FileWrite (
1480 FwhInstance
->FvBase
[FVB_PHYSICAL
] + FwhInstance
->Offset
,
1481 FwhInstance
->ActuralSize
- FwhInstance
->Offset
1483 ASSERT_EFI_ERROR (Status
);
1484 if (!EFI_ERROR (Status
)) {
1485 if (FwhInstance
->Device
!= NULL
) {
1486 gBS
->FreePool (FwhInstance
->Device
);
1488 FwhInstance
->Device
= Device
;
1490 EFI_D_ERROR
, "Fwh: MappedFile FVB (0x%x:0x%x) - Mapped!\n",
1491 (UINTN
) FwhInstance
->FvBase
[FVB_PHYSICAL
],
1492 (UINTN
) FwhInstance
->Offset
1503 FvbInstallSfsNotify (
1510 Status
= gBS
->CreateEvent (
1513 OnSimpleFileSystemInstall
,
1517 ASSERT_EFI_ERROR (Status
);
1519 Status
= gBS
->RegisterProtocolNotify (
1520 &gEfiSimpleFileSystemProtocolGuid
,
1524 ASSERT_EFI_ERROR (Status
);
1531 IN EFI_HANDLE ImageHandle
,
1532 IN EFI_SYSTEM_TABLE
*SystemTable
1536 Routine Description:
1537 This function does common initialization for FVB services
1546 EFI_FW_VOL_INSTANCE
*FwhInstance
;
1547 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1548 EFI_PEI_HOB_POINTERS FirmwareVolumeHobList
;
1550 EFI_FV_BLOCK_MAP_ENTRY
*PtrBlockMapEntry
;
1552 EFI_HANDLE FwbHandle
;
1553 EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
;
1554 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*OldFwbInterface
;
1555 EFI_DEVICE_PATH_PROTOCOL
*TempFwbDevicePath
;
1556 FV_DEVICE_PATH TempFvbDevicePathData
;
1558 EFI_PHYSICAL_ADDRESS BaseAddress
;
1566 BOOLEAN InstallSfsNotify
;
1569 InstallSfsNotify
= FALSE
;
1572 // Allocate runtime services data for global variable, which contains
1573 // the private data of all firmware volume block instances
1575 Status
= gBS
->AllocatePool (
1576 EfiRuntimeServicesData
,
1577 sizeof (ESAL_FWB_GLOBAL
),
1580 ASSERT_EFI_ERROR (Status
);
1582 // Calculate the total size for all firmware volume block instances
1585 FirmwareVolumeHobList
.Raw
= GetHobList();
1587 Status
= GetFvbHeader (&FirmwareVolumeHobList
, &FwVolHeader
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1588 if (EFI_ERROR (Status
)) {
1591 FirmwareVolumeHobList
.Raw
= GET_NEXT_HOB (FirmwareVolumeHobList
);
1594 BufferSize
+= (FwVolHeader
->HeaderLength
+ sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
));
1599 // Only need to allocate once. There is only one copy of physical memory for
1600 // the private data of each FV instance. But in virtual mode or in physical
1601 // mode, the address of the the physical memory may be different.
1603 Status
= gBS
->AllocatePool (
1604 EfiRuntimeServicesData
,
1606 &mFvbModuleGlobal
->FvInstance
[FVB_PHYSICAL
]
1608 ASSERT_EFI_ERROR (Status
);
1611 // Make a virtual copy of the FvInstance pointer.
1613 FwhInstance
= mFvbModuleGlobal
->FvInstance
[FVB_PHYSICAL
];
1614 mFvbModuleGlobal
->FvInstance
[FVB_VIRTUAL
] = FwhInstance
;
1616 mFvbModuleGlobal
->NumFv
= 0;
1617 FirmwareVolumeHobList
.Raw
= GetHobList();
1621 // Fill in the private data of each firmware volume block instance
1624 Status
= GetFvbHeader (
1625 &FirmwareVolumeHobList
, &FwVolHeader
,
1626 &BaseAddress
, &VolumeId
, &MappedFile
, &ActuralSize
, &Offset
,
1629 if (EFI_ERROR (Status
)) {
1632 FirmwareVolumeHobList
.Raw
= GET_NEXT_HOB (FirmwareVolumeHobList
);
1638 CopyMem ((UINTN
*) &(FwhInstance
->VolumeHeader
), (UINTN
*) FwVolHeader
, FwVolHeader
->HeaderLength
);
1639 FwVolHeader
= &(FwhInstance
->VolumeHeader
);
1641 FwhInstance
->FvBase
[FVB_PHYSICAL
] = (UINTN
) BaseAddress
;
1642 FwhInstance
->FvBase
[FVB_VIRTUAL
] = (UINTN
) BaseAddress
;
1643 FwhInstance
->Device
= NULL
;
1644 FwhInstance
->Offset
= Offset
;
1646 if (*MappedFile
!= '\0') {
1647 FwhInstance
->VolumeId
= VolumeId
;
1648 FwhInstance
->ActuralSize
= ActuralSize
;
1649 StrCpy (FwhInstance
->MappedFile
, MappedFile
);
1651 InstallSfsNotify
= TRUE
;
1653 FwhInstance
->VolumeId
= (UINT32
) -1;
1654 FwhInstance
->ActuralSize
= (UINT32
) -1;
1655 FwhInstance
->MappedFile
[0] = L
'\0';
1658 DEBUG ((EFI_D_INFO
, "FirmVolume Found! BaseAddress=0x%lx, VolumeId=0x%x, MappedFile=%s, Size=0x%x\n",
1659 (UINTN
) BaseAddress
, VolumeId
, MappedFile
, ActuralSize
));
1661 // We may expose readonly FVB in future.
1663 FwhInstance
->WriteEnabled
= TRUE
; // Ken: Why enable write?
1664 EfiInitializeLock (&(FwhInstance
->FvbDevLock
), TPL_HIGH_LEVEL
);
1666 LbaAddress
= (UINTN
) FwhInstance
->FvBase
[0];
1669 if (FwhInstance
->WriteEnabled
) {
1670 for (PtrBlockMapEntry
= FwVolHeader
->BlockMap
; PtrBlockMapEntry
->NumBlocks
!= 0; PtrBlockMapEntry
++) {
1672 LbaAddress
+= PtrBlockMapEntry
->NumBlocks
* PtrBlockMapEntry
->Length
;
1674 // Get the maximum size of a block. The size will be used to allocate
1675 // buffer for Scratch space, the intermediate buffer for FVB extension
1678 if (MaxLbaSize
< PtrBlockMapEntry
->Length
) {
1679 MaxLbaSize
= PtrBlockMapEntry
->Length
;
1682 NumOfBlocks
+= PtrBlockMapEntry
->NumBlocks
;
1685 // Write back a healthy FV header
1688 Status
= FlashFdErase (
1689 (UINTN
) FwhInstance
->FvBase
[0],
1691 FwVolHeader
->BlockMap
->Length
1694 HeaderLength
= (UINTN
) FwVolHeader
->HeaderLength
;
1696 Status
= FlashFdWrite (
1697 (UINTN
) FwhInstance
->FvBase
[0],
1699 (UINTN
*) &HeaderLength
,
1700 (UINT8
*) FwVolHeader
1703 FwVolHeader
->HeaderLength
= (UINT16
) HeaderLength
;
1705 DEBUG ((EFI_D_ERROR
, "Fvb (0x%x): FV header invalid, write back - %r\n", (UINTN
) FwhInstance
->FvBase
[0], Status
));
1709 // The total number of blocks in the FV.
1711 FwhInstance
->NumOfBlocks
= NumOfBlocks
;
1714 // Add a FVB Protocol Instance
1716 Status
= gBS
->AllocatePool (
1717 EfiRuntimeServicesData
,
1718 sizeof (EFI_FW_VOL_BLOCK_DEVICE
),
1721 ASSERT_EFI_ERROR (Status
);
1723 CopyMem (FvbDevice
, &mFvbDeviceTemplate
, sizeof (EFI_FW_VOL_BLOCK_DEVICE
));
1725 FvbDevice
->Instance
= mFvbModuleGlobal
->NumFv
;
1726 mFvbModuleGlobal
->NumFv
++;
1729 // Set up the devicepath
1731 FvbDevice
->DevicePath
.MemMapDevPath
.StartingAddress
= BaseAddress
;
1732 FvbDevice
->DevicePath
.MemMapDevPath
.EndingAddress
= BaseAddress
+ (FwVolHeader
->FvLength
- 1);
1735 // Find a handle with a matching device path that has supports FW Block protocol
1737 TempFwbDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) &TempFvbDevicePathData
;
1738 CopyMem (TempFwbDevicePath
, &FvbDevice
->DevicePath
, sizeof (FV_DEVICE_PATH
));
1739 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid
, &TempFwbDevicePath
, &FwbHandle
);
1740 if (EFI_ERROR (Status
)) {
1742 // LocateDevicePath fails so install a new interface and device path
1745 Status
= gBS
->InstallMultipleProtocolInterfaces (
1747 &gEfiFirmwareVolumeBlockProtocolGuid
,
1748 &FvbDevice
->FwVolBlockInstance
,
1749 &gEfiDevicePathProtocolGuid
,
1750 &FvbDevice
->DevicePath
,
1753 ASSERT_EFI_ERROR (Status
);
1754 } else if (IsDevicePathEnd (TempFwbDevicePath
)) {
1756 // Device allready exists, so reinstall the FVB protocol
1758 Status
= gBS
->HandleProtocol (
1760 &gEfiFirmwareVolumeBlockProtocolGuid
,
1763 ASSERT_EFI_ERROR (Status
);
1765 Status
= gBS
->ReinstallProtocolInterface (
1767 &gEfiFirmwareVolumeBlockProtocolGuid
,
1769 &FvbDevice
->FwVolBlockInstance
1771 ASSERT_EFI_ERROR (Status
);
1775 // There was a FVB protocol on an End Device Path node
1780 // Install FVB Extension Protocol on the same handle
1782 Status
= gBS
->InstallMultipleProtocolInterfaces (
1784 &gEfiFvbExtensionProtocolGuid
,
1785 &FvbDevice
->FvbExtension
,
1786 &gEfiAlternateFvBlockGuid
,
1791 ASSERT_EFI_ERROR (Status
);
1793 FwhInstance
= (EFI_FW_VOL_INSTANCE
*)
1795 (UINTN
) ((UINT8
*) FwhInstance
) + FwVolHeader
->HeaderLength
+
1796 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
1801 // Allocate for scratch space, an intermediate buffer for FVB extention
1803 Status
= gBS
->AllocatePool (
1804 EfiRuntimeServicesData
,
1806 &mFvbModuleGlobal
->FvbScratchSpace
[FVB_PHYSICAL
]
1808 ASSERT_EFI_ERROR (Status
);
1810 mFvbModuleGlobal
->FvbScratchSpace
[FVB_VIRTUAL
] = mFvbModuleGlobal
->FvbScratchSpace
[FVB_PHYSICAL
];
1812 if (InstallSfsNotify
) {
1813 FvbInstallSfsNotify ();