TianoCore EDK2 master
Loading...
Searching...
No Matches
FtwMisc.c
Go to the documentation of this file.
1
10#include "FaultTolerantWrite.h"
11
22BOOLEAN
24 IN UINT8 *Buffer,
25 IN UINTN BufferSize
26 )
27{
28 BOOLEAN IsEmpty;
29 UINT8 *Ptr;
30 UINTN Index;
31
32 Ptr = Buffer;
33 IsEmpty = TRUE;
34 for (Index = 0; Index < BufferSize; Index += 1) {
35 if (*Ptr++ != FTW_ERASED_BYTE) {
36 IsEmpty = FALSE;
37 break;
38 }
39 }
40
41 return IsEmpty;
42}
43
59 IN EFI_FTW_DEVICE *FtwDevice,
61 EFI_LBA Lba,
62 UINTN NumberOfBlocks
63 )
64{
65 return FvBlock->EraseBlocks (
66 FvBlock,
67 Lba,
68 NumberOfBlocks,
70 );
71}
72
92 IN EFI_FTW_DEVICE *FtwDevice
93 )
94{
95 return FtwDevice->FtwBackupFvb->EraseBlocks (
96 FtwDevice->FtwBackupFvb,
97 FtwDevice->FtwSpareLba,
98 FtwDevice->NumberOfSpareBlock,
100 );
101}
102
114BOOLEAN
116 EFI_FTW_DEVICE *FtwDevice,
118 EFI_LBA Lba
119 )
120{
121 //
122 // If matching the following condition, the target block is in working block.
123 // 1. Target block is on the FV of working block (Using the same FVB protocol instance).
124 // 2. Lba falls into the range of working block.
125 //
126 return (BOOLEAN)
127 (
128 (FvBlock == FtwDevice->FtwFvBlock) &&
129 (Lba >= FtwDevice->FtwWorkBlockLba) &&
130 (Lba <= FtwDevice->FtwWorkSpaceLba)
131 );
132}
133
148 IN EFI_PHYSICAL_ADDRESS Address,
150 )
151{
152 EFI_STATUS Status;
153 EFI_HANDLE *HandleBuffer;
154 UINTN HandleCount;
155 UINTN Index;
156 EFI_PHYSICAL_ADDRESS FvbBaseAddress;
158 EFI_HANDLE FvbHandle;
159 UINTN BlockSize;
160 UINTN NumberOfBlocks;
161
162 *FvBlock = NULL;
163 FvbHandle = NULL;
164 HandleBuffer = NULL;
165 //
166 // Locate all handles of Fvb protocol
167 //
168 Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
169 if (EFI_ERROR (Status)) {
170 return NULL;
171 }
172
173 //
174 // Get the FVB to access variable store
175 //
176 for (Index = 0; Index < HandleCount; Index += 1) {
177 Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
178 if (EFI_ERROR (Status)) {
179 break;
180 }
181
182 //
183 // Compare the address and select the right one
184 //
185 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
186 if (EFI_ERROR (Status)) {
187 continue;
188 }
189
190 //
191 // Now, one FVB has one type of BlockSize
192 //
193 Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
194 if (EFI_ERROR (Status)) {
195 continue;
196 }
197
198 if ((Address >= FvbBaseAddress) && (Address < (FvbBaseAddress + BlockSize * NumberOfBlocks))) {
199 *FvBlock = Fvb;
200 FvbHandle = HandleBuffer[Index];
201 break;
202 }
203 }
204
205 FreePool (HandleBuffer);
206 return FvbHandle;
207}
208
219BOOLEAN
221 EFI_FTW_DEVICE *FtwDevice,
223 )
224{
225 EFI_STATUS Status;
227 EFI_PHYSICAL_ADDRESS BootBlockBase;
228 UINTN BootBlockSize;
229 EFI_PHYSICAL_ADDRESS BackupBlockBase;
230 UINTN BackupBlockSize;
232 BOOLEAN IsSwapped;
233 EFI_HANDLE FvbHandle;
234
235 if (!FeaturePcdGet (PcdFullFtwServiceEnable)) {
236 return FALSE;
237 }
238
239 Status = FtwGetSarProtocol ((VOID **)&SarProtocol);
240 if (EFI_ERROR (Status)) {
241 return FALSE;
242 }
243
244 //
245 // Get the boot block range
246 //
247 Status = SarProtocol->GetRangeLocation (
248 SarProtocol,
249 &BootBlockBase,
250 &BootBlockSize,
251 &BackupBlockBase,
252 &BackupBlockSize
253 );
254 if (EFI_ERROR (Status)) {
255 return FALSE;
256 }
257
258 Status = SarProtocol->GetSwapState (SarProtocol, &IsSwapped);
259 if (EFI_ERROR (Status)) {
260 return FALSE;
261 }
262
263 //
264 // Get FVB by address
265 //
266 if (!IsSwapped) {
267 FvbHandle = GetFvbByAddress (BootBlockBase, &BootFvb);
268 } else {
269 FvbHandle = GetFvbByAddress (BackupBlockBase, &BootFvb);
270 }
271
272 if (FvbHandle == NULL) {
273 return FALSE;
274 }
275
276 //
277 // Compare the Fvb
278 //
279 return (BOOLEAN)(FvBlock == BootFvb);
280}
281
310 EFI_FTW_DEVICE *FtwDevice
311 )
312{
313 EFI_STATUS Status;
314 UINTN Length;
315 UINT8 *Buffer;
316 UINTN Count;
317 UINT8 *Ptr;
318 UINTN Index;
319 BOOLEAN TopSwap;
322 EFI_LBA BootLba;
323
324 if (!FeaturePcdGet (PcdFullFtwServiceEnable)) {
325 return EFI_UNSUPPORTED;
326 }
327
328 //
329 // Locate swap address range protocol
330 //
331 Status = FtwGetSarProtocol ((VOID **)&SarProtocol);
332 if (EFI_ERROR (Status)) {
333 return Status;
334 }
335
336 //
337 // Allocate a memory buffer
338 //
339 Length = FtwDevice->SpareAreaLength;
340 Buffer = AllocatePool (Length);
341 if (Buffer == NULL) {
342 return EFI_OUT_OF_RESOURCES;
343 }
344
345 //
346 // Get TopSwap bit state
347 //
348 Status = SarProtocol->GetSwapState (SarProtocol, &TopSwap);
349 if (EFI_ERROR (Status)) {
350 DEBUG ((DEBUG_ERROR, "Ftw: Get Top Swapped status - %r\n", Status));
351 FreePool (Buffer);
352 return EFI_ABORTED;
353 }
354
355 if (TopSwap) {
356 //
357 // Get FVB of current boot block
358 //
359 if (GetFvbByAddress (FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength, &BootFvb) == NULL) {
360 FreePool (Buffer);
361 return EFI_ABORTED;
362 }
363
364 //
365 // Read data from current boot block
366 //
367 BootLba = 0;
368 Ptr = Buffer;
369 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
370 Count = FtwDevice->SpareBlockSize;
371 Status = BootFvb->Read (
372 BootFvb,
373 BootLba + Index,
374 0,
375 &Count,
376 Ptr
377 );
378 if (EFI_ERROR (Status)) {
379 FreePool (Buffer);
380 return Status;
381 }
382
383 Ptr += Count;
384 }
385 } else {
386 //
387 // Read data from spare block
388 //
389 Ptr = Buffer;
390 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
391 Count = FtwDevice->SpareBlockSize;
392 Status = FtwDevice->FtwBackupFvb->Read (
393 FtwDevice->FtwBackupFvb,
394 FtwDevice->FtwSpareLba + Index,
395 0,
396 &Count,
397 Ptr
398 );
399 if (EFI_ERROR (Status)) {
400 FreePool (Buffer);
401 return Status;
402 }
403
404 Ptr += Count;
405 }
406
407 //
408 // Set TopSwap bit
409 //
410 Status = SarProtocol->SetSwapState (SarProtocol, TRUE);
411 if (EFI_ERROR (Status)) {
412 FreePool (Buffer);
413 return Status;
414 }
415 }
416
417 //
418 // Erase current spare block
419 // Because TopSwap is set, this actually erase the top block (boot block)!
420 //
421 Status = FtwEraseSpareBlock (FtwDevice);
422 if (EFI_ERROR (Status)) {
423 FreePool (Buffer);
424 return EFI_ABORTED;
425 }
426
427 //
428 // Write memory buffer to current spare block. Still top block.
429 //
430 Ptr = Buffer;
431 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
432 Count = FtwDevice->SpareBlockSize;
433 Status = FtwDevice->FtwBackupFvb->Write (
434 FtwDevice->FtwBackupFvb,
435 FtwDevice->FtwSpareLba + Index,
436 0,
437 &Count,
438 Ptr
439 );
440 if (EFI_ERROR (Status)) {
441 DEBUG ((DEBUG_ERROR, "Ftw: FVB Write boot block - %r\n", Status));
442 FreePool (Buffer);
443 return Status;
444 }
445
446 Ptr += Count;
447 }
448
449 FreePool (Buffer);
450
451 //
452 // Clear TopSwap bit
453 //
454 Status = SarProtocol->SetSwapState (SarProtocol, FALSE);
455
456 return Status;
457}
458
479 EFI_FTW_DEVICE *FtwDevice,
481 EFI_LBA Lba,
482 UINTN BlockSize,
483 UINTN NumberOfBlocks
484 )
485{
486 EFI_STATUS Status;
487 UINTN Length;
488 UINT8 *Buffer;
489 UINTN Count;
490 UINT8 *Ptr;
491 UINTN Index;
492
493 if ((FtwDevice == NULL) || (FvBlock == NULL)) {
494 return EFI_INVALID_PARAMETER;
495 }
496
497 //
498 // Allocate a memory buffer
499 //
500 Length = FtwDevice->SpareAreaLength;
501 Buffer = AllocatePool (Length);
502 if (Buffer == NULL) {
503 return EFI_OUT_OF_RESOURCES;
504 }
505
506 //
507 // Read all content of spare block to memory buffer
508 //
509 Ptr = Buffer;
510 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
511 Count = FtwDevice->SpareBlockSize;
512 Status = FtwDevice->FtwBackupFvb->Read (
513 FtwDevice->FtwBackupFvb,
514 FtwDevice->FtwSpareLba + Index,
515 0,
516 &Count,
517 Ptr
518 );
519 if (EFI_ERROR (Status)) {
520 FreePool (Buffer);
521 return Status;
522 }
523
524 Ptr += Count;
525 }
526
527 //
528 // Erase the target block
529 //
530 Status = FtwEraseBlock (FtwDevice, FvBlock, Lba, NumberOfBlocks);
531 if (EFI_ERROR (Status)) {
532 FreePool (Buffer);
533 return EFI_ABORTED;
534 }
535
536 //
537 // Write memory buffer to block, using the FvBlock protocol interface
538 //
539 Ptr = Buffer;
540 for (Index = 0; Index < NumberOfBlocks; Index += 1) {
541 Count = BlockSize;
542 Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);
543 if (EFI_ERROR (Status)) {
544 DEBUG ((DEBUG_ERROR, "Ftw: FVB Write block - %r\n", Status));
545 FreePool (Buffer);
546 return Status;
547 }
548
549 Ptr += Count;
550 }
551
552 FreePool (Buffer);
553
554 return Status;
555}
556
577 EFI_FTW_DEVICE *FtwDevice
578 )
579{
580 EFI_STATUS Status;
581 UINTN Length;
582 UINT8 *Buffer;
583 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
584 UINTN Count;
585 UINT8 *Ptr;
586 UINTN Index;
587
588 //
589 // Allocate a memory buffer
590 //
591 Length = FtwDevice->SpareAreaLength;
592 Buffer = AllocatePool (Length);
593 if (Buffer == NULL) {
594 return EFI_OUT_OF_RESOURCES;
595 }
596
597 //
598 // To guarantee that the WorkingBlockValid is set on spare block
599 //
600 // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
601 // WorkingBlockValid);
602 // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
603 //
605 FtwDevice->FtwBackupFvb,
606 FtwDevice->SpareBlockSize,
607 FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
608 FtwDevice->FtwWorkSpaceBaseInSpare + sizeof (EFI_GUID) + sizeof (UINT32),
609 WORKING_BLOCK_VALID
610 );
611 //
612 // Read from spare block to memory buffer
613 //
614 Ptr = Buffer;
615 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
616 Count = FtwDevice->SpareBlockSize;
617 Status = FtwDevice->FtwBackupFvb->Read (
618 FtwDevice->FtwBackupFvb,
619 FtwDevice->FtwSpareLba + Index,
620 0,
621 &Count,
622 Ptr
623 );
624 if (EFI_ERROR (Status)) {
625 FreePool (Buffer);
626 return Status;
627 }
628
629 Ptr += Count;
630 }
631
632 //
633 // Clear the CRC and STATE, copy data from spare to working block.
634 //
635 WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *)(Buffer + (UINTN)FtwDevice->FtwWorkSpaceLbaInSpare * FtwDevice->SpareBlockSize + FtwDevice->FtwWorkSpaceBaseInSpare);
636 InitWorkSpaceHeader (WorkingBlockHeader);
637 WorkingBlockHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
638 WorkingBlockHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
639
640 //
641 // target block is working block, then
642 // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
643 // before erase the working block.
644 //
645 // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
646 // WorkingBlockInvalid);
647 // So hardcode offset as sizeof(EFI_GUID)+sizeof(UINT32) to
648 // skip Signature and Crc.
649 //
650 Status = FtwUpdateFvState (
651 FtwDevice->FtwFvBlock,
652 FtwDevice->WorkBlockSize,
653 FtwDevice->FtwWorkSpaceLba,
654 FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
655 WORKING_BLOCK_INVALID
656 );
657 if (EFI_ERROR (Status)) {
658 FreePool (Buffer);
659 return EFI_ABORTED;
660 }
661
662 FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
663
664 //
665 // Erase the working block
666 //
667 Status = FtwEraseBlock (FtwDevice, FtwDevice->FtwFvBlock, FtwDevice->FtwWorkBlockLba, FtwDevice->NumberOfWorkBlock);
668 if (EFI_ERROR (Status)) {
669 FreePool (Buffer);
670 return EFI_ABORTED;
671 }
672
673 //
674 // Write memory buffer to working block, using the FvBlock protocol interface
675 //
676 Ptr = Buffer;
677 for (Index = 0; Index < FtwDevice->NumberOfWorkBlock; Index += 1) {
678 Count = FtwDevice->WorkBlockSize;
679 Status = FtwDevice->FtwFvBlock->Write (
680 FtwDevice->FtwFvBlock,
681 FtwDevice->FtwWorkBlockLba + Index,
682 0,
683 &Count,
684 Ptr
685 );
686 if (EFI_ERROR (Status)) {
687 DEBUG ((DEBUG_ERROR, "Ftw: FVB Write block - %r\n", Status));
688 FreePool (Buffer);
689 return Status;
690 }
691
692 Ptr += Count;
693 }
694
695 //
696 // Since the memory buffer will not be used, free memory Buffer.
697 //
698 FreePool (Buffer);
699
700 //
701 // Update the VALID of the working block
702 //
703 // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER, WorkingBlockValid);
704 // So hardcode offset as sizeof(EFI_GUID)+sizeof(UINT32) to skip Signature and Crc.
705 //
706 Status = FtwUpdateFvState (
707 FtwDevice->FtwFvBlock,
708 FtwDevice->WorkBlockSize,
709 FtwDevice->FtwWorkSpaceLba,
710 FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
711 WORKING_BLOCK_VALID
712 );
713 if (EFI_ERROR (Status)) {
714 return EFI_ABORTED;
715 }
716
717 FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
718 FtwDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;
719
720 return EFI_SUCCESS;
721}
722
745 IN UINTN BlockSize,
746 IN EFI_LBA Lba,
747 IN UINTN Offset,
748 IN UINT8 NewBit
749 )
750{
751 EFI_STATUS Status;
752 UINT8 State;
753 UINTN Length;
754
755 //
756 // Calculate the real Offset and Lba to write.
757 //
758 while (Offset >= BlockSize) {
759 Offset -= BlockSize;
760 Lba++;
761 }
762
763 //
764 // Read state from device, assume State is only one byte.
765 //
766 Length = sizeof (UINT8);
767 Status = FvBlock->Read (FvBlock, Lba, Offset, &Length, &State);
768 if (EFI_ERROR (Status)) {
769 return EFI_ABORTED;
770 }
771
772 State ^= FTW_POLARITY_REVERT;
773 State = (UINT8)(State | NewBit);
774 State ^= FTW_POLARITY_REVERT;
775
776 //
777 // Write state back to device
778 //
779 Length = sizeof (UINT8);
780 Status = FvBlock->Write (FvBlock, Lba, Offset, &Length, &State);
781
782 return Status;
783}
784
802 IN UINTN FtwWorkSpaceSize,
803 OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader
804 )
805{
806 UINTN Offset;
808
809 *FtwWriteHeader = NULL;
810 FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *)(FtwWorkSpaceHeader + 1);
812
813 if (!CompareGuid (&FtwWorkSpaceHeader->Signature, &gEdkiiWorkingBlockSignatureGuid)) {
814 *FtwWriteHeader = FtwHeader;
815 return EFI_ABORTED;
816 }
817
818 while (FtwHeader->Complete == FTW_VALID_STATE) {
819 Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
820 //
821 // If Offset exceed the FTW work space boudary, return error.
822 //
823
824 if ((Offset + sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER)) >= FtwWorkSpaceSize) {
825 *FtwWriteHeader = FtwHeader;
826 return EFI_ABORTED;
827 }
828
829 FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *)((UINT8 *)FtwWorkSpaceHeader + Offset);
830 }
831
832 //
833 // Last write header is found
834 //
835 *FtwWriteHeader = FtwHeader;
836
837 return EFI_SUCCESS;
838}
839
855 IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader,
857 )
858{
859 UINTN Index;
861
863 FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)(FtwWriteHeader + 1);
864
865 //
866 // Try to find the last write record "that has not completed"
867 //
868 for (Index = 0; Index < FtwWriteHeader->NumberOfWrites; Index += 1) {
869 if (FtwRecord->DestinationComplete != FTW_VALID_STATE) {
870 //
871 // The last write record is found
872 //
873 *FtwWriteRecord = FtwRecord;
874 return EFI_SUCCESS;
875 }
876
877 FtwRecord++;
878
879 if (FtwWriteHeader->PrivateDataSize != 0) {
880 FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)((UINTN)FtwRecord + (UINTN)FtwWriteHeader->PrivateDataSize);
881 }
882 }
883
884 //
885 // if Index == NumberOfWrites, then
886 // the last record has been written successfully,
887 // but the Header->Complete Flag has not been set.
888 // also return the last record.
889 //
890 if (Index == FtwWriteHeader->NumberOfWrites) {
891 *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)((UINTN)FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
892 return EFI_SUCCESS;
893 }
894
895 return EFI_ABORTED;
896}
897
908BOOLEAN
912 )
913{
914 UINT8 *Head;
915 UINT8 *Ptr;
916
917 Head = (UINT8 *)FtwHeader;
918 Ptr = (UINT8 *)FtwRecord;
919
920 Head += sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER);
921 return (BOOLEAN)(Head == Ptr);
922}
923
936BOOLEAN
940 )
941{
942 UINT8 *Head;
943 UINT8 *Ptr;
944
945 Head = (UINT8 *)FtwHeader;
946 Ptr = (UINT8 *)FtwRecord;
947
948 Head += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);
949 return (BOOLEAN)(Head == Ptr);
950}
951
966 )
967{
968 UINT8 *Ptr;
969
970 if (IsFirstRecordOfWrites (FtwHeader, *FtwRecord)) {
971 *FtwRecord = NULL;
972 return EFI_ACCESS_DENIED;
973 }
974
975 Ptr = (UINT8 *)(*FtwRecord);
976 Ptr -= FTW_RECORD_SIZE (FtwHeader->PrivateDataSize);
977 *FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)Ptr;
978 return EFI_SUCCESS;
979}
980
993 OUT EFI_FTW_DEVICE **FtwData
994 )
995{
996 EFI_STATUS Status;
997 EFI_PHYSICAL_ADDRESS WorkSpaceAddress;
998 UINT64 Size;
999 UINTN FtwWorkingSize;
1000 EFI_FTW_DEVICE *FtwDevice;
1001
1002 FtwWorkingSize = 0;
1003
1004 Status = GetVariableFlashFtwWorkingInfo (&WorkSpaceAddress, &Size);
1005 ASSERT_EFI_ERROR (Status);
1006
1007 Status = SafeUint64ToUintn (Size, &FtwWorkingSize);
1008 // This driver currently assumes the size will be UINTN so assert the value is safe for now.
1009 ASSERT_EFI_ERROR (Status);
1010
1011 //
1012 // Allocate private data of this driver,
1013 // Including the FtwWorkSpace[FTW_WORK_SPACE_SIZE].
1014 //
1015 FtwDevice = AllocateZeroPool (sizeof (EFI_FTW_DEVICE) + FtwWorkingSize);
1016 if (FtwDevice == NULL) {
1017 return EFI_OUT_OF_RESOURCES;
1018 }
1019
1020 FtwDevice->WorkSpaceAddress = WorkSpaceAddress;
1021 FtwDevice->WorkSpaceLength = FtwWorkingSize;
1022
1023 Status = GetVariableFlashFtwSpareInfo (&FtwDevice->SpareAreaAddress, &Size);
1024 ASSERT_EFI_ERROR (Status);
1025
1026 Status = SafeUint64ToUintn (Size, &FtwDevice->SpareAreaLength);
1027 // This driver currently assumes the size will be UINTN so assert the value is safe for now.
1028 ASSERT_EFI_ERROR (Status);
1029
1030 //
1031 // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
1032 //
1033 if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {
1034 DEBUG ((DEBUG_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));
1035 FreePool (FtwDevice);
1036 return EFI_INVALID_PARAMETER;
1037 }
1038
1039 FtwDevice->Signature = FTW_DEVICE_SIGNATURE;
1040 FtwDevice->FtwFvBlock = NULL;
1041 FtwDevice->FtwBackupFvb = NULL;
1042 FtwDevice->FtwWorkSpaceLba = (EFI_LBA)(-1);
1043 FtwDevice->FtwSpareLba = (EFI_LBA)(-1);
1044
1045 *FtwData = FtwDevice;
1046 return EFI_SUCCESS;
1047}
1048
1061 IN OUT EFI_FTW_DEVICE *FtwDevice
1062 )
1063{
1064 EFI_STATUS Status;
1065 EFI_HANDLE *HandleBuffer;
1066 UINTN HandleCount;
1067 UINTN Index;
1068 EFI_PHYSICAL_ADDRESS FvbBaseAddress;
1070 EFI_FVB_ATTRIBUTES_2 Attributes;
1071 UINT32 LbaIndex;
1072 UINTN BlockSize;
1073 UINTN NumberOfBlocks;
1074
1075 HandleBuffer = NULL;
1076
1077 //
1078 // Get all FVB handle.
1079 //
1080 Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
1081 if (EFI_ERROR (Status)) {
1082 return EFI_NOT_FOUND;
1083 }
1084
1085 //
1086 // Get the FVB to access variable store
1087 //
1088 Fvb = NULL;
1089 for (Index = 0; Index < HandleCount; Index += 1) {
1090 Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
1091 if (EFI_ERROR (Status)) {
1092 Status = EFI_NOT_FOUND;
1093 break;
1094 }
1095
1096 //
1097 // Ensure this FVB protocol support Write operation.
1098 //
1099 Status = Fvb->GetAttributes (Fvb, &Attributes);
1100 if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
1101 continue;
1102 }
1103
1104 //
1105 // Compare the address and select the right one
1106 //
1107 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
1108 if (EFI_ERROR (Status)) {
1109 continue;
1110 }
1111
1112 //
1113 // Now, one FVB has one type of BlockSize.
1114 //
1115 Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
1116 if (EFI_ERROR (Status)) {
1117 continue;
1118 }
1119
1120 if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) &&
1121 ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + BlockSize * NumberOfBlocks)))
1122 {
1123 FtwDevice->FtwFvBlock = Fvb;
1124 //
1125 // To get the LBA of work space
1126 //
1127 for (LbaIndex = 1; LbaIndex <= NumberOfBlocks; LbaIndex += 1) {
1128 if ( (FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + BlockSize * (LbaIndex - 1)))
1129 && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + BlockSize * LbaIndex)))
1130 {
1131 FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;
1132 //
1133 // Get the Work space size and Base(Offset)
1134 //
1135 FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength;
1136 FtwDevice->WorkBlockSize = BlockSize;
1137 FtwDevice->FtwWorkSpaceBase = (UINTN)(FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FtwDevice->WorkBlockSize * (LbaIndex - 1)));
1138 FtwDevice->NumberOfWorkSpaceBlock = FTW_BLOCKS (FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize, FtwDevice->WorkBlockSize);
1139 if (FtwDevice->FtwWorkSpaceSize >= FtwDevice->WorkBlockSize) {
1140 //
1141 // Check the alignment of work space address and length, they should be block size aligned when work space size is larger than one block size.
1142 //
1143 if (((FtwDevice->WorkSpaceAddress & (FtwDevice->WorkBlockSize - 1)) != 0) ||
1144 ((FtwDevice->WorkSpaceLength & (FtwDevice->WorkBlockSize - 1)) != 0))
1145 {
1146 DEBUG ((DEBUG_ERROR, "Ftw: Work space address or length is not block size aligned when work space size is larger than one block size\n"));
1147 FreePool (HandleBuffer);
1148 ASSERT (FALSE);
1149 return EFI_ABORTED;
1150 }
1151 } else if ((FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize) > FtwDevice->WorkBlockSize) {
1152 DEBUG ((DEBUG_ERROR, "Ftw: The work space range should not span blocks when work space size is less than one block size\n"));
1153 FreePool (HandleBuffer);
1154 ASSERT (FALSE);
1155 return EFI_ABORTED;
1156 }
1157
1158 break;
1159 }
1160 }
1161 }
1162
1163 if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) &&
1164 ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + BlockSize * NumberOfBlocks)))
1165 {
1166 FtwDevice->FtwBackupFvb = Fvb;
1167 //
1168 // To get the LBA of spare
1169 //
1170 for (LbaIndex = 1; LbaIndex <= NumberOfBlocks; LbaIndex += 1) {
1171 if ( (FtwDevice->SpareAreaAddress >= (FvbBaseAddress + BlockSize * (LbaIndex - 1)))
1172 && (FtwDevice->SpareAreaAddress < (FvbBaseAddress + BlockSize * LbaIndex)))
1173 {
1174 //
1175 // Get the NumberOfSpareBlock and BlockSize
1176 //
1177 FtwDevice->FtwSpareLba = LbaIndex - 1;
1178 FtwDevice->SpareBlockSize = BlockSize;
1179 FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->SpareBlockSize;
1180 //
1181 // Check the range of spare area to make sure that it's in FV range
1182 //
1183 if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > NumberOfBlocks) {
1184 DEBUG ((DEBUG_ERROR, "Ftw: Spare area is out of FV range\n"));
1185 FreePool (HandleBuffer);
1186 ASSERT (FALSE);
1187 return EFI_ABORTED;
1188 }
1189
1190 //
1191 // Check the alignment of spare area address and length, they should be block size aligned
1192 //
1193 if (((FtwDevice->SpareAreaAddress & (FtwDevice->SpareBlockSize - 1)) != 0) ||
1194 ((FtwDevice->SpareAreaLength & (FtwDevice->SpareBlockSize - 1)) != 0))
1195 {
1196 DEBUG ((DEBUG_ERROR, "Ftw: Spare area address or length is not block size aligned\n"));
1197 FreePool (HandleBuffer);
1198 //
1199 // Report Status Code EFI_SW_EC_ABORTED.
1200 //
1201 REPORT_STATUS_CODE ((EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ABORTED));
1202 ASSERT (FALSE);
1203 CpuDeadLoop ();
1204 }
1205
1206 break;
1207 }
1208 }
1209 }
1210 }
1211
1212 FreePool (HandleBuffer);
1213
1214 if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||
1215 (FtwDevice->FtwWorkSpaceLba == (EFI_LBA)(-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA)(-1)))
1216 {
1217 return EFI_ABORTED;
1218 }
1219
1220 DEBUG ((DEBUG_INFO, "Ftw: FtwWorkSpaceLba - 0x%lx, WorkBlockSize - 0x%x, FtwWorkSpaceBase - 0x%x\n", FtwDevice->FtwWorkSpaceLba, FtwDevice->WorkBlockSize, FtwDevice->FtwWorkSpaceBase));
1221 DEBUG ((DEBUG_INFO, "Ftw: FtwSpareLba - 0x%lx, SpareBlockSize - 0x%x\n", FtwDevice->FtwSpareLba, FtwDevice->SpareBlockSize));
1222
1223 return EFI_SUCCESS;
1224}
1225
1237 IN OUT EFI_FTW_DEVICE *FtwDevice
1238 )
1239{
1240 EFI_STATUS Status;
1243 UINTN Offset;
1244 EFI_HANDLE FvbHandle;
1245 EFI_LBA WorkSpaceLbaOffset;
1246
1247 //
1248 // Find the right SMM Fvb protocol instance for FTW.
1249 //
1250 Status = FindFvbForFtw (FtwDevice);
1251 if (EFI_ERROR (Status)) {
1252 return EFI_NOT_FOUND;
1253 }
1254
1255 //
1256 // Calculate the start LBA of working block.
1257 //
1258 if (FtwDevice->FtwWorkSpaceSize >= FtwDevice->WorkBlockSize) {
1259 //
1260 // Working block is a standalone area which only contains working space.
1261 //
1262 FtwDevice->NumberOfWorkBlock = FtwDevice->NumberOfWorkSpaceBlock;
1263 } else {
1264 //
1265 // Working block is an area which
1266 // contains working space in its last block and has the same size as spare
1267 // block, unless there are not enough blocks before the block that contains
1268 // working space.
1269 //
1270 FtwDevice->NumberOfWorkBlock = (UINTN)(FtwDevice->FtwWorkSpaceLba + FtwDevice->NumberOfWorkSpaceBlock);
1271 while (FtwDevice->NumberOfWorkBlock * FtwDevice->WorkBlockSize > FtwDevice->SpareAreaLength) {
1272 FtwDevice->NumberOfWorkBlock--;
1273 }
1274 }
1275
1276 FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba + FtwDevice->NumberOfWorkSpaceBlock - FtwDevice->NumberOfWorkBlock;
1277 DEBUG ((DEBUG_INFO, "Ftw: NumberOfWorkBlock - 0x%x, FtwWorkBlockLba - 0x%lx\n", FtwDevice->NumberOfWorkBlock, FtwDevice->FtwWorkBlockLba));
1278
1279 //
1280 // Calcualte the LBA and base of work space in spare block.
1281 // Note: Do not assume Spare Block and Work Block have same block size.
1282 //
1283 WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;
1284 FtwDevice->FtwWorkSpaceLbaInSpare = (EFI_LBA)(((UINTN)WorkSpaceLbaOffset * FtwDevice->WorkBlockSize + FtwDevice->FtwWorkSpaceBase) / FtwDevice->SpareBlockSize);
1285 FtwDevice->FtwWorkSpaceBaseInSpare = ((UINTN)WorkSpaceLbaOffset * FtwDevice->WorkBlockSize + FtwDevice->FtwWorkSpaceBase) % FtwDevice->SpareBlockSize;
1286 DEBUG ((DEBUG_INFO, "Ftw: WorkSpaceLbaInSpare - 0x%lx, WorkSpaceBaseInSpare - 0x%x\n", FtwDevice->FtwWorkSpaceLbaInSpare, FtwDevice->FtwWorkSpaceBaseInSpare));
1287
1288 //
1289 // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
1290 //
1291 FtwDevice->FtwWorkSpace = (UINT8 *)(FtwDevice + 1);
1292 FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *)FtwDevice->FtwWorkSpace;
1293
1294 FtwDevice->FtwLastWriteHeader = NULL;
1295 FtwDevice->FtwLastWriteRecord = NULL;
1296
1297 InitializeLocalWorkSpaceHeader (FtwDevice->WorkSpaceLength);
1298
1299 //
1300 // Refresh the working space data from working block
1301 //
1302 Status = WorkSpaceRefresh (FtwDevice);
1303 ASSERT_EFI_ERROR (Status);
1304 //
1305 // If the working block workspace is not valid, try the spare block
1306 //
1307 if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
1308 //
1309 // Read from spare block
1310 //
1311 Status = ReadWorkSpaceData (
1312 FtwDevice->FtwBackupFvb,
1313 FtwDevice->SpareBlockSize,
1314 FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
1315 FtwDevice->FtwWorkSpaceBaseInSpare,
1316 FtwDevice->FtwWorkSpaceSize,
1317 FtwDevice->FtwWorkSpace
1318 );
1319 ASSERT_EFI_ERROR (Status);
1320
1321 //
1322 // If spare block is valid, then replace working block content.
1323 //
1324 if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
1325 Status = FlushSpareBlockToWorkingBlock (FtwDevice);
1326 DEBUG ((
1327 DEBUG_INFO,
1328 "Ftw: Restart working block update in %a() - %r\n",
1329 __func__,
1330 Status
1331 ));
1332 FtwAbort (&FtwDevice->FtwInstance);
1333 //
1334 // Refresh work space.
1335 //
1336 Status = WorkSpaceRefresh (FtwDevice);
1337 ASSERT_EFI_ERROR (Status);
1338 } else {
1339 DEBUG ((
1340 DEBUG_INFO,
1341 "Ftw: Both working and spare blocks are invalid, init workspace\n"
1342 ));
1343 //
1344 // If both are invalid, then initialize work space.
1345 //
1346 SetMem (
1347 FtwDevice->FtwWorkSpace,
1348 FtwDevice->FtwWorkSpaceSize,
1349 FTW_ERASED_BYTE
1350 );
1351 InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader);
1352 //
1353 // Initialize the work space
1354 //
1355 Status = FtwReclaimWorkSpace (FtwDevice, FALSE);
1356 ASSERT_EFI_ERROR (Status);
1357 }
1358 }
1359
1360 //
1361 // If the FtwDevice->FtwLastWriteRecord is 1st record of write header &&
1362 // (! SpareComplete) THEN call Abort().
1363 //
1364 if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) &&
1365 (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) &&
1366 IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
1367 )
1368 {
1369 DEBUG ((DEBUG_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n"));
1370 FtwAbort (&FtwDevice->FtwInstance);
1371 }
1372
1373 //
1374 // If Header is incompleted and the last record has completed, then
1375 // call Abort() to set the Header->Complete FLAG.
1376 //
1377 if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
1378 (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) &&
1379 IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
1380 )
1381 {
1382 DEBUG ((DEBUG_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n"));
1383 FtwAbort (&FtwDevice->FtwInstance);
1384 }
1385
1386 //
1387 // To check the workspace buffer following last Write header/records is EMPTY or not.
1388 // If it's not EMPTY, FTW also need to call reclaim().
1389 //
1390 FtwHeader = FtwDevice->FtwLastWriteHeader;
1391 Offset = (UINT8 *)FtwHeader - FtwDevice->FtwWorkSpace;
1392 if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
1393 Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
1394 }
1395
1396 if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {
1397 Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
1398 ASSERT_EFI_ERROR (Status);
1399 }
1400
1401 //
1402 // Restart if it's boot block
1403 //
1404 if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
1405 (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE)
1406 )
1407 {
1408 if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) {
1409 Status = FlushSpareBlockToBootBlock (FtwDevice);
1410 DEBUG ((DEBUG_ERROR, "Ftw: Restart boot block update - %r\n", Status));
1411 ASSERT_EFI_ERROR (Status);
1412 FtwAbort (&FtwDevice->FtwInstance);
1413 } else {
1414 //
1415 // if (SpareCompleted) THEN Restart to fault tolerant write.
1416 //
1417 FvbHandle = NULL;
1418 FvbHandle = GetFvbByAddress ((EFI_PHYSICAL_ADDRESS)(UINTN)((INT64)FtwDevice->SpareAreaAddress + FtwDevice->FtwLastWriteRecord->RelativeOffset), &Fvb);
1419 if (FvbHandle != NULL) {
1420 Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);
1421 DEBUG ((DEBUG_ERROR, "Ftw: Restart last write - %r\n", Status));
1422 ASSERT_EFI_ERROR (Status);
1423 }
1424
1425 FtwAbort (&FtwDevice->FtwInstance);
1426 }
1427 }
1428
1429 //
1430 // Hook the protocol API
1431 //
1432 FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize;
1433 FtwDevice->FtwInstance.Allocate = FtwAllocate;
1434 FtwDevice->FtwInstance.Write = FtwWrite;
1435 FtwDevice->FtwInstance.Restart = FtwRestart;
1436 FtwDevice->FtwInstance.Abort = FtwAbort;
1437 FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite;
1438
1439 return EFI_SUCCESS;
1440}
UINT64 UINTN
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
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 EFI_LBA_LIST_TERMINATOR
EFI_STATUS FtwEraseSpareBlock(IN EFI_FTW_DEVICE *FtwDevice)
Definition: FtwMisc.c:91
EFI_STATUS FtwGetLastWriteRecord(IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader, OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwWriteRecord)
Definition: FtwMisc.c:854
EFI_HANDLE GetFvbByAddress(IN EFI_PHYSICAL_ADDRESS Address, OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock)
Definition: FtwMisc.c:147
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 InitFtwDevice(OUT EFI_FTW_DEVICE **FtwData)
Definition: FtwMisc.c:992
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 FtwEraseBlock(IN EFI_FTW_DEVICE *FtwDevice, EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, EFI_LBA Lba, UINTN NumberOfBlocks)
Definition: FtwMisc.c:58
BOOLEAN IsLastRecordOfWrites(IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader, IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord)
Definition: FtwMisc.c:937
EFI_STATUS FtwGetLastWriteHeader(IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader, IN UINTN FtwWorkSpaceSize, OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader)
Definition: FtwMisc.c:800
EFI_STATUS InitFtwProtocol(IN OUT EFI_FTW_DEVICE *FtwDevice)
Definition: FtwMisc.c:1236
BOOLEAN IsFirstRecordOfWrites(IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader, IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord)
Definition: FtwMisc.c:909
EFI_STATUS FindFvbForFtw(IN OUT EFI_FTW_DEVICE *FtwDevice)
Definition: FtwMisc.c:1060
EFI_STATUS GetPreviousRecordOfWrites(IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader, IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwRecord)
Definition: FtwMisc.c:963
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
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE(Type, Value)
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
UINT32 EFI_FVB_ATTRIBUTES_2
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFIAPI SafeUint64ToUintn(IN UINT64 Operand, OUT UINTN *Result)
Definition: SafeIntLib32.c:307
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
BOOLEAN IsValidWorkSpace(IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader)
EFI_STATUS InitWorkSpaceHeader(IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader)
EFI_STATUS FtwGetSarProtocol(OUT VOID **SarProtocol)
EFI_STATUS FtwReclaimWorkSpace(IN EFI_FTW_DEVICE *FtwDevice, IN BOOLEAN PreserveRecord)
EFI_STATUS WorkSpaceRefresh(IN EFI_FTW_DEVICE *FtwDevice)
VOID InitializeLocalWorkSpaceHeader(IN UINTN WorkSpaceLength)
EFI_STATUS GetFvbCountAndBuffer(OUT UINTN *NumberHandles, OUT EFI_HANDLE **Buffer)
EFI_STATUS FtwGetFvbByHandle(IN EFI_HANDLE FvBlockHandle, OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock)
EFI_STATUS ReadWorkSpaceData(IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, IN UINTN BlockSize, IN EFI_LBA Lba, IN UINTN Offset, IN UINTN Length, OUT UINT8 *Buffer)
EFI_STATUS EFIAPI GetVariableFlashFtwWorkingInfo(OUT EFI_PHYSICAL_ADDRESS *BaseAddress, OUT UINT64 *Length)
EFI_STATUS EFIAPI GetVariableFlashFtwSpareInfo(OUT EFI_PHYSICAL_ADDRESS *BaseAddress, OUT UINT64 *Length)
Definition: Base.h:213