TianoCore EDK2 master
Loading...
Searching...
No Matches
FaultTolerantWrite.c
Go to the documentation of this file.
1
11#include "FaultTolerantWrite.h"
12
13//
14// Fault Tolerant Write Protocol API
15//
16
29EFIAPI
32 OUT UINTN *BlockSize
33 )
34{
35 EFI_FTW_DEVICE *FtwDevice;
36
37 if (!FeaturePcdGet (PcdFullFtwServiceEnable)) {
38 return EFI_UNSUPPORTED;
39 }
40
41 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
42
43 *BlockSize = FtwDevice->SpareAreaLength;
44
45 return EFI_SUCCESS;
46}
47
70EFIAPI
73 IN EFI_GUID *CallerId,
74 IN UINTN PrivateDataSize,
75 IN UINTN NumberOfWrites
76 )
77{
78 EFI_STATUS Status;
79 UINTN Offset;
80 EFI_FTW_DEVICE *FtwDevice;
82
83 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
84
85 Status = WorkSpaceRefresh (FtwDevice);
86 if (EFI_ERROR (Status)) {
87 return EFI_ABORTED;
88 }
89
90 //
91 // Check if there is enough space for the coming allocation
92 //
93 if (FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceHeader->WriteQueueSize) {
94 DEBUG ((DEBUG_ERROR, "Ftw: Allocate() request exceed Workspace, Caller: %g\n", CallerId));
95 return EFI_BUFFER_TOO_SMALL;
96 }
97
98 //
99 // Find the last write header and record.
100 // If the FtwHeader is complete, skip the completed last write header/records
101 //
102 FtwHeader = FtwDevice->FtwLastWriteHeader;
103
104 //
105 // Previous write has not completed, access denied.
106 //
107 if ((FtwHeader->HeaderAllocated == FTW_VALID_STATE) || (FtwHeader->WritesAllocated == FTW_VALID_STATE)) {
108 return EFI_ACCESS_DENIED;
109 }
110
111 //
112 // If workspace is not enough, then reclaim workspace
113 //
114 Offset = (UINT8 *)FtwHeader - (UINT8 *)FtwDevice->FtwWorkSpace;
115 if (Offset + FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceSize) {
116 Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
117 if (EFI_ERROR (Status)) {
118 return EFI_ABORTED;
119 }
120
121 FtwHeader = FtwDevice->FtwLastWriteHeader;
122 }
123
124 //
125 // Prepare FTW write header,
126 // overwrite the buffer and write to workspace.
127 //
128 FtwHeader->WritesAllocated = FTW_INVALID_STATE;
129 FtwHeader->Complete = FTW_INVALID_STATE;
130 CopyMem (&FtwHeader->CallerId, CallerId, sizeof (EFI_GUID));
131 FtwHeader->NumberOfWrites = NumberOfWrites;
132 FtwHeader->PrivateDataSize = PrivateDataSize;
133 FtwHeader->HeaderAllocated = FTW_VALID_STATE;
134
135 Status = WriteWorkSpaceData (
136 FtwDevice->FtwFvBlock,
137 FtwDevice->WorkBlockSize,
138 FtwDevice->FtwWorkSpaceLba,
139 FtwDevice->FtwWorkSpaceBase + Offset,
141 (UINT8 *)FtwHeader
142 );
143 if (EFI_ERROR (Status)) {
144 return EFI_ABORTED;
145 }
146
147 //
148 // Update Header->WriteAllocated as VALID
149 //
150 Status = FtwUpdateFvState (
151 FtwDevice->FtwFvBlock,
152 FtwDevice->WorkBlockSize,
153 FtwDevice->FtwWorkSpaceLba,
154 FtwDevice->FtwWorkSpaceBase + Offset,
155 WRITES_ALLOCATED
156 );
157 if (EFI_ERROR (Status)) {
158 return EFI_ABORTED;
159 }
160
161 DEBUG (
162 (DEBUG_INFO,
163 "Ftw: Allocate() success, Caller:%g, # %d\n",
164 CallerId,
165 NumberOfWrites)
166 );
167
168 return EFI_SUCCESS;
169}
170
189 IN UINTN BlockSize
190 )
191{
192 EFI_STATUS Status;
193 EFI_FTW_DEVICE *FtwDevice;
196 UINTN Offset;
197 UINTN NumberOfWriteBlocks;
198
199 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
200
201 //
202 // Spare Complete but Destination not complete,
203 // Recover the target block with the spare block.
204 //
205 Header = FtwDevice->FtwLastWriteHeader;
206 Record = FtwDevice->FtwLastWriteRecord;
207
208 //
209 // IF target block is working block, THEN Flush Spare Block To Working Block;
210 // ELSE flush spare block to target block, which may be boot block after all.
211 //
212 if (IsWorkingBlock (FtwDevice, Fvb, Record->Lba)) {
213 //
214 // If target block is working block,
215 // it also need to set SPARE_COMPLETED to spare block.
216 //
217 Offset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
218 Status = FtwUpdateFvState (
219 FtwDevice->FtwBackupFvb,
220 FtwDevice->SpareBlockSize,
221 FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
222 FtwDevice->FtwWorkSpaceBaseInSpare + Offset,
223 SPARE_COMPLETED
224 );
225 if (EFI_ERROR (Status)) {
226 return EFI_ABORTED;
227 }
228
229 Status = FlushSpareBlockToWorkingBlock (FtwDevice);
230 } else if (IsBootBlock (FtwDevice, Fvb)) {
231 //
232 // Update boot block
233 //
234 Status = FlushSpareBlockToBootBlock (FtwDevice);
235 } else {
236 //
237 // Update blocks other than working block or boot block
238 //
239 NumberOfWriteBlocks = FTW_BLOCKS ((UINTN)(Record->Offset + Record->Length), BlockSize);
240 Status = FlushSpareBlockToTargetBlock (FtwDevice, Fvb, Record->Lba, BlockSize, NumberOfWriteBlocks);
241 }
242
243 if (EFI_ERROR (Status)) {
244 return EFI_ABORTED;
245 }
246
247 //
248 // Record the DestionationComplete in record
249 //
250 Offset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
251 Status = FtwUpdateFvState (
252 FtwDevice->FtwFvBlock,
253 FtwDevice->WorkBlockSize,
254 FtwDevice->FtwWorkSpaceLba,
255 FtwDevice->FtwWorkSpaceBase + Offset,
256 DEST_COMPLETED
257 );
258 if (EFI_ERROR (Status)) {
259 return EFI_ABORTED;
260 }
261
262 Record->DestinationComplete = FTW_VALID_STATE;
263
264 //
265 // If this is the last Write in these write sequence,
266 // set the complete flag of write header.
267 //
268 if (IsLastRecordOfWrites (Header, Record)) {
269 Offset = (UINT8 *)Header - FtwDevice->FtwWorkSpace;
270 Status = FtwUpdateFvState (
271 FtwDevice->FtwFvBlock,
272 FtwDevice->WorkBlockSize,
273 FtwDevice->FtwWorkSpaceLba,
274 FtwDevice->FtwWorkSpaceBase + Offset,
275 WRITES_COMPLETED
276 );
277 Header->Complete = FTW_VALID_STATE;
278 if (EFI_ERROR (Status)) {
279 return EFI_ABORTED;
280 }
281 }
282
283 return EFI_SUCCESS;
284}
285
312EFIAPI
315 IN EFI_LBA Lba,
316 IN UINTN Offset,
317 IN UINTN Length,
318 IN VOID *PrivateData,
319 IN EFI_HANDLE FvBlockHandle,
320 IN VOID *Buffer
321 )
322{
323 EFI_STATUS Status;
324 EFI_FTW_DEVICE *FtwDevice;
328 UINTN MyLength;
329 UINTN MyOffset;
330 UINTN MyBufferSize;
331 UINT8 *MyBuffer;
332 UINTN SpareBufferSize;
333 UINT8 *SpareBuffer;
334 UINTN Index;
335 UINT8 *Ptr;
336 EFI_PHYSICAL_ADDRESS FvbPhysicalAddress;
337 UINTN BlockSize;
338 UINTN NumberOfBlocks;
339 UINTN NumberOfWriteBlocks;
340 UINTN WriteLength;
341
342 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
343
344 Status = WorkSpaceRefresh (FtwDevice);
345 if (EFI_ERROR (Status)) {
346 return EFI_ABORTED;
347 }
348
349 Header = FtwDevice->FtwLastWriteHeader;
350 Record = FtwDevice->FtwLastWriteRecord;
351
352 if (IsErasedFlashBuffer ((UINT8 *)Header, sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER))) {
353 if (PrivateData == NULL) {
354 //
355 // Ftw Write Header is not allocated.
356 // No additional private data, the private data size is zero. Number of record can be set to 1.
357 //
358 Status = FtwAllocate (This, &gEfiCallerIdGuid, 0, 1);
359 if (EFI_ERROR (Status)) {
360 return Status;
361 }
362 } else {
363 //
364 // Ftw Write Header is not allocated
365 // Additional private data is not NULL, the private data size can't be determined.
366 //
367 DEBUG ((DEBUG_ERROR, "Ftw: no allocates space for write record!\n"));
368 DEBUG ((DEBUG_ERROR, "Ftw: Allocate service should be called before Write service!\n"));
369 return EFI_NOT_READY;
370 }
371 }
372
373 //
374 // If Record is out of the range of Header, return access denied.
375 //
376 if (((UINTN)Record - (UINTN)Header) > FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
377 return EFI_ACCESS_DENIED;
378 }
379
380 //
381 // Check the COMPLETE flag of last write header
382 //
383 if (Header->Complete == FTW_VALID_STATE) {
384 return EFI_ACCESS_DENIED;
385 }
386
387 if (Record->DestinationComplete == FTW_VALID_STATE) {
388 return EFI_ACCESS_DENIED;
389 }
390
391 if ((Record->SpareComplete == FTW_VALID_STATE) && (Record->DestinationComplete != FTW_VALID_STATE)) {
392 return EFI_NOT_READY;
393 }
394
395 //
396 // Get the FVB protocol by handle
397 //
398 Status = FtwGetFvbByHandle (FvBlockHandle, &Fvb);
399 if (EFI_ERROR (Status)) {
400 return EFI_NOT_FOUND;
401 }
402
403 Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress);
404 if (EFI_ERROR (Status)) {
405 DEBUG ((DEBUG_ERROR, "Ftw: Write(), Get FVB physical address - %r\n", Status));
406 return EFI_ABORTED;
407 }
408
409 //
410 // Now, one FVB has one type of BlockSize.
411 //
412 Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
413 if (EFI_ERROR (Status)) {
414 DEBUG ((DEBUG_ERROR, "Ftw: Write(), Get block size - %r\n", Status));
415 return EFI_ABORTED;
416 }
417
418 NumberOfWriteBlocks = FTW_BLOCKS (Offset + Length, BlockSize);
419 DEBUG ((DEBUG_INFO, "Ftw: Write(), BlockSize - 0x%x, NumberOfWriteBlock - 0x%x\n", BlockSize, NumberOfWriteBlocks));
420 WriteLength = NumberOfWriteBlocks * BlockSize;
421
422 //
423 // Check if the input data can fit within the spare block.
424 //
425 if (WriteLength > FtwDevice->SpareAreaLength) {
426 return EFI_BAD_BUFFER_SIZE;
427 }
428
429 //
430 // Set BootBlockUpdate FLAG if it's updating boot block.
431 //
432 if (IsBootBlock (FtwDevice, Fvb)) {
433 Record->BootBlockUpdate = FTW_VALID_STATE;
434 //
435 // Boot Block and Spare Block should have same block size and block numbers.
436 //
437 ASSERT ((BlockSize == FtwDevice->SpareBlockSize) && (NumberOfWriteBlocks == FtwDevice->NumberOfSpareBlock));
438 }
439
440 //
441 // Write the record to the work space.
442 //
443 Record->Lba = Lba;
444 Record->Offset = Offset;
445 Record->Length = Length;
446 Record->RelativeOffset = (INT64)(FvbPhysicalAddress + (UINTN)Lba * BlockSize) - (INT64)FtwDevice->SpareAreaAddress;
447 if (PrivateData != NULL) {
448 CopyMem ((Record + 1), PrivateData, (UINTN)Header->PrivateDataSize);
449 }
450
451 MyOffset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
452 MyLength = FTW_RECORD_SIZE (Header->PrivateDataSize);
453
454 Status = WriteWorkSpaceData (
455 FtwDevice->FtwFvBlock,
456 FtwDevice->WorkBlockSize,
457 FtwDevice->FtwWorkSpaceLba,
458 FtwDevice->FtwWorkSpaceBase + MyOffset,
459 MyLength,
460 (UINT8 *)Record
461 );
462 if (EFI_ERROR (Status)) {
463 return EFI_ABORTED;
464 }
465
466 //
467 // Record has written to working block, then do the data.
468 //
469 //
470 // Allocate a memory buffer
471 //
472 MyBufferSize = WriteLength;
473 MyBuffer = AllocatePool (MyBufferSize);
474 if (MyBuffer == NULL) {
475 return EFI_OUT_OF_RESOURCES;
476 }
477
478 //
479 // Read all original data from target block to memory buffer
480 //
481 Ptr = MyBuffer;
482 for (Index = 0; Index < NumberOfWriteBlocks; Index += 1) {
483 MyLength = BlockSize;
484 Status = Fvb->Read (Fvb, Lba + Index, 0, &MyLength, Ptr);
485 if (EFI_ERROR (Status)) {
486 FreePool (MyBuffer);
487 return EFI_ABORTED;
488 }
489
490 Ptr += MyLength;
491 }
492
493 //
494 // Overwrite the updating range data with
495 // the input buffer content
496 //
497 CopyMem (MyBuffer + Offset, Buffer, Length);
498
499 //
500 // Try to keep the content of spare block
501 // Save spare block into a spare backup memory buffer (Sparebuffer)
502 //
503 SpareBufferSize = FtwDevice->SpareAreaLength;
504 SpareBuffer = AllocatePool (SpareBufferSize);
505 if (SpareBuffer == NULL) {
506 FreePool (MyBuffer);
507 return EFI_OUT_OF_RESOURCES;
508 }
509
510 Ptr = SpareBuffer;
511 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
512 MyLength = FtwDevice->SpareBlockSize;
513 Status = FtwDevice->FtwBackupFvb->Read (
514 FtwDevice->FtwBackupFvb,
515 FtwDevice->FtwSpareLba + Index,
516 0,
517 &MyLength,
518 Ptr
519 );
520 if (EFI_ERROR (Status)) {
521 FreePool (MyBuffer);
522 FreePool (SpareBuffer);
523 return EFI_ABORTED;
524 }
525
526 Ptr += MyLength;
527 }
528
529 //
530 // Write the memory buffer to spare block
531 // Do not assume Spare Block and Target Block have same block size
532 //
533 Status = FtwEraseSpareBlock (FtwDevice);
534 if (EFI_ERROR (Status)) {
535 FreePool (MyBuffer);
536 FreePool (SpareBuffer);
537 return EFI_ABORTED;
538 }
539
540 Ptr = MyBuffer;
541 for (Index = 0; MyBufferSize > 0; Index += 1) {
542 if (MyBufferSize > FtwDevice->SpareBlockSize) {
543 MyLength = FtwDevice->SpareBlockSize;
544 } else {
545 MyLength = MyBufferSize;
546 }
547
548 Status = FtwDevice->FtwBackupFvb->Write (
549 FtwDevice->FtwBackupFvb,
550 FtwDevice->FtwSpareLba + Index,
551 0,
552 &MyLength,
553 Ptr
554 );
555 if (EFI_ERROR (Status)) {
556 FreePool (MyBuffer);
557 FreePool (SpareBuffer);
558 return EFI_ABORTED;
559 }
560
561 Ptr += MyLength;
562 MyBufferSize -= MyLength;
563 }
564
565 //
566 // Free MyBuffer
567 //
568 FreePool (MyBuffer);
569
570 //
571 // Set the SpareComplete in the FTW record,
572 //
573 MyOffset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
574 Status = FtwUpdateFvState (
575 FtwDevice->FtwFvBlock,
576 FtwDevice->WorkBlockSize,
577 FtwDevice->FtwWorkSpaceLba,
578 FtwDevice->FtwWorkSpaceBase + MyOffset,
579 SPARE_COMPLETED
580 );
581 if (EFI_ERROR (Status)) {
582 FreePool (SpareBuffer);
583 return EFI_ABORTED;
584 }
585
586 Record->SpareComplete = FTW_VALID_STATE;
587
588 //
589 // Since the content has already backuped in spare block, the write is
590 // guaranteed to be completed with fault tolerant manner.
591 //
592 Status = FtwWriteRecord (This, Fvb, BlockSize);
593 if (EFI_ERROR (Status)) {
594 FreePool (SpareBuffer);
595 return EFI_ABORTED;
596 }
597
598 //
599 // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
600 //
601 Status = FtwEraseSpareBlock (FtwDevice);
602 if (EFI_ERROR (Status)) {
603 FreePool (SpareBuffer);
604 return EFI_ABORTED;
605 }
606
607 Ptr = SpareBuffer;
608 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
609 MyLength = FtwDevice->SpareBlockSize;
610 Status = FtwDevice->FtwBackupFvb->Write (
611 FtwDevice->FtwBackupFvb,
612 FtwDevice->FtwSpareLba + Index,
613 0,
614 &MyLength,
615 Ptr
616 );
617 if (EFI_ERROR (Status)) {
618 FreePool (SpareBuffer);
619 return EFI_ABORTED;
620 }
621
622 Ptr += MyLength;
623 }
624
625 //
626 // All success.
627 //
628 FreePool (SpareBuffer);
629
630 DEBUG (
631 (DEBUG_INFO,
632 "Ftw: Write() success, (Lba:Offset)=(%lx:0x%x), Length: 0x%x\n",
633 Lba,
634 Offset,
635 Length)
636 );
637
638 return EFI_SUCCESS;
639}
640
656EFIAPI
659 IN EFI_HANDLE FvBlockHandle
660 )
661{
662 EFI_STATUS Status;
663 EFI_FTW_DEVICE *FtwDevice;
667 UINTN BlockSize;
668 UINTN NumberOfBlocks;
669
670 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
671
672 Status = WorkSpaceRefresh (FtwDevice);
673 if (EFI_ERROR (Status)) {
674 return EFI_ABORTED;
675 }
676
677 Header = FtwDevice->FtwLastWriteHeader;
678 Record = FtwDevice->FtwLastWriteRecord;
679
680 //
681 // Spare Complete but Destination not complete,
682 // Recover the targt block with the spare block.
683 //
684 Status = FtwGetFvbByHandle (FvBlockHandle, &Fvb);
685 if (EFI_ERROR (Status)) {
686 return EFI_NOT_FOUND;
687 }
688
689 //
690 // Now, one FVB has one type of BlockSize
691 //
692 Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
693 if (EFI_ERROR (Status)) {
694 DEBUG ((DEBUG_ERROR, "Ftw: Restart(), Get block size - %r\n", Status));
695 return EFI_ABORTED;
696 }
697
698 //
699 // Check the COMPLETE flag of last write header
700 //
701 if (Header->Complete == FTW_VALID_STATE) {
702 return EFI_ACCESS_DENIED;
703 }
704
705 //
706 // Check the flags of last write record
707 //
708 if (Record->DestinationComplete == FTW_VALID_STATE) {
709 return EFI_ACCESS_DENIED;
710 }
711
712 if ((Record->SpareComplete != FTW_VALID_STATE)) {
713 return EFI_ABORTED;
714 }
715
716 //
717 // Since the content has already backuped in spare block, the write is
718 // guaranteed to be completed with fault tolerant manner.
719 //
720 Status = FtwWriteRecord (This, Fvb, BlockSize);
721 if (EFI_ERROR (Status)) {
722 return EFI_ABORTED;
723 }
724
725 //
726 // Erase Spare block
727 // This is restart, no need to keep spareblock content.
728 //
729 Status = FtwEraseSpareBlock (FtwDevice);
730 if (EFI_ERROR (Status)) {
731 return EFI_ABORTED;
732 }
733
734 DEBUG ((DEBUG_INFO, "%a(): success\n", __func__));
735 return EFI_SUCCESS;
736}
737
749EFIAPI
752 )
753{
754 EFI_STATUS Status;
755 UINTN Offset;
756 EFI_FTW_DEVICE *FtwDevice;
757
758 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
759
760 Status = WorkSpaceRefresh (FtwDevice);
761 if (EFI_ERROR (Status)) {
762 return EFI_ABORTED;
763 }
764
765 if (FtwDevice->FtwLastWriteHeader->HeaderAllocated != FTW_VALID_STATE) {
766 return EFI_NOT_FOUND;
767 }
768
769 if (FtwDevice->FtwLastWriteHeader->Complete == FTW_VALID_STATE) {
770 return EFI_NOT_FOUND;
771 }
772
773 //
774 // Update the complete state of the header as VALID and abort.
775 //
776 Offset = (UINT8 *)FtwDevice->FtwLastWriteHeader - FtwDevice->FtwWorkSpace;
777 Status = FtwUpdateFvState (
778 FtwDevice->FtwFvBlock,
779 FtwDevice->WorkBlockSize,
780 FtwDevice->FtwWorkSpaceLba,
781 FtwDevice->FtwWorkSpaceBase + Offset,
782 WRITES_COMPLETED
783 );
784 if (EFI_ERROR (Status)) {
785 return EFI_ABORTED;
786 }
787
788 FtwDevice->FtwLastWriteHeader->Complete = FTW_VALID_STATE;
789
790 DEBUG ((DEBUG_INFO, "%a(): success\n", __func__));
791 return EFI_SUCCESS;
792}
793
818EFIAPI
821 OUT EFI_GUID *CallerId,
822 OUT EFI_LBA *Lba,
823 OUT UINTN *Offset,
824 OUT UINTN *Length,
825 IN OUT UINTN *PrivateDataSize,
826 OUT VOID *PrivateData,
827 OUT BOOLEAN *Complete
828 )
829{
830 EFI_STATUS Status;
831 EFI_FTW_DEVICE *FtwDevice;
834
835 if (!FeaturePcdGet (PcdFullFtwServiceEnable)) {
836 return EFI_UNSUPPORTED;
837 }
838
839 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
840
841 Status = WorkSpaceRefresh (FtwDevice);
842 if (EFI_ERROR (Status)) {
843 return EFI_ABORTED;
844 }
845
846 Header = FtwDevice->FtwLastWriteHeader;
847 Record = FtwDevice->FtwLastWriteRecord;
848
849 //
850 // If Header is incompleted and the last record has completed, then
851 // call Abort() to set the Header->Complete FLAG.
852 //
853 if ((Header->Complete != FTW_VALID_STATE) &&
854 (Record->DestinationComplete == FTW_VALID_STATE) &&
855 IsLastRecordOfWrites (Header, Record)
856 )
857 {
858 Status = FtwAbort (This);
859 *Complete = TRUE;
860 return EFI_NOT_FOUND;
861 }
862
863 //
864 // If there is no write header/record, return not found.
865 //
866 if (Header->HeaderAllocated != FTW_VALID_STATE) {
867 *Complete = TRUE;
868 return EFI_NOT_FOUND;
869 }
870
871 //
872 // If this record SpareComplete has not set, then it can not restart.
873 //
874 if (Record->SpareComplete != FTW_VALID_STATE) {
875 Status = GetPreviousRecordOfWrites (Header, &Record);
876 if (EFI_ERROR (Status)) {
877 FtwAbort (This);
878 *Complete = TRUE;
879 return EFI_NOT_FOUND;
880 }
881
882 ASSERT (Record != NULL);
883 }
884
885 //
886 // Fill all the requested values
887 //
888 CopyMem (CallerId, &Header->CallerId, sizeof (EFI_GUID));
889 *Lba = Record->Lba;
890 *Offset = (UINTN)Record->Offset;
891 *Length = (UINTN)Record->Length;
892 *Complete = (BOOLEAN)(Record->DestinationComplete == FTW_VALID_STATE);
893
894 if (*PrivateDataSize < Header->PrivateDataSize) {
895 *PrivateDataSize = (UINTN)Header->PrivateDataSize;
896 PrivateData = NULL;
897 Status = EFI_BUFFER_TOO_SMALL;
898 } else {
899 *PrivateDataSize = (UINTN)Header->PrivateDataSize;
900 CopyMem (PrivateData, Record + 1, *PrivateDataSize);
901 Status = EFI_SUCCESS;
902 }
903
904 DEBUG ((DEBUG_INFO, "%a(): success\n", __func__));
905
906 return Status;
907}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS FtwWriteRecord(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, IN UINTN BlockSize)
EFI_STATUS EFIAPI FtwGetMaxBlockSize(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, OUT UINTN *BlockSize)
EFI_STATUS EFIAPI FtwRestart(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, IN EFI_HANDLE FvBlockHandle)
EFI_STATUS EFIAPI FtwAllocate(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, IN EFI_GUID *CallerId, IN UINTN PrivateDataSize, IN UINTN NumberOfWrites)
EFI_STATUS EFIAPI FtwWrite(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN UINTN Length, IN VOID *PrivateData, IN EFI_HANDLE FvBlockHandle, IN VOID *Buffer)
EFI_STATUS EFIAPI FtwGetLastWrite(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This, OUT EFI_GUID *CallerId, OUT EFI_LBA *Lba, OUT UINTN *Offset, OUT UINTN *Length, IN OUT UINTN *PrivateDataSize, OUT VOID *PrivateData, OUT BOOLEAN *Complete)
EFI_STATUS EFIAPI FtwAbort(IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS FtwEraseSpareBlock(IN EFI_FTW_DEVICE *FtwDevice)
Definition: FtwMisc.c:91
EFI_STATUS FlushSpareBlockToTargetBlock(EFI_FTW_DEVICE *FtwDevice, EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, EFI_LBA Lba, UINTN BlockSize, UINTN NumberOfBlocks)
Definition: FtwMisc.c:478
EFI_STATUS FlushSpareBlockToWorkingBlock(EFI_FTW_DEVICE *FtwDevice)
Definition: FtwMisc.c:576
BOOLEAN IsBootBlock(EFI_FTW_DEVICE *FtwDevice, EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock)
Definition: FtwMisc.c:220
EFI_STATUS FtwReclaimWorkSpace(IN EFI_FTW_DEVICE *FtwDevice, IN BOOLEAN PreserveRecord)
EFI_STATUS FlushSpareBlockToBootBlock(EFI_FTW_DEVICE *FtwDevice)
Definition: FtwMisc.c:309
BOOLEAN IsWorkingBlock(EFI_FTW_DEVICE *FtwDevice, EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, EFI_LBA Lba)
Definition: FtwMisc.c:115
BOOLEAN IsErasedFlashBuffer(IN UINT8 *Buffer, IN UINTN BufferSize)
Definition: FtwMisc.c:23
EFI_STATUS WorkSpaceRefresh(IN EFI_FTW_DEVICE *FtwDevice)
BOOLEAN IsLastRecordOfWrites(IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader, IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord)
Definition: FtwMisc.c:937
EFI_STATUS WriteWorkSpaceData(IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, IN UINTN BlockSize, IN EFI_LBA Lba, IN UINTN Offset, IN UINTN Length, IN UINT8 *Buffer)
EFI_STATUS GetPreviousRecordOfWrites(IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader, IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwRecord)
Definition: FtwMisc.c:963
EFI_STATUS FtwGetFvbByHandle(IN EFI_HANDLE FvBlockHandle, OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock)
EFI_STATUS FtwUpdateFvState(IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, IN UINTN BlockSize, IN EFI_LBA Lba, IN UINTN Offset, IN UINT8 NewBit)
Definition: FtwMisc.c:743
Definition: Base.h:213