2 Functions in this file will program the image into flash area.
4 Copyright (c) 2002 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "UpdateDriver.h"
13 Write a block size data into flash.
15 @param FvbProtocol Pointer to FVB protocol.
16 @param Lba Logic block index to be updated.
17 @param BlockSize Block size
18 @param Buffer Buffer data to be written.
20 @retval EFI_SUCCESS Write data successfully.
21 @retval other errors Write data failed.
26 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
36 // First erase the block
38 Status
= FvbProtocol
->EraseBlocks (
42 EFI_LBA_LIST_TERMINATOR
44 if (EFI_ERROR (Status
)) {
52 Status
= FvbProtocol
->Write (
59 if ((EFI_ERROR (Status
)) || (Size
!= BlockSize
)) {
67 Write buffer data in a flash block.
69 @param FvbProtocol Pointer to FVB protocol.
70 @param Lba Logic block index to be updated.
71 @param Offset The offset within the block.
72 @param Length Size of buffer to be updated.
73 @param BlockSize Block size.
74 @param Buffer Buffer data to be updated.
76 @retval EFI_SUCCESS Write data successfully.
77 @retval other errors Write data failed.
81 UpdateBufferInOneBlock (
82 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
92 UINT8
*ReservedBuffer
;
95 // If we are going to update a whole block
97 if ((Offset
== 0) && (Length
== BlockSize
)) {
98 Status
= UpdateOneBlock (
108 // If it is not a full block update, we need to coalesce data in
109 // the block that is not going to be updated and new data together.
113 // Allocate a reserved buffer to make up the final buffer for update
115 ReservedBuffer
= NULL
;
116 ReservedBuffer
= AllocatePool (BlockSize
);
117 if (ReservedBuffer
== NULL
) {
118 return EFI_OUT_OF_RESOURCES
;
121 // First get the original content of the block
124 Status
= FvbProtocol
->Read (
131 if ((EFI_ERROR (Status
)) || (Size
!= BlockSize
)) {
132 FreePool (ReservedBuffer
);
137 // Overwrite the reserved buffer with new content
139 CopyMem (ReservedBuffer
+ Offset
, Buffer
, Length
);
141 Status
= UpdateOneBlock (
148 FreePool (ReservedBuffer
);
154 Get the last write log, and check the status of last write.
155 If not complete, restart will be taken.
157 @param FvbHandle Handle of FVB protocol.
158 @param FtwProtocol FTW protocol instance.
159 @param ConfigData Config data on updating driver.
160 @param PrivateDataSize bytes from the private data
161 stored for this write.
162 @param PrivateData A pointer to a buffer. The function will copy.
163 @param Lba The logical block address of the last write.
164 @param Offset The offset within the block of the last write.
165 @param Length The length of the last write.
166 @param Pending A Boolean value with TRUE indicating
167 that the write was completed.
169 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
170 @retval EFI_ABORTED The FTW work space is damaged.
171 @retval EFI_NOT_FOUND The last write is not done by this driver.
172 @retval EFI_SUCCESS Last write log is got.
177 IN EFI_HANDLE FvbHandle
,
178 IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL
*FtwProtocol
,
179 IN UPDATE_CONFIG_DATA
*ConfigData
,
180 IN UINTN PrivateDataSize
,
181 IN OUT UPDATE_PRIVATE_DATA
*PrivateData
,
183 IN OUT UINTN
*Offset
,
184 IN OUT UINTN
*Length
,
185 IN OUT BOOLEAN
*Pending
190 UINTN PrivateBufferSize
;
192 VOID
*PrivateDataBuffer
;
195 // Get the last write
198 PrivateBufferSize
= PrivateDataSize
;
199 PrivateDataBuffer
= NULL
;
200 Status
= FtwProtocol
->GetLastWrite (
210 if (EFI_ERROR (Status
)) {
212 // If there is no incompleted record, return success.
214 if ((Status
== EFI_NOT_FOUND
) && Complete
) {
216 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
218 // If buffer too small, reallocate buffer and call getlastwrite again
220 PrivateDataBuffer
= AllocatePool (PrivateBufferSize
);
222 if (PrivateDataBuffer
== NULL
) {
223 return EFI_OUT_OF_RESOURCES
;
226 Status
= FtwProtocol
->GetLastWrite (
236 if (EFI_ERROR (Status
)) {
237 FreePool ( PrivateDataBuffer
);
240 CopyMem (PrivateData
, PrivateDataBuffer
, PrivateDataSize
);
241 FreePool (PrivateDataBuffer
);
242 PrivateDataBuffer
= NULL
;
252 // If the caller is not the update driver, then return.
253 // The update driver cannot continue to perform the update
255 if (CompareMem (&CallerId
, &gEfiCallerIdGuid
, sizeof (EFI_GUID
)) != 0) {
256 return EFI_NOT_FOUND
;
260 // Check the private data and see if it is the one I need.
262 if (CompareMem (&(PrivateData
->FileGuid
), &(ConfigData
->FileGuid
), sizeof(EFI_GUID
)) != 0) {
263 return EFI_NOT_FOUND
;
267 // If the caller is the update driver and complete is not true, then restart().
271 // Re-start the update
273 Status
= FtwProtocol
->Restart (
278 // If restart() error, then abort().
280 if (EFI_ERROR (Status
)) {
281 FtwProtocol
->Abort (FtwProtocol
);
283 // Now set Pending as FALSE as this record has been cleared
295 Update the whole FV image in fault tolerant write method.
297 @param FvbHandle Handle of FVB protocol for the updated flash range.
298 @param FvbProtocol FVB protocol.
299 @param BlockMap Block array to specify flash area.
300 @param ConfigData Config data on updating driver.
301 @param ImageBuffer Image buffer to be updated.
302 @param ImageSize Image size.
304 @retval EFI_SUCCESS FV image is writed into flash.
305 @retval EFI_INVALID_PARAMETER Config data is not valid.
306 @retval EFI_NOT_FOUND FTW protocol doesn't exist.
307 @retval EFI_OUT_OF_RESOURCES No enough backup space.
308 @retval EFI_ABORTED Error happen when update FV.
312 FaultTolerantUpdateOnWholeFv (
313 IN EFI_HANDLE FvbHandle
,
314 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
315 IN EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
,
316 IN UPDATE_CONFIG_DATA
*ConfigData
,
317 IN UINT8
*ImageBuffer
,
322 EFI_FAULT_TOLERANT_WRITE_PROTOCOL
*FtwProtocol
;
324 UINTN FtwMaxBlockSize
;
326 UPDATE_PRIVATE_DATA PrivateData
;
333 EFI_FV_BLOCK_MAP_ENTRY
*PtrMap
;
338 if ((ConfigData
->UpdateType
!= UpdateWholeFV
)
339 || (!ConfigData
->FaultTolerant
)) {
340 return EFI_INVALID_PARAMETER
;
344 // Get the FTW protocol
346 Status
= gBS
->LocateProtocol (
347 &gEfiFaultTolerantWriteProtocolGuid
,
349 (VOID
**) &FtwProtocol
351 if (EFI_ERROR (Status
)) {
352 return EFI_NOT_FOUND
;
356 // Get the maximum block size of the FV, and number of blocks
357 // NumOfBlocks will be the NumOfUdpates.
363 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
366 if (MaxBlockSize
< PtrMap
->Length
) {
367 MaxBlockSize
= PtrMap
->Length
;
369 NumOfBlocks
= NumOfBlocks
+ PtrMap
->NumBlocks
;
373 FtwProtocol
->GetMaxBlockSize (FtwProtocol
, &FtwMaxBlockSize
);
375 // Not enough backup space. return directly
377 if (FtwMaxBlockSize
< MaxBlockSize
) {
378 return EFI_OUT_OF_RESOURCES
;
387 // Fault Tolerant Write can only support actual fault tolerance if the write
388 // is a reclaim operation, which means the data buffer (new and old) are
389 // acutally both stored in flash. But for component update write, the data
390 // are now in memory. So we cannot actually recover the data after power
393 Status
= RetrieveLastWrite (
397 sizeof (UPDATE_PRIVATE_DATA
),
405 if (Pending
&& (Status
== EFI_NOT_FOUND
)) {
407 // Cannot continue with the write operation
412 if (EFI_ERROR(Status
)) {
417 // Currently we start from the pending write if there is any. But as we
418 // are going to update a whole FV, we can just abort last write and start
419 // from the very begining.
423 // Now allocte the update private data in FTW. If there is pending
424 // write, it has already been allocated and no need to allocate here.
426 Status
= FtwProtocol
->Allocate (
429 sizeof (UPDATE_PRIVATE_DATA
),
432 if (EFI_ERROR (Status
)) {
438 // Perform the update now. If there are pending writes, we need to
439 // start from the pending write instead of the very beginning.
444 UpdateBuffer
= ImageBuffer
;
446 (VOID
*) &PrivateData
.FileGuid
,
447 (VOID
*) &ConfigData
->FileGuid
,
452 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
455 Length
= (UINTN
)PtrMap
->Length
;
456 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
459 // Add an extra check here to see if the pending record is correct
461 if (Pending
&& (Lba
== PendingLba
)) {
462 if ((PendingOffset
!= Offset
) || (PendingLength
!= Length
)) {
466 Status
= EFI_ABORTED
;
471 if ((!Pending
) || (Lba
>= PendingLba
)) {
472 Status
= FtwProtocol
->Write (
477 &PrivateData
, // Private Data
478 FvbHandle
, // FVB handle
479 UpdateBuffer
// Buffer
483 if (EFI_ERROR (Status
)) {
487 UpdateBuffer
= (UINT8
*) ((UINTN
)UpdateBuffer
+ Length
);
490 if (EFI_ERROR (Status
)) {
501 Directly update the whole FV image without fault tolerant write method.
503 @param FvbHandle Handle of FVB protocol for the updated flash range.
504 @param FvbProtocol FVB protocol.
505 @param BlockMap Block array to specify flash area.
506 @param ConfigData Config data on updating driver.
507 @param ImageBuffer Image buffer to be updated.
508 @param ImageSize Image size.
510 @retval EFI_SUCCESS FV image is writed into flash.
511 @retval EFI_INVALID_PARAMETER Config data is not valid.
512 @retval EFI_ABORTED Error happen when update FV.
516 NonFaultTolerantUpdateOnWholeFv (
517 IN EFI_HANDLE FvbHandle
,
518 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
519 IN EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
,
520 IN UPDATE_CONFIG_DATA
*ConfigData
,
521 IN UINT8
*ImageBuffer
,
526 EFI_FV_BLOCK_MAP_ENTRY
*PtrMap
;
532 if ((ConfigData
->UpdateType
!= UpdateWholeFV
)
533 || (ConfigData
->FaultTolerant
)) {
534 return EFI_INVALID_PARAMETER
;
537 Status
= EFI_SUCCESS
;
540 UpdateBuffer
= ImageBuffer
;
543 // Perform the update now
546 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
549 UpdateSize
= (UINTN
)PtrMap
->Length
;
550 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
551 Status
= UpdateOneBlock (
557 if (EFI_ERROR (Status
)) {
562 UpdateBuffer
= (UINT8
*) ((UINTN
)UpdateBuffer
+ UpdateSize
);
565 if (EFI_ERROR (Status
)) {
575 Update the whole FV image, and reinsall FVB protocol for the updated FV image.
577 @param FvbHandle Handle of FVB protocol for the updated flash range.
578 @param FvbProtocol FVB protocol.
579 @param ConfigData Config data on updating driver.
580 @param ImageBuffer Image buffer to be updated.
581 @param ImageSize Image size.
583 @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV.
584 Or Image size is not same to the size of whole FV.
585 @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated.
586 @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled.
590 PerformUpdateOnWholeFv (
591 IN EFI_HANDLE FvbHandle
,
592 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
593 IN UPDATE_CONFIG_DATA
*ConfigData
,
594 IN UINT8
*ImageBuffer
,
599 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
600 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
603 if (ConfigData
->UpdateType
!= UpdateWholeFV
) {
604 return EFI_INVALID_PARAMETER
;
608 // Get the header of the firmware volume
611 FwVolHeader
= AllocatePool (((EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) (ConfigData
->BaseAddress
)))->HeaderLength
);
612 if (FwVolHeader
== NULL
) {
613 return EFI_OUT_OF_RESOURCES
;
617 (VOID
*) ((UINTN
) (ConfigData
->BaseAddress
)),
618 ((EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) (ConfigData
->BaseAddress
)))->HeaderLength
622 // Check if ImageSize is the same as the size of the whole FV
624 if ((UINT64
)ImageSize
!= FwVolHeader
->FvLength
) {
625 FreePool (FwVolHeader
);
626 return EFI_INVALID_PARAMETER
;
632 TmpStr
= HiiGetString (gHiiHandle
, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME
), NULL
);
633 if (TmpStr
!= NULL
) {
634 Print (TmpStr
, ConfigData
->BaseAddress
, (FwVolHeader
->FvLength
+ ConfigData
->BaseAddress
));
638 DEBUG ((EFI_D_UPDATE
, "UpdateDriver: updating whole FV from %08LX to %08LX\n",
639 ConfigData
->BaseAddress
, (FwVolHeader
->FvLength
+ ConfigData
->BaseAddress
)));
642 // Get the block map of the firmware volume
644 BlockMap
= &(FwVolHeader
->BlockMap
[0]);
647 // It is about the same if we are going to fault tolerantly update
648 // a certain FV in our current design. But we divide non-fault tolerant
649 // and fault tolerant udpate here for better maintenance as fault
650 // tolerance may change and may be done more wisely if we have space.
652 if (ConfigData
->FaultTolerant
) {
653 Status
= FaultTolerantUpdateOnWholeFv (
662 Status
= NonFaultTolerantUpdateOnWholeFv (
672 FreePool (FwVolHeader
);
674 if (EFI_ERROR (Status
)) {
679 // As the whole FV has been replaced, the FV driver shall re-parse the
680 // firmware volume. So re-install FVB protocol here
682 Status
= gBS
->ReinstallProtocolInterface (
684 &gEfiFirmwareVolumeBlockProtocolGuid
,
693 Update certain file in the FV.
695 @param FvbHandle Handle of FVB protocol for the updated flash range.
696 @param FvbProtocol FVB protocol.
697 @param ConfigData Config data on updating driver.
698 @param ImageBuffer Image buffer to be updated.
699 @param ImageSize Image size.
700 @param FileType FFS file type.
701 @param FileAttributes FFS file attribute
703 @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile.
704 Or Image size is not same to the size of whole FV.
705 @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated.
706 @retval EFI_SUCCESS The FFS file is added into FV.
710 PerformUpdateOnFvFile (
711 IN EFI_HANDLE FvbHandle
,
712 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
713 IN UPDATE_CONFIG_DATA
*ConfigData
,
714 IN UINT8
*ImageBuffer
,
716 IN EFI_FV_FILETYPE FileType
,
717 IN EFI_FV_FILE_ATTRIBUTES FileAttributes
721 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVolProtocol
;
722 EFI_FV_WRITE_FILE_DATA FileData
;
725 if (ConfigData
->UpdateType
!= UpdateFvFile
) {
726 return EFI_INVALID_PARAMETER
;
732 TmpStr
= HiiGetString (gHiiHandle
, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME_FILE
), NULL
);
733 if (TmpStr
!= NULL
) {
734 Print (TmpStr
, &(ConfigData
->FileGuid
));
738 DEBUG ((EFI_D_UPDATE
, "UpdateDriver: updating file: %g\n",
739 &(ConfigData
->FileGuid
)));
742 // Get Firmware volume protocol on this FVB protocol
744 Status
= gBS
->HandleProtocol (
746 &gEfiFirmwareVolume2ProtocolGuid
,
747 (VOID
**) &FwVolProtocol
749 if (EFI_ERROR (Status
)) {
754 // If it is a PEIM, we need first to rebase it before committing
755 // the write to target
757 if ((FileType
== EFI_FV_FILETYPE_PEI_CORE
) || (FileType
== EFI_FV_FILETYPE_PEIM
)
758 || (FileType
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
)) {
759 return EFI_UNSUPPORTED
;
762 FileData
.NameGuid
= &(ConfigData
->FileGuid
);
763 FileData
.Type
= FileType
;
764 FileData
.FileAttributes
= FileAttributes
;
765 FileData
.Buffer
= ImageBuffer
;
766 FileData
.BufferSize
= (UINT32
) ImageSize
;
768 Status
= FwVolProtocol
->WriteFile (
771 (EFI_FV_WRITE_POLICY
)ConfigData
->FaultTolerant
,
778 Update the buffer into flash area in fault tolerant write method.
780 @param ImageBuffer Image buffer to be updated.
781 @param SizeLeft Size of the image buffer.
782 @param UpdatedSize Size of the updated buffer.
783 @param ConfigData Config data on updating driver.
784 @param FlashAddress Flash address to be updated as start address.
785 @param FvbProtocol FVB protocol.
786 @param FvbHandle Handle of FVB protocol for the updated flash range.
788 @retval EFI_SUCCESS Buffer data is updated into flash.
789 @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
790 @retval EFI_NOT_FOUND FTW protocol doesn't exist.
791 @retval EFI_OUT_OF_RESOURCES No enough backup space.
792 @retval EFI_ABORTED Error happen when update flash area.
796 FaultTolerantUpdateOnPartFv (
797 IN UINT8
*ImageBuffer
,
799 IN OUT UINTN
*UpdatedSize
,
800 IN UPDATE_CONFIG_DATA
*ConfigData
,
801 IN EFI_PHYSICAL_ADDRESS FlashAddress
,
802 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
803 IN EFI_HANDLE FvbHandle
807 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
808 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeaderTmp
;
809 EFI_PHYSICAL_ADDRESS BaseAddress
;
810 EFI_PHYSICAL_ADDRESS FvBase
;
811 EFI_PHYSICAL_ADDRESS NextBlock
;
812 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
813 EFI_FV_BLOCK_MAP_ENTRY
*PtrMap
;
816 EFI_PHYSICAL_ADDRESS StartAddress
;
817 EFI_FAULT_TOLERANT_WRITE_PROTOCOL
*FtwProtocol
;
819 UINTN FtwMaxBlockSize
;
821 UPDATE_PRIVATE_DATA PrivateData
;
833 // Get the block map to update the block one by one
835 Status
= FvbProtocol
->GetPhysicalAddress (
839 if (EFI_ERROR (Status
)) {
843 FwVolHeaderTmp
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
844 if ((FlashAddress
< FvBase
) || (FlashAddress
> (FvBase
+ FwVolHeaderTmp
->FvLength
))) {
845 return EFI_INVALID_PARAMETER
;
848 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)AllocateCopyPool (
849 FwVolHeaderTmp
->HeaderLength
,
852 if (FwVolHeader
== NULL
) {
853 return EFI_OUT_OF_RESOURCES
;
857 // For fault tolerant write, we have to know how many blocks we need to
858 // update. So we will calculate number of updates and max block size first
862 TotalSize
= SizeLeft
;
863 StartAddress
= FlashAddress
;
864 BaseAddress
= FvBase
;
865 BlockMap
= &(FwVolHeader
->BlockMap
[0]);
868 while (TotalSize
> 0) {
869 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
873 BlockSize
= PtrMap
->Length
;
874 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
875 NextBlock
= BaseAddress
+ BlockSize
;
877 // Check if this block need to be updated
879 if ((StartAddress
>= BaseAddress
) && (StartAddress
< NextBlock
)) {
881 // Get the maximum block size
883 if (MaxBlockSize
< BlockSize
) {
884 MaxBlockSize
= BlockSize
;
888 // This block shall be udpated. So increment number of updates
891 Offset
= (UINTN
) (StartAddress
- BaseAddress
);
893 if ((Length
+ Offset
) > BlockSize
) {
894 Length
= BlockSize
- Offset
;
897 StartAddress
= StartAddress
+ Length
;
898 TotalSize
= TotalSize
- Length
;
899 if (TotalSize
<= 0) {
903 BaseAddress
= NextBlock
;
909 // Get the FTW protocol
911 Status
= gBS
->LocateProtocol (
912 &gEfiFaultTolerantWriteProtocolGuid
,
914 (VOID
**) &FtwProtocol
916 if (EFI_ERROR (Status
)) {
917 FreePool (FwVolHeader
);
918 return EFI_NOT_FOUND
;
921 FtwProtocol
->GetMaxBlockSize (FtwProtocol
, &FtwMaxBlockSize
);
924 // Not enough backup space. return directly
926 if (FtwMaxBlockSize
< MaxBlockSize
) {
927 FreePool (FwVolHeader
);
928 return EFI_OUT_OF_RESOURCES
;
937 // Fault Tolerant Write can only support actual fault tolerance if the write
938 // is a reclaim operation, which means the data buffer (new and old) are
939 // acutally both stored in flash. But for component update write, the data
940 // are now in memory. So we cannot actually recover the data after power
943 Status
= RetrieveLastWrite (
947 sizeof (UPDATE_PRIVATE_DATA
),
954 if (Pending
&& (Status
== EFI_NOT_FOUND
)) {
956 // I'm not the owner of the pending fault tolerant write record
957 // Cannot continue with the write operation
959 FreePool (FwVolHeader
);
963 if (EFI_ERROR(Status
)) {
964 FreePool (FwVolHeader
);
969 // Currently we start from the pending write if there is any. But if the
970 // caller is exactly the same, and the new data is already a in memory, (it
971 // cannot be stored in flash in last write,) we can just abort last write
972 // and start from the very begining.
976 // Now allocte the update private data in FTW. If there is pending
977 // write, it has already been allocated and no need to allocate here.
979 Status
= FtwProtocol
->Allocate (
982 sizeof (UPDATE_PRIVATE_DATA
),
985 if (EFI_ERROR (Status
)) {
986 FreePool (FwVolHeader
);
992 // Perform the update now. If there are pending writes, we need to
993 // start from the pending write instead of the very beginning.
995 TotalSize
= SizeLeft
;
997 StartAddress
= FlashAddress
;
998 BaseAddress
= FvBase
;
1000 Image
= ImageBuffer
;
1002 (VOID
*) &PrivateData
.FileGuid
,
1003 (VOID
*) &ConfigData
->FileGuid
,
1007 while (TotalSize
> 0) {
1008 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
1012 BlockSize
= (UINTN
)PtrMap
->Length
;
1013 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
1014 NextBlock
= BaseAddress
+ BlockSize
;
1015 if ((StartAddress
>= BaseAddress
) && (StartAddress
< NextBlock
)) {
1017 // So we need to update this block
1019 Offset
= (UINTN
) (StartAddress
- BaseAddress
);
1021 if ((Length
+ Offset
) > BlockSize
) {
1022 Length
= BlockSize
- Offset
;
1026 // Add an extra check here to see if the pending record is correct
1028 if (Pending
&& (Lba
== PendingLba
)) {
1029 if ((PendingOffset
!= Offset
) || (PendingLength
!= Length
)) {
1033 Status
= EFI_ABORTED
;
1038 if ((!Pending
) || (Lba
>= PendingLba
)) {
1039 DEBUG ((EFI_D_UPDATE
, "Update Flash area from %08LX to %08LX\n", StartAddress
, (UINT64
)StartAddress
+ Length
));
1040 Status
= FtwProtocol
->Write (
1045 &PrivateData
, // Private Data
1046 FvbHandle
, // FVB handle
1049 if (EFI_ERROR (Status
)) {
1055 // Now increment StartAddress, ImageBuffer and decrease the
1056 // left size to prepare for the next block update.
1058 StartAddress
= StartAddress
+ Length
;
1059 Image
= Image
+ Length
;
1060 TotalSize
= TotalSize
- Length
;
1061 if (TotalSize
<= 0) {
1065 BaseAddress
= NextBlock
;
1069 if (EFI_ERROR (Status
)) {
1075 FreePool (FwVolHeader
);
1077 *UpdatedSize
= SizeLeft
- TotalSize
;
1083 Directly update the buffer into flash area without fault tolerant write method.
1085 @param ImageBuffer Image buffer to be updated.
1086 @param SizeLeft Size of the image buffer.
1087 @param UpdatedSize Size of the updated buffer.
1088 @param FlashAddress Flash address to be updated as start address.
1089 @param FvbProtocol FVB protocol.
1090 @param FvbHandle Handle of FVB protocol for the updated flash range.
1092 @retval EFI_SUCCESS Buffer data is updated into flash.
1093 @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
1094 @retval EFI_OUT_OF_RESOURCES No enough backup space.
1098 NonFaultTolerantUpdateOnPartFv (
1099 IN UINT8
*ImageBuffer
,
1101 IN OUT UINTN
*UpdatedSize
,
1102 IN EFI_PHYSICAL_ADDRESS FlashAddress
,
1103 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
1104 IN EFI_HANDLE FvbHandle
1108 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1109 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeaderTmp
;
1110 EFI_PHYSICAL_ADDRESS BaseAddress
;
1111 EFI_PHYSICAL_ADDRESS NextBlock
;
1112 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
1122 // Get the block map to update the block one by one
1124 Status
= FvbProtocol
->GetPhysicalAddress (
1128 if (EFI_ERROR (Status
)) {
1132 FwVolHeaderTmp
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)BaseAddress
;
1133 if ((FlashAddress
< BaseAddress
) || (FlashAddress
> ( BaseAddress
+ FwVolHeaderTmp
->FvLength
))) {
1134 return EFI_INVALID_PARAMETER
;
1137 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)AllocateCopyPool (
1138 FwVolHeaderTmp
->HeaderLength
,
1141 if (FwVolHeader
== NULL
) {
1142 return EFI_OUT_OF_RESOURCES
;
1145 Image
= ImageBuffer
;
1146 TotalSize
= SizeLeft
;
1147 BlockMap
= &(FwVolHeader
->BlockMap
[0]);
1150 while (TotalSize
> 0) {
1151 if ((BlockMap
->NumBlocks
== 0) || (BlockMap
->Length
== 0)) {
1155 BlockSize
= BlockMap
->Length
;
1156 for (Index
= 0 ; Index
< BlockMap
->NumBlocks
; Index
++) {
1157 NextBlock
= BaseAddress
+ BlockSize
;
1158 if ((FlashAddress
>= BaseAddress
) && (FlashAddress
< NextBlock
)) {
1160 // So we need to update this block
1162 Offset
= (UINTN
) FlashAddress
- (UINTN
) BaseAddress
;
1164 if ((Length
+ Offset
) > BlockSize
) {
1165 Length
= BlockSize
- Offset
;
1168 DEBUG ((EFI_D_UPDATE
, "Update Flash area from %08LX to %08LX\n", FlashAddress
, (UINT64
)FlashAddress
+ Length
));
1172 Status
= UpdateBufferInOneBlock (
1180 if (EFI_ERROR (Status
)) {
1181 FreePool (FwVolHeader
);
1186 // Now increment FlashAddress, ImageBuffer and decrease the
1187 // left size to prepare for the next block update.
1189 FlashAddress
= FlashAddress
+ Length
;
1190 Image
= Image
+ Length
;
1191 TotalSize
= TotalSize
- Length
;
1192 if (TotalSize
<= 0) {
1196 BaseAddress
= NextBlock
;
1200 if (EFI_ERROR (Status
)) {
1206 FreePool (FwVolHeader
);
1208 *UpdatedSize
= SizeLeft
- TotalSize
;