38 return EFI_UNSUPPORTED;
41 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
43 *BlockSize = FtwDevice->SpareAreaLength;
83 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
86 if (EFI_ERROR (Status)) {
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;
102 FtwHeader = FtwDevice->FtwLastWriteHeader;
107 if ((FtwHeader->HeaderAllocated == FTW_VALID_STATE) || (FtwHeader->WritesAllocated == FTW_VALID_STATE)) {
108 return EFI_ACCESS_DENIED;
114 Offset = (UINT8 *)FtwHeader - (UINT8 *)FtwDevice->FtwWorkSpace;
115 if (Offset + FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceSize) {
117 if (EFI_ERROR (Status)) {
121 FtwHeader = FtwDevice->FtwLastWriteHeader;
128 FtwHeader->WritesAllocated = FTW_INVALID_STATE;
129 FtwHeader->Complete = FTW_INVALID_STATE;
131 FtwHeader->NumberOfWrites = NumberOfWrites;
132 FtwHeader->PrivateDataSize = PrivateDataSize;
133 FtwHeader->HeaderAllocated = FTW_VALID_STATE;
136 FtwDevice->FtwFvBlock,
137 FtwDevice->WorkBlockSize,
138 FtwDevice->FtwWorkSpaceLba,
139 FtwDevice->FtwWorkSpaceBase + Offset,
143 if (EFI_ERROR (Status)) {
151 FtwDevice->FtwFvBlock,
152 FtwDevice->WorkBlockSize,
153 FtwDevice->FtwWorkSpaceLba,
154 FtwDevice->FtwWorkSpaceBase + Offset,
157 if (EFI_ERROR (Status)) {
163 "Ftw: Allocate() success, Caller:%g, # %d\n",
197 UINTN NumberOfWriteBlocks;
199 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
205 Header = FtwDevice->FtwLastWriteHeader;
206 Record = FtwDevice->FtwLastWriteRecord;
217 Offset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
219 FtwDevice->FtwBackupFvb,
220 FtwDevice->SpareBlockSize,
221 FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
222 FtwDevice->FtwWorkSpaceBaseInSpare + Offset,
225 if (EFI_ERROR (Status)) {
239 NumberOfWriteBlocks = FTW_BLOCKS ((
UINTN)(Record->Offset + Record->Length), BlockSize);
243 if (EFI_ERROR (Status)) {
250 Offset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
252 FtwDevice->FtwFvBlock,
253 FtwDevice->WorkBlockSize,
254 FtwDevice->FtwWorkSpaceLba,
255 FtwDevice->FtwWorkSpaceBase + Offset,
258 if (EFI_ERROR (Status)) {
262 Record->DestinationComplete = FTW_VALID_STATE;
269 Offset = (UINT8 *)Header - FtwDevice->FtwWorkSpace;
271 FtwDevice->FtwFvBlock,
272 FtwDevice->WorkBlockSize,
273 FtwDevice->FtwWorkSpaceLba,
274 FtwDevice->FtwWorkSpaceBase + Offset,
277 Header->Complete = FTW_VALID_STATE;
278 if (EFI_ERROR (Status)) {
318 IN VOID *PrivateData,
332 UINTN SpareBufferSize;
338 UINTN NumberOfBlocks;
339 UINTN NumberOfWriteBlocks;
342 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
345 if (EFI_ERROR (Status)) {
349 Header = FtwDevice->FtwLastWriteHeader;
350 Record = FtwDevice->FtwLastWriteRecord;
353 if (PrivateData ==
NULL) {
358 Status =
FtwAllocate (This, &gEfiCallerIdGuid, 0, 1);
359 if (EFI_ERROR (Status)) {
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;
376 if (((
UINTN)Record - (
UINTN)Header) > FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
377 return EFI_ACCESS_DENIED;
383 if (Header->Complete == FTW_VALID_STATE) {
384 return EFI_ACCESS_DENIED;
387 if (Record->DestinationComplete == FTW_VALID_STATE) {
388 return EFI_ACCESS_DENIED;
391 if ((Record->SpareComplete == FTW_VALID_STATE) && (Record->DestinationComplete != FTW_VALID_STATE)) {
392 return EFI_NOT_READY;
399 if (EFI_ERROR (Status)) {
400 return EFI_NOT_FOUND;
403 Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress);
404 if (EFI_ERROR (Status)) {
405 DEBUG ((DEBUG_ERROR,
"Ftw: Write(), Get FVB physical address - %r\n", Status));
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));
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;
425 if (WriteLength > FtwDevice->SpareAreaLength) {
426 return EFI_BAD_BUFFER_SIZE;
433 Record->BootBlockUpdate = FTW_VALID_STATE;
437 ASSERT ((BlockSize == FtwDevice->SpareBlockSize) && (NumberOfWriteBlocks == FtwDevice->NumberOfSpareBlock));
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);
451 MyOffset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
452 MyLength = FTW_RECORD_SIZE (Header->PrivateDataSize);
455 FtwDevice->FtwFvBlock,
456 FtwDevice->WorkBlockSize,
457 FtwDevice->FtwWorkSpaceLba,
458 FtwDevice->FtwWorkSpaceBase + MyOffset,
462 if (EFI_ERROR (Status)) {
472 MyBufferSize = WriteLength;
474 if (MyBuffer ==
NULL) {
475 return EFI_OUT_OF_RESOURCES;
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)) {
497 CopyMem (MyBuffer + Offset, Buffer, Length);
503 SpareBufferSize = FtwDevice->SpareAreaLength;
505 if (SpareBuffer ==
NULL) {
507 return EFI_OUT_OF_RESOURCES;
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,
520 if (EFI_ERROR (Status)) {
534 if (EFI_ERROR (Status)) {
541 for (Index = 0; MyBufferSize > 0; Index += 1) {
542 if (MyBufferSize > FtwDevice->SpareBlockSize) {
543 MyLength = FtwDevice->SpareBlockSize;
545 MyLength = MyBufferSize;
548 Status = FtwDevice->FtwBackupFvb->Write (
549 FtwDevice->FtwBackupFvb,
550 FtwDevice->FtwSpareLba + Index,
555 if (EFI_ERROR (Status)) {
562 MyBufferSize -= MyLength;
573 MyOffset = (UINT8 *)Record - FtwDevice->FtwWorkSpace;
575 FtwDevice->FtwFvBlock,
576 FtwDevice->WorkBlockSize,
577 FtwDevice->FtwWorkSpaceLba,
578 FtwDevice->FtwWorkSpaceBase + MyOffset,
581 if (EFI_ERROR (Status)) {
586 Record->SpareComplete = FTW_VALID_STATE;
593 if (EFI_ERROR (Status)) {
602 if (EFI_ERROR (Status)) {
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,
617 if (EFI_ERROR (Status)) {
632 "Ftw: Write() success, (Lba:Offset)=(%lx:0x%x), Length: 0x%x\n",
668 UINTN NumberOfBlocks;
670 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
673 if (EFI_ERROR (Status)) {
677 Header = FtwDevice->FtwLastWriteHeader;
678 Record = FtwDevice->FtwLastWriteRecord;
685 if (EFI_ERROR (Status)) {
686 return EFI_NOT_FOUND;
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));
701 if (Header->Complete == FTW_VALID_STATE) {
702 return EFI_ACCESS_DENIED;
708 if (Record->DestinationComplete == FTW_VALID_STATE) {
709 return EFI_ACCESS_DENIED;
712 if ((Record->SpareComplete != FTW_VALID_STATE)) {
721 if (EFI_ERROR (Status)) {
730 if (EFI_ERROR (Status)) {
734 DEBUG ((DEBUG_INFO,
"%a(): success\n", __func__));
758 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
761 if (EFI_ERROR (Status)) {
765 if (FtwDevice->FtwLastWriteHeader->HeaderAllocated != FTW_VALID_STATE) {
766 return EFI_NOT_FOUND;
769 if (FtwDevice->FtwLastWriteHeader->Complete == FTW_VALID_STATE) {
770 return EFI_NOT_FOUND;
776 Offset = (UINT8 *)FtwDevice->FtwLastWriteHeader - FtwDevice->FtwWorkSpace;
778 FtwDevice->FtwFvBlock,
779 FtwDevice->WorkBlockSize,
780 FtwDevice->FtwWorkSpaceLba,
781 FtwDevice->FtwWorkSpaceBase + Offset,
784 if (EFI_ERROR (Status)) {
788 FtwDevice->FtwLastWriteHeader->Complete = FTW_VALID_STATE;
790 DEBUG ((DEBUG_INFO,
"%a(): success\n", __func__));
826 OUT VOID *PrivateData,
827 OUT BOOLEAN *Complete
836 return EFI_UNSUPPORTED;
839 FtwDevice = FTW_CONTEXT_FROM_THIS (This);
842 if (EFI_ERROR (Status)) {
846 Header = FtwDevice->FtwLastWriteHeader;
847 Record = FtwDevice->FtwLastWriteRecord;
853 if ((Header->Complete != FTW_VALID_STATE) &&
854 (Record->DestinationComplete == FTW_VALID_STATE) &&
860 return EFI_NOT_FOUND;
866 if (Header->HeaderAllocated != FTW_VALID_STATE) {
868 return EFI_NOT_FOUND;
874 if (Record->SpareComplete != FTW_VALID_STATE) {
876 if (EFI_ERROR (Status)) {
879 return EFI_NOT_FOUND;
882 ASSERT (Record !=
NULL);
890 *Offset = (
UINTN)Record->Offset;
891 *Length = (
UINTN)Record->Length;
892 *Complete = (BOOLEAN)(Record->DestinationComplete == FTW_VALID_STATE);
894 if (*PrivateDataSize < Header->PrivateDataSize) {
895 *PrivateDataSize = (
UINTN)Header->PrivateDataSize;
897 Status = EFI_BUFFER_TOO_SMALL;
899 *PrivateDataSize = (
UINTN)Header->PrivateDataSize;
900 CopyMem (PrivateData, Record + 1, *PrivateDataSize);
904 DEBUG ((DEBUG_INFO,
"%a(): success\n", __func__));
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 DEBUG(Expression)
#define FeaturePcdGet(TokenName)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_PHYSICAL_ADDRESS
EFI_STATUS FtwEraseSpareBlock(IN EFI_FTW_DEVICE *FtwDevice)
EFI_STATUS FlushSpareBlockToTargetBlock(EFI_FTW_DEVICE *FtwDevice, EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, EFI_LBA Lba, UINTN BlockSize, UINTN NumberOfBlocks)
EFI_STATUS FlushSpareBlockToWorkingBlock(EFI_FTW_DEVICE *FtwDevice)
BOOLEAN IsBootBlock(EFI_FTW_DEVICE *FtwDevice, EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock)
EFI_STATUS FtwReclaimWorkSpace(IN EFI_FTW_DEVICE *FtwDevice, IN BOOLEAN PreserveRecord)
EFI_STATUS FlushSpareBlockToBootBlock(EFI_FTW_DEVICE *FtwDevice)
BOOLEAN IsWorkingBlock(EFI_FTW_DEVICE *FtwDevice, EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, EFI_LBA Lba)
BOOLEAN IsErasedFlashBuffer(IN UINT8 *Buffer, IN UINTN BufferSize)
EFI_STATUS WorkSpaceRefresh(IN EFI_FTW_DEVICE *FtwDevice)
BOOLEAN IsLastRecordOfWrites(IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader, IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord)
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)
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)