2 Functions in this file will program the image into flash area.
4 Copyright (c) 2002 - 2018, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "UpdateDriver.h"
20 Write a block size data into flash.
22 @param FvbProtocol Pointer to FVB protocol.
23 @param Lba Logic block index to be updated.
24 @param BlockSize Block size
25 @param Buffer Buffer data to be written.
27 @retval EFI_SUCCESS Write data successfully.
28 @retval other errors Write data failed.
33 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
43 // First erase the block
45 Status
= FvbProtocol
->EraseBlocks (
49 EFI_LBA_LIST_TERMINATOR
51 if (EFI_ERROR (Status
)) {
59 Status
= FvbProtocol
->Write (
66 if ((EFI_ERROR (Status
)) || (Size
!= BlockSize
)) {
74 Write buffer data in a flash block.
76 @param FvbProtocol Pointer to FVB protocol.
77 @param Lba Logic block index to be updated.
78 @param Offset The offset within the block.
79 @param Length Size of buffer to be updated.
80 @param BlockSize Block size.
81 @param Buffer Buffer data to be updated.
83 @retval EFI_SUCCESS Write data successfully.
84 @retval other errors Write data failed.
88 UpdateBufferInOneBlock (
89 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
99 UINT8
*ReservedBuffer
;
102 // If we are going to update a whole block
104 if ((Offset
== 0) && (Length
== BlockSize
)) {
105 Status
= UpdateOneBlock (
115 // If it is not a full block update, we need to coalesce data in
116 // the block that is not going to be updated and new data together.
120 // Allocate a reserved buffer to make up the final buffer for update
122 ReservedBuffer
= NULL
;
123 ReservedBuffer
= AllocatePool (BlockSize
);
124 if (ReservedBuffer
== NULL
) {
125 return EFI_OUT_OF_RESOURCES
;
128 // First get the original content of the block
131 Status
= FvbProtocol
->Read (
138 if ((EFI_ERROR (Status
)) || (Size
!= BlockSize
)) {
139 FreePool (ReservedBuffer
);
144 // Overwrite the reserved buffer with new content
146 CopyMem (ReservedBuffer
+ Offset
, Buffer
, Length
);
148 Status
= UpdateOneBlock (
155 FreePool (ReservedBuffer
);
161 Get the last write log, and check the status of last write.
162 If not complete, restart will be taken.
164 @param FvbHandle Handle of FVB protocol.
165 @param FtwProtocol FTW protocol instance.
166 @param ConfigData Config data on updating driver.
167 @param PrivateDataSize bytes from the private data
168 stored for this write.
169 @param PrivateData A pointer to a buffer. The function will copy.
170 @param Lba The logical block address of the last write.
171 @param Offset The offset within the block of the last write.
172 @param Length The length of the last write.
173 @param Pending A Boolean value with TRUE indicating
174 that the write was completed.
176 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
177 @retval EFI_ABORTED The FTW work space is damaged.
178 @retval EFI_NOT_FOUND The last write is not done by this driver.
179 @retval EFI_SUCCESS Last write log is got.
184 IN EFI_HANDLE FvbHandle
,
185 IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL
*FtwProtocol
,
186 IN UPDATE_CONFIG_DATA
*ConfigData
,
187 IN UINTN PrivateDataSize
,
188 IN OUT UPDATE_PRIVATE_DATA
*PrivateData
,
190 IN OUT UINTN
*Offset
,
191 IN OUT UINTN
*Length
,
192 IN OUT BOOLEAN
*Pending
197 UINTN PrivateBufferSize
;
199 VOID
*PrivateDataBuffer
;
202 // Get the last write
205 PrivateBufferSize
= PrivateDataSize
;
206 PrivateDataBuffer
= NULL
;
207 Status
= FtwProtocol
->GetLastWrite (
217 if (EFI_ERROR (Status
)) {
219 // If there is no incompleted record, return success.
221 if ((Status
== EFI_NOT_FOUND
) && Complete
) {
223 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
225 // If buffer too small, reallocate buffer and call getlastwrite again
227 PrivateDataBuffer
= AllocatePool (PrivateBufferSize
);
229 if (PrivateDataBuffer
== NULL
) {
230 return EFI_OUT_OF_RESOURCES
;
233 Status
= FtwProtocol
->GetLastWrite (
243 if (EFI_ERROR (Status
)) {
244 FreePool ( PrivateDataBuffer
);
247 CopyMem (PrivateData
, PrivateDataBuffer
, PrivateDataSize
);
248 FreePool (PrivateDataBuffer
);
249 PrivateDataBuffer
= NULL
;
259 // If the caller is not the update driver, then return.
260 // The update driver cannot continue to perform the update
262 if (CompareMem (&CallerId
, &gEfiCallerIdGuid
, sizeof (EFI_GUID
)) != 0) {
263 return EFI_NOT_FOUND
;
267 // Check the private data and see if it is the one I need.
269 if (CompareMem (&(PrivateData
->FileGuid
), &(ConfigData
->FileGuid
), sizeof(EFI_GUID
)) != 0) {
270 return EFI_NOT_FOUND
;
274 // If the caller is the update driver and complete is not true, then restart().
278 // Re-start the update
280 Status
= FtwProtocol
->Restart (
285 // If restart() error, then abort().
287 if (EFI_ERROR (Status
)) {
288 FtwProtocol
->Abort (FtwProtocol
);
290 // Now set Pending as FALSE as this record has been cleared
302 Update the whole FV image in fault tolerant write method.
304 @param FvbHandle Handle of FVB protocol for the updated flash range.
305 @param FvbProtocol FVB protocol.
306 @param BlockMap Block array to specify flash area.
307 @param ConfigData Config data on updating driver.
308 @param ImageBuffer Image buffer to be updated.
309 @param ImageSize Image size.
311 @retval EFI_SUCCESS FV image is writed into flash.
312 @retval EFI_INVALID_PARAMETER Config data is not valid.
313 @retval EFI_NOT_FOUND FTW protocol doesn't exist.
314 @retval EFI_OUT_OF_RESOURCES No enough backup space.
315 @retval EFI_ABORTED Error happen when update FV.
319 FaultTolerantUpdateOnWholeFv (
320 IN EFI_HANDLE FvbHandle
,
321 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
322 IN EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
,
323 IN UPDATE_CONFIG_DATA
*ConfigData
,
324 IN UINT8
*ImageBuffer
,
329 EFI_FAULT_TOLERANT_WRITE_PROTOCOL
*FtwProtocol
;
331 UINTN FtwMaxBlockSize
;
333 UPDATE_PRIVATE_DATA PrivateData
;
340 EFI_FV_BLOCK_MAP_ENTRY
*PtrMap
;
345 if ((ConfigData
->UpdateType
!= UpdateWholeFV
)
346 || (!ConfigData
->FaultTolerant
)) {
347 return EFI_INVALID_PARAMETER
;
351 // Get the FTW protocol
353 Status
= gBS
->LocateProtocol (
354 &gEfiFaultTolerantWriteProtocolGuid
,
356 (VOID
**) &FtwProtocol
358 if (EFI_ERROR (Status
)) {
359 return EFI_NOT_FOUND
;
363 // Get the maximum block size of the FV, and number of blocks
364 // NumOfBlocks will be the NumOfUdpates.
370 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
373 if (MaxBlockSize
< PtrMap
->Length
) {
374 MaxBlockSize
= PtrMap
->Length
;
376 NumOfBlocks
= NumOfBlocks
+ PtrMap
->NumBlocks
;
380 FtwProtocol
->GetMaxBlockSize (FtwProtocol
, &FtwMaxBlockSize
);
382 // Not enough backup space. return directly
384 if (FtwMaxBlockSize
< MaxBlockSize
) {
385 return EFI_OUT_OF_RESOURCES
;
394 // Fault Tolerant Write can only support actual fault tolerance if the write
395 // is a reclaim operation, which means the data buffer (new and old) are
396 // acutally both stored in flash. But for component update write, the data
397 // are now in memory. So we cannot actually recover the data after power
400 Status
= RetrieveLastWrite (
404 sizeof (UPDATE_PRIVATE_DATA
),
412 if (Pending
&& (Status
== EFI_NOT_FOUND
)) {
414 // Cannot continue with the write operation
419 if (EFI_ERROR(Status
)) {
424 // Currently we start from the pending write if there is any. But as we
425 // are going to update a whole FV, we can just abort last write and start
426 // from the very begining.
430 // Now allocte the update private data in FTW. If there is pending
431 // write, it has already been allocated and no need to allocate here.
433 Status
= FtwProtocol
->Allocate (
436 sizeof (UPDATE_PRIVATE_DATA
),
439 if (EFI_ERROR (Status
)) {
445 // Perform the update now. If there are pending writes, we need to
446 // start from the pending write instead of the very beginning.
451 UpdateBuffer
= ImageBuffer
;
453 (VOID
*) &PrivateData
.FileGuid
,
454 (VOID
*) &ConfigData
->FileGuid
,
459 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
462 Length
= (UINTN
)PtrMap
->Length
;
463 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
466 // Add an extra check here to see if the pending record is correct
468 if (Pending
&& (Lba
== PendingLba
)) {
469 if ((PendingOffset
!= Offset
) || (PendingLength
!= Length
)) {
473 Status
= EFI_ABORTED
;
478 if ((!Pending
) || (Lba
>= PendingLba
)) {
479 Status
= FtwProtocol
->Write (
484 &PrivateData
, // Private Data
485 FvbHandle
, // FVB handle
486 UpdateBuffer
// Buffer
490 if (EFI_ERROR (Status
)) {
494 UpdateBuffer
= (UINT8
*) ((UINTN
)UpdateBuffer
+ Length
);
497 if (EFI_ERROR (Status
)) {
508 Directly update the whole FV image without fault tolerant write method.
510 @param FvbHandle Handle of FVB protocol for the updated flash range.
511 @param FvbProtocol FVB protocol.
512 @param BlockMap Block array to specify flash area.
513 @param ConfigData Config data on updating driver.
514 @param ImageBuffer Image buffer to be updated.
515 @param ImageSize Image size.
517 @retval EFI_SUCCESS FV image is writed into flash.
518 @retval EFI_INVALID_PARAMETER Config data is not valid.
519 @retval EFI_ABORTED Error happen when update FV.
523 NonFaultTolerantUpdateOnWholeFv (
524 IN EFI_HANDLE FvbHandle
,
525 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
526 IN EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
,
527 IN UPDATE_CONFIG_DATA
*ConfigData
,
528 IN UINT8
*ImageBuffer
,
533 EFI_FV_BLOCK_MAP_ENTRY
*PtrMap
;
539 if ((ConfigData
->UpdateType
!= UpdateWholeFV
)
540 || (ConfigData
->FaultTolerant
)) {
541 return EFI_INVALID_PARAMETER
;
544 Status
= EFI_SUCCESS
;
547 UpdateBuffer
= ImageBuffer
;
550 // Perform the update now
553 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
556 UpdateSize
= (UINTN
)PtrMap
->Length
;
557 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
558 Status
= UpdateOneBlock (
564 if (EFI_ERROR (Status
)) {
569 UpdateBuffer
= (UINT8
*) ((UINTN
)UpdateBuffer
+ UpdateSize
);
572 if (EFI_ERROR (Status
)) {
582 Update the whole FV image, and reinsall FVB protocol for the updated FV image.
584 @param FvbHandle Handle of FVB protocol for the updated flash range.
585 @param FvbProtocol FVB protocol.
586 @param ConfigData Config data on updating driver.
587 @param ImageBuffer Image buffer to be updated.
588 @param ImageSize Image size.
590 @retval EFI_INVALID_PARAMETER Update type is not UpdateWholeFV.
591 Or Image size is not same to the size of whole FV.
592 @retval EFI_OUT_OF_RESOURCES No enoug memory is allocated.
593 @retval EFI_SUCCESS FV image is updated, and its FVB protocol is reinstalled.
597 PerformUpdateOnWholeFv (
598 IN EFI_HANDLE FvbHandle
,
599 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
600 IN UPDATE_CONFIG_DATA
*ConfigData
,
601 IN UINT8
*ImageBuffer
,
606 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
607 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
610 if (ConfigData
->UpdateType
!= UpdateWholeFV
) {
611 return EFI_INVALID_PARAMETER
;
615 // Get the header of the firmware volume
618 FwVolHeader
= AllocatePool (((EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) (ConfigData
->BaseAddress
)))->HeaderLength
);
619 if (FwVolHeader
== NULL
) {
620 return EFI_OUT_OF_RESOURCES
;
624 (VOID
*) ((UINTN
) (ConfigData
->BaseAddress
)),
625 ((EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) (ConfigData
->BaseAddress
)))->HeaderLength
629 // Check if ImageSize is the same as the size of the whole FV
631 if ((UINT64
)ImageSize
!= FwVolHeader
->FvLength
) {
632 FreePool (FwVolHeader
);
633 return EFI_INVALID_PARAMETER
;
639 TmpStr
= HiiGetString (gHiiHandle
, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME
), NULL
);
640 if (TmpStr
!= NULL
) {
641 Print (TmpStr
, ConfigData
->BaseAddress
, (FwVolHeader
->FvLength
+ ConfigData
->BaseAddress
));
645 DEBUG ((EFI_D_UPDATE
, "UpdateDriver: updating whole FV from %08LX to %08LX\n",
646 ConfigData
->BaseAddress
, (FwVolHeader
->FvLength
+ ConfigData
->BaseAddress
)));
649 // Get the block map of the firmware volume
651 BlockMap
= &(FwVolHeader
->BlockMap
[0]);
654 // It is about the same if we are going to fault tolerantly update
655 // a certain FV in our current design. But we divide non-fault tolerant
656 // and fault tolerant udpate here for better maintenance as fault
657 // tolerance may change and may be done more wisely if we have space.
659 if (ConfigData
->FaultTolerant
) {
660 Status
= FaultTolerantUpdateOnWholeFv (
669 Status
= NonFaultTolerantUpdateOnWholeFv (
679 FreePool (FwVolHeader
);
681 if (EFI_ERROR (Status
)) {
686 // As the whole FV has been replaced, the FV driver shall re-parse the
687 // firmware volume. So re-install FVB protocol here
689 Status
= gBS
->ReinstallProtocolInterface (
691 &gEfiFirmwareVolumeBlockProtocolGuid
,
700 Update certain file in the FV.
702 @param FvbHandle Handle of FVB protocol for the updated flash range.
703 @param FvbProtocol FVB protocol.
704 @param ConfigData Config data on updating driver.
705 @param ImageBuffer Image buffer to be updated.
706 @param ImageSize Image size.
707 @param FileType FFS file type.
708 @param FileAttributes FFS file attribute
710 @retval EFI_INVALID_PARAMETER Update type is not UpdateFvFile.
711 Or Image size is not same to the size of whole FV.
712 @retval EFI_UNSUPPORTED PEIM FFS is unsupported to be updated.
713 @retval EFI_SUCCESS The FFS file is added into FV.
717 PerformUpdateOnFvFile (
718 IN EFI_HANDLE FvbHandle
,
719 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
720 IN UPDATE_CONFIG_DATA
*ConfigData
,
721 IN UINT8
*ImageBuffer
,
723 IN EFI_FV_FILETYPE FileType
,
724 IN EFI_FV_FILE_ATTRIBUTES FileAttributes
728 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVolProtocol
;
729 EFI_FV_WRITE_FILE_DATA FileData
;
732 if (ConfigData
->UpdateType
!= UpdateFvFile
) {
733 return EFI_INVALID_PARAMETER
;
739 TmpStr
= HiiGetString (gHiiHandle
, STRING_TOKEN(UPDATE_FIRMWARE_VOLUME_FILE
), NULL
);
740 if (TmpStr
!= NULL
) {
741 Print (TmpStr
, &(ConfigData
->FileGuid
));
745 DEBUG ((EFI_D_UPDATE
, "UpdateDriver: updating file: %g\n",
746 &(ConfigData
->FileGuid
)));
749 // Get Firmware volume protocol on this FVB protocol
751 Status
= gBS
->HandleProtocol (
753 &gEfiFirmwareVolume2ProtocolGuid
,
754 (VOID
**) &FwVolProtocol
756 if (EFI_ERROR (Status
)) {
761 // If it is a PEIM, we need first to rebase it before committing
762 // the write to target
764 if ((FileType
== EFI_FV_FILETYPE_PEI_CORE
) || (FileType
== EFI_FV_FILETYPE_PEIM
)
765 || (FileType
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
)) {
766 return EFI_UNSUPPORTED
;
769 FileData
.NameGuid
= &(ConfigData
->FileGuid
);
770 FileData
.Type
= FileType
;
771 FileData
.FileAttributes
= FileAttributes
;
772 FileData
.Buffer
= ImageBuffer
;
773 FileData
.BufferSize
= (UINT32
) ImageSize
;
775 Status
= FwVolProtocol
->WriteFile (
778 (EFI_FV_WRITE_POLICY
)ConfigData
->FaultTolerant
,
785 Update the buffer into flash area in fault tolerant write method.
787 @param ImageBuffer Image buffer to be updated.
788 @param SizeLeft Size of the image buffer.
789 @param UpdatedSize Size of the updated buffer.
790 @param ConfigData Config data on updating driver.
791 @param FlashAddress Flash address to be updated as start address.
792 @param FvbProtocol FVB protocol.
793 @param FvbHandle Handle of FVB protocol for the updated flash range.
795 @retval EFI_SUCCESS Buffer data is updated into flash.
796 @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
797 @retval EFI_NOT_FOUND FTW protocol doesn't exist.
798 @retval EFI_OUT_OF_RESOURCES No enough backup space.
799 @retval EFI_ABORTED Error happen when update flash area.
803 FaultTolerantUpdateOnPartFv (
804 IN UINT8
*ImageBuffer
,
806 IN OUT UINTN
*UpdatedSize
,
807 IN UPDATE_CONFIG_DATA
*ConfigData
,
808 IN EFI_PHYSICAL_ADDRESS FlashAddress
,
809 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
810 IN EFI_HANDLE FvbHandle
814 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
815 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeaderTmp
;
816 EFI_PHYSICAL_ADDRESS BaseAddress
;
817 EFI_PHYSICAL_ADDRESS FvBase
;
818 EFI_PHYSICAL_ADDRESS NextBlock
;
819 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
820 EFI_FV_BLOCK_MAP_ENTRY
*PtrMap
;
823 EFI_PHYSICAL_ADDRESS StartAddress
;
824 EFI_FAULT_TOLERANT_WRITE_PROTOCOL
*FtwProtocol
;
826 UINTN FtwMaxBlockSize
;
828 UPDATE_PRIVATE_DATA PrivateData
;
840 // Get the block map to update the block one by one
842 Status
= FvbProtocol
->GetPhysicalAddress (
846 if (EFI_ERROR (Status
)) {
850 FwVolHeaderTmp
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)FvBase
;
851 if ((FlashAddress
< FvBase
) || (FlashAddress
> (FvBase
+ FwVolHeaderTmp
->FvLength
))) {
852 return EFI_INVALID_PARAMETER
;
855 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)AllocateCopyPool (
856 FwVolHeaderTmp
->HeaderLength
,
859 if (FwVolHeader
== NULL
) {
860 return EFI_OUT_OF_RESOURCES
;
864 // For fault tolerant write, we have to know how many blocks we need to
865 // update. So we will calculate number of updates and max block size first
869 TotalSize
= SizeLeft
;
870 StartAddress
= FlashAddress
;
871 BaseAddress
= FvBase
;
872 BlockMap
= &(FwVolHeader
->BlockMap
[0]);
875 while (TotalSize
> 0) {
876 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
880 BlockSize
= PtrMap
->Length
;
881 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
882 NextBlock
= BaseAddress
+ BlockSize
;
884 // Check if this block need to be updated
886 if ((StartAddress
>= BaseAddress
) && (StartAddress
< NextBlock
)) {
888 // Get the maximum block size
890 if (MaxBlockSize
< BlockSize
) {
891 MaxBlockSize
= BlockSize
;
895 // This block shall be udpated. So increment number of updates
898 Offset
= (UINTN
) (StartAddress
- BaseAddress
);
900 if ((Length
+ Offset
) > BlockSize
) {
901 Length
= BlockSize
- Offset
;
904 StartAddress
= StartAddress
+ Length
;
905 TotalSize
= TotalSize
- Length
;
906 if (TotalSize
<= 0) {
910 BaseAddress
= NextBlock
;
916 // Get the FTW protocol
918 Status
= gBS
->LocateProtocol (
919 &gEfiFaultTolerantWriteProtocolGuid
,
921 (VOID
**) &FtwProtocol
923 if (EFI_ERROR (Status
)) {
924 FreePool (FwVolHeader
);
925 return EFI_NOT_FOUND
;
928 FtwProtocol
->GetMaxBlockSize (FtwProtocol
, &FtwMaxBlockSize
);
931 // Not enough backup space. return directly
933 if (FtwMaxBlockSize
< MaxBlockSize
) {
934 FreePool (FwVolHeader
);
935 return EFI_OUT_OF_RESOURCES
;
944 // Fault Tolerant Write can only support actual fault tolerance if the write
945 // is a reclaim operation, which means the data buffer (new and old) are
946 // acutally both stored in flash. But for component update write, the data
947 // are now in memory. So we cannot actually recover the data after power
950 Status
= RetrieveLastWrite (
954 sizeof (UPDATE_PRIVATE_DATA
),
961 if (Pending
&& (Status
== EFI_NOT_FOUND
)) {
963 // I'm not the owner of the pending fault tolerant write record
964 // Cannot continue with the write operation
966 FreePool (FwVolHeader
);
970 if (EFI_ERROR(Status
)) {
971 FreePool (FwVolHeader
);
976 // Currently we start from the pending write if there is any. But if the
977 // caller is exactly the same, and the new data is already a in memory, (it
978 // cannot be stored in flash in last write,) we can just abort last write
979 // and start from the very begining.
983 // Now allocte the update private data in FTW. If there is pending
984 // write, it has already been allocated and no need to allocate here.
986 Status
= FtwProtocol
->Allocate (
989 sizeof (UPDATE_PRIVATE_DATA
),
992 if (EFI_ERROR (Status
)) {
993 FreePool (FwVolHeader
);
999 // Perform the update now. If there are pending writes, we need to
1000 // start from the pending write instead of the very beginning.
1002 TotalSize
= SizeLeft
;
1004 StartAddress
= FlashAddress
;
1005 BaseAddress
= FvBase
;
1007 Image
= ImageBuffer
;
1009 (VOID
*) &PrivateData
.FileGuid
,
1010 (VOID
*) &ConfigData
->FileGuid
,
1014 while (TotalSize
> 0) {
1015 if ((PtrMap
->NumBlocks
== 0) || (PtrMap
->Length
== 0)) {
1019 BlockSize
= (UINTN
)PtrMap
->Length
;
1020 for (Index
= 0; Index
< PtrMap
->NumBlocks
; Index
++) {
1021 NextBlock
= BaseAddress
+ BlockSize
;
1022 if ((StartAddress
>= BaseAddress
) && (StartAddress
< NextBlock
)) {
1024 // So we need to update this block
1026 Offset
= (UINTN
) (StartAddress
- BaseAddress
);
1028 if ((Length
+ Offset
) > BlockSize
) {
1029 Length
= BlockSize
- Offset
;
1033 // Add an extra check here to see if the pending record is correct
1035 if (Pending
&& (Lba
== PendingLba
)) {
1036 if ((PendingOffset
!= Offset
) || (PendingLength
!= Length
)) {
1040 Status
= EFI_ABORTED
;
1045 if ((!Pending
) || (Lba
>= PendingLba
)) {
1046 DEBUG ((EFI_D_UPDATE
, "Update Flash area from %08LX to %08LX\n", StartAddress
, (UINT64
)StartAddress
+ Length
));
1047 Status
= FtwProtocol
->Write (
1052 &PrivateData
, // Private Data
1053 FvbHandle
, // FVB handle
1056 if (EFI_ERROR (Status
)) {
1062 // Now increment StartAddress, ImageBuffer and decrease the
1063 // left size to prepare for the next block update.
1065 StartAddress
= StartAddress
+ Length
;
1066 Image
= Image
+ Length
;
1067 TotalSize
= TotalSize
- Length
;
1068 if (TotalSize
<= 0) {
1072 BaseAddress
= NextBlock
;
1076 if (EFI_ERROR (Status
)) {
1082 FreePool (FwVolHeader
);
1084 *UpdatedSize
= SizeLeft
- TotalSize
;
1090 Directly update the buffer into flash area without fault tolerant write method.
1092 @param ImageBuffer Image buffer to be updated.
1093 @param SizeLeft Size of the image buffer.
1094 @param UpdatedSize Size of the updated buffer.
1095 @param FlashAddress Flash address to be updated as start address.
1096 @param FvbProtocol FVB protocol.
1097 @param FvbHandle Handle of FVB protocol for the updated flash range.
1099 @retval EFI_SUCCESS Buffer data is updated into flash.
1100 @retval EFI_INVALID_PARAMETER Base flash address is not in FVB flash area.
1101 @retval EFI_OUT_OF_RESOURCES No enough backup space.
1105 NonFaultTolerantUpdateOnPartFv (
1106 IN UINT8
*ImageBuffer
,
1108 IN OUT UINTN
*UpdatedSize
,
1109 IN EFI_PHYSICAL_ADDRESS FlashAddress
,
1110 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvbProtocol
,
1111 IN EFI_HANDLE FvbHandle
1115 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
1116 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeaderTmp
;
1117 EFI_PHYSICAL_ADDRESS BaseAddress
;
1118 EFI_PHYSICAL_ADDRESS NextBlock
;
1119 EFI_FV_BLOCK_MAP_ENTRY
*BlockMap
;
1129 // Get the block map to update the block one by one
1131 Status
= FvbProtocol
->GetPhysicalAddress (
1135 if (EFI_ERROR (Status
)) {
1139 FwVolHeaderTmp
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)BaseAddress
;
1140 if ((FlashAddress
< BaseAddress
) || (FlashAddress
> ( BaseAddress
+ FwVolHeaderTmp
->FvLength
))) {
1141 return EFI_INVALID_PARAMETER
;
1144 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*)AllocateCopyPool (
1145 FwVolHeaderTmp
->HeaderLength
,
1148 if (FwVolHeader
== NULL
) {
1149 return EFI_OUT_OF_RESOURCES
;
1152 Image
= ImageBuffer
;
1153 TotalSize
= SizeLeft
;
1154 BlockMap
= &(FwVolHeader
->BlockMap
[0]);
1157 while (TotalSize
> 0) {
1158 if ((BlockMap
->NumBlocks
== 0) || (BlockMap
->Length
== 0)) {
1162 BlockSize
= BlockMap
->Length
;
1163 for (Index
= 0 ; Index
< BlockMap
->NumBlocks
; Index
++) {
1164 NextBlock
= BaseAddress
+ BlockSize
;
1165 if ((FlashAddress
>= BaseAddress
) && (FlashAddress
< NextBlock
)) {
1167 // So we need to update this block
1169 Offset
= (UINTN
) FlashAddress
- (UINTN
) BaseAddress
;
1171 if ((Length
+ Offset
) > BlockSize
) {
1172 Length
= BlockSize
- Offset
;
1175 DEBUG ((EFI_D_UPDATE
, "Update Flash area from %08LX to %08LX\n", FlashAddress
, (UINT64
)FlashAddress
+ Length
));
1179 Status
= UpdateBufferInOneBlock (
1187 if (EFI_ERROR (Status
)) {
1188 FreePool (FwVolHeader
);
1193 // Now increment FlashAddress, ImageBuffer and decrease the
1194 // left size to prepare for the next block update.
1196 FlashAddress
= FlashAddress
+ Length
;
1197 Image
= Image
+ Length
;
1198 TotalSize
= TotalSize
- Length
;
1199 if (TotalSize
<= 0) {
1203 BaseAddress
= NextBlock
;
1207 if (EFI_ERROR (Status
)) {
1213 FreePool (FwVolHeader
);
1215 *UpdatedSize
= SizeLeft
- TotalSize
;