diff --git a/DuetPkg/FvbRuntimeService/DUETFwh.inf b/DuetPkg/FvbRuntimeService/DUETFwh.inf index 9a73ae8110..b00ea7b5f1 100644 --- a/DuetPkg/FvbRuntimeService/DUETFwh.inf +++ b/DuetPkg/FvbRuntimeService/DUETFwh.inf @@ -51,7 +51,6 @@ [Guids] gEfiFlashMapHobGuid gEfiHobListGuid - gEfiAlternateFvBlockGuid [Protocols] gEfiSimpleFileSystemProtocolGuid diff --git a/DuetPkg/FvbRuntimeService/FWBlockService.c b/DuetPkg/FvbRuntimeService/FWBlockService.c index f5260a5eaa..664a4cffc6 100644 --- a/DuetPkg/FvbRuntimeService/FWBlockService.c +++ b/DuetPkg/FvbRuntimeService/FWBlockService.c @@ -1632,17 +1632,6 @@ Returns: // ASSERT (FALSE); } - // - // Install FVB Extension Protocol on the same handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &FwbHandle, - &gEfiAlternateFvBlockGuid, - NULL, - NULL - ); - - ASSERT_EFI_ERROR (Status); FwhInstance = (EFI_FW_VOL_INSTANCE *) ( diff --git a/DuetPkg/FvbRuntimeService/FwBlockService.h b/DuetPkg/FvbRuntimeService/FwBlockService.h index eddde81b4a..bec2572a3c 100644 --- a/DuetPkg/FvbRuntimeService/FwBlockService.h +++ b/DuetPkg/FvbRuntimeService/FwBlockService.h @@ -31,7 +31,6 @@ Abstract: #include #include #include -#include #include #include #include @@ -39,7 +38,6 @@ Abstract: #include #include #include -#include // // The Library classes this module consumes diff --git a/MdeModulePkg/Include/Guid/AlternateFvBlock.h b/MdeModulePkg/Include/Guid/AlternateFvBlock.h deleted file mode 100644 index a5e81f0750..0000000000 --- a/MdeModulePkg/Include/Guid/AlternateFvBlock.h +++ /dev/null @@ -1,28 +0,0 @@ -/** @file - - This file defines the Alternate Firmware Volume Block Guid, which is - used to specify that the full funcationality FVB protocol is installed - that support read, write and erase capability for block devices. - -Copyright (c) 2006 - 2008, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __ALT_FVB_GUID_H__ -#define __ALT_FVB_GUID_H__ - -#define EFI_ALTERNATE_FV_BLOCK_GUID \ - { \ - 0xf496922d, 0x172f, 0x4bbc, {0xa1, 0xeb, 0xe, 0xeb, 0x94, 0x9c, 0x34, 0x86 } \ - } - -extern EFI_GUID gEfiAlternateFvBlockGuid; - -#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index b5f86f5b26..ebd59e17c3 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -30,15 +30,15 @@ [LibraryClasses.common] ## @libraryclass IpIo layer upon EFI IP4 Protocol. - # Ihis library is only intended to be used by UEFI network stack modules. + # This library is only intended to be used by UEFI network stack modules. IpIoLib|Include/Library/IpIoLib.h ## @libraryclass Basic function for UEFI network stack. - # Ihis library is only intended to be used by UEFI network stack modules. + # This library is only intended to be used by UEFI network stack modules. NetLib|Include/Library/NetLib.h ## @libraryclass The helper routines to access UDP service. - # Ihis library is only intended to be used by UEFI network stack modules. + # This library is only intended to be used by UEFI network stack modules. UdpIoLib|Include/Library/UdpIoLib.h ## @libraryclass Defines a set of methods to reset whole system. @@ -51,7 +51,7 @@ RecoveryLib|Include/Library/RecoveryLib.h ## @libraryclass Basic platform driver override functions. - # Ihis library is only intended to be used by Platform Driver Override Dxe Driver and Application. + # This library is only intended to be used by Platform Driver Override Dxe Driver and Application. PlatformDriverOverrideLib|Include/Library/PlatformDriverOverrideLib.h ## @libraryclass Provides HII related functions. @@ -101,11 +101,6 @@ ## Include/Guid/SystemNvDataGuid.h gEfiSystemNvDataFvGuid = { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} - ## Alternate Firmware Volume Block Guid specify that the additional - # FVB protocol is installed into FVB handle - ## Include/Guid/AlternateFvBlock.h - gEfiAlternateFvBlockGuid = { 0xF496922D, 0x172F, 0x4BBC, { 0xA1, 0xEB, 0x0E, 0xEB, 0x94, 0x9C, 0x34, 0x86 }} - ## Guid specify the device is the console out device. ## Include/Guid/ConsoleOutDevice.h gEfiConsoleOutDeviceGuid = { 0xD3B36F2C, 0xD551, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} @@ -121,12 +116,11 @@ ## Capsule update hob and variable guid ## Include/Guid/CapsuleVendor.h gEfiCapsuleVendorGuid = { 0x711C703F, 0xC285, 0x4B10, { 0xA3, 0xB0, 0x36, 0xEC, 0xBD, 0x3C, 0x8B, 0xE2 }} - + ## Guid specifiy the device is the StdErr device. ## Include/Guid/StandardErrorDevice.h gEfiStandardErrorDeviceGuid = { 0xD3B36F2D, 0xD551, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }} - ## Guid acted as variable store header's signature and to specify the variable list entries put in the EFI system table. ## Include/Guid/VariableFormat.h gEfiVariableGuid = { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }} diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c index 53352881c4..e0ac6ee17c 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c @@ -53,6 +53,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "FaultTolerantWrite.h" +EFI_EVENT mFvbRegistration = NULL; // // Fault Tolerant Write Protocol API @@ -862,6 +863,308 @@ FtwGetLastWrite ( return Status; } +VOID +EFIAPI +FvbNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_PHYSICAL_ADDRESS FvbBaseAddress; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FVB_ATTRIBUTES_2 Attributes; + EFI_FTW_DEVICE *FtwDevice; + EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry; + UINT32 LbaIndex; + UINTN Length; + EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader; + UINTN Offset; + EFI_HANDLE FvbHandle; + + FtwDevice = (EFI_FTW_DEVICE *)Context; + FvbHandle = NULL; + Fvb = NULL; + + // + // Locate all handles of Fvb protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return; + } + + // + // Get the FVB to access variable store + // + for (Index = 0; Index < HandleCount; Index += 1) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &Fvb + ); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + break; + } + + // + // Ensure this FVB protocol supported Write operation. + // + Status = Fvb->GetAttributes (Fvb, &Attributes); + if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) { + continue; + } + // + // Compare the address and select the right one + // + Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress); + if (EFI_ERROR (Status)) { + continue; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress); + if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) && + ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + FwVolHeader->FvLength)) + ) { + FtwDevice->FtwFvBlock = Fvb; + // + // To get the LBA of work space + // + if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { + // + // Now, one FV has one type of BlockLength + // + FvbMapEntry = &FwVolHeader->BlockMap[0]; + for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { + if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1))) + && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) { + FtwDevice->FtwWorkSpaceLba = LbaIndex - 1; + // + // Get the Work space size and Base(Offset) + // + FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength; + FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1))); + break; + } + } + } + } + + if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) && + ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + FwVolHeader->FvLength)) + ) { + FtwDevice->FtwBackupFvb = Fvb; + // + // To get the LBA of spare + // + if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { + // + // Now, one FV has one type of BlockLength + // + FvbMapEntry = &FwVolHeader->BlockMap[0]; + for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { + if ((FtwDevice->SpareAreaAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1))) + && (FtwDevice->SpareAreaAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) { + // + // Get the NumberOfSpareBlock and BlockSize + // + FtwDevice->FtwSpareLba = LbaIndex - 1; + FtwDevice->BlockSize = FvbMapEntry->Length; + FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize; + // + // Check the range of spare area to make sure that it's in FV range + // + if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > FvbMapEntry->NumBlocks) { + DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n")); + ASSERT (FALSE); + return; + } + break; + } + } + } + } + } + + if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) || + (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) { + return; + } + + DEBUG ((EFI_D_INFO, "Ftw: Working and spare FVB is ready\n")); + // + // Calculate the start LBA of working block. Working block is an area which + // contains working space in its last block and has the same size as spare + // block, unless there are not enough blocks before the block that contains + // working space. + // + FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1; + ASSERT ((INT64) (FtwDevice->FtwWorkBlockLba) >= 0); + + // + // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE. + // + FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1); + FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace; + + FtwDevice->FtwLastWriteHeader = NULL; + FtwDevice->FtwLastWriteRecord = NULL; + + // + // Refresh the working space data from working block + // + Status = WorkSpaceRefresh (FtwDevice); + ASSERT_EFI_ERROR (Status); + // + // If the working block workspace is not valid, try the spare block + // + if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) { + // + // Read from spare block + // + Length = FtwDevice->FtwWorkSpaceSize; + Status = FtwDevice->FtwBackupFvb->Read ( + FtwDevice->FtwBackupFvb, + FtwDevice->FtwSpareLba, + FtwDevice->FtwWorkSpaceBase, + &Length, + FtwDevice->FtwWorkSpace + ); + ASSERT_EFI_ERROR (Status); + + // + // If spare block is valid, then replace working block content. + // + if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) { + Status = FlushSpareBlockToWorkingBlock (FtwDevice); + DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in Init() - %r\n", Status)); + FtwAbort (&FtwDevice->FtwInstance); + // + // Refresh work space. + // + Status = WorkSpaceRefresh (FtwDevice); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n")); + // + // If both are invalid, then initialize work space. + // + SetMem ( + FtwDevice->FtwWorkSpace, + FtwDevice->FtwWorkSpaceSize, + FTW_ERASED_BYTE + ); + InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader); + // + // Initialize the work space + // + Status = FtwReclaimWorkSpace (FtwDevice, FALSE); + ASSERT_EFI_ERROR (Status); + } + } + // + // If the FtwDevice->FtwLastWriteRecord is 1st record of write header && + // (! SpareComplete) THEN call Abort(). + // + if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) && + (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) && + IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord) + ) { + DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n")); + FtwAbort (&FtwDevice->FtwInstance); + } + // + // If Header is incompleted and the last record has completed, then + // call Abort() to set the Header->Complete FLAG. + // + if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) && + (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) && + IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord) + ) { + DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n")); + FtwAbort (&FtwDevice->FtwInstance); + } + // + // To check the workspace buffer following last Write header/records is EMPTY or not. + // If it's not EMPTY, FTW also need to call reclaim(). + // + FtwHeader = FtwDevice->FtwLastWriteHeader; + Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace; + if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) { + Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize); + } + + if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) { + Status = FtwReclaimWorkSpace (FtwDevice, TRUE); + ASSERT_EFI_ERROR (Status); + } + + // + // Restart if it's boot block + // + if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) && + (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE) + ) { + if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) { + Status = FlushSpareBlockToBootBlock (FtwDevice); + DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + FtwAbort (&FtwDevice->FtwInstance); + } else { + // + // if (SpareCompleted) THEN Restart to fault tolerant write. + // + FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb); + if (FvbHandle != NULL) { + Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle); + DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + } + FtwAbort (&FtwDevice->FtwInstance); + } + } + // + // Hook the protocol API + // + FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize; + FtwDevice->FtwInstance.Allocate = FtwAllocate; + FtwDevice->FtwInstance.Write = FtwWrite; + FtwDevice->FtwInstance.Restart = FtwRestart; + FtwDevice->FtwInstance.Abort = FtwAbort; + FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite; + + // + // Install protocol interface + // + Status = gBS->InstallProtocolInterface ( + &FtwDevice->Handle, + &gEfiFaultTolerantWriteProtocolGuid, + EFI_NATIVE_INTERFACE, + &FtwDevice->FtwInstance + ); + + ASSERT_EFI_ERROR (Status); + + // + // Close the notify event to avoid install FaultTolerantWriteProtocol again. + // + Status = gBS->CloseEvent (Event); + ASSERT_EFI_ERROR (Status); + + return; +} + /** This function is the entry point of the Fault Tolerant Write driver. @@ -882,28 +1185,14 @@ InitializeFaultTolerantWrite ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; - UINTN Index; - EFI_HANDLE *HandleBuffer; - UINTN HandleCount; - EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; - EFI_PHYSICAL_ADDRESS BaseAddress; EFI_FTW_DEVICE *FtwDevice; - EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader; - UINTN Length; - EFI_STATUS Status; - UINTN Offset; - EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry; - UINT32 LbaIndex; - EFI_HANDLE FvbHandle; // // Allocate Private data of this driver, // INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE]. // - FvbHandle = NULL; FtwDevice = NULL; - FtwDevice = AllocatePool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize)); + FtwDevice = AllocateZeroPool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize)); if (FtwDevice == NULL) { return EFI_OUT_OF_RESOURCES; } @@ -926,306 +1215,21 @@ InitializeFaultTolerantWrite ( FreePool (FtwDevice); return EFI_OUT_OF_RESOURCES; } - // - // Locate FVB protocol by handle - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiFirmwareVolumeBlockProtocolGuid, - NULL, - &HandleCount, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - FreePool (FtwDevice); - return EFI_NOT_FOUND; - } - - if (HandleCount <= 0) { - FreePool (FtwDevice); - return EFI_NOT_FOUND; - } - - Fvb = NULL; FtwDevice->FtwFvBlock = NULL; FtwDevice->FtwBackupFvb = NULL; FtwDevice->FtwWorkSpaceLba = (EFI_LBA) (-1); FtwDevice->FtwSpareLba = (EFI_LBA) (-1); - for (Index = 0; Index < HandleCount; Index += 1) { - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiFirmwareVolumeBlockProtocolGuid, - (VOID **) &Fvb - ); - if (EFI_ERROR (Status)) { - FreePool (FtwDevice); - return Status; - } - - Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress); - if (EFI_ERROR (Status)) { - continue; - } - - FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress); - - if ((FtwDevice->WorkSpaceAddress >= BaseAddress) && - ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (BaseAddress + FwVolHeader->FvLength)) - ) { - FtwDevice->FtwFvBlock = Fvb; - // - // To get the LBA of work space - // - if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { - // - // Now, one FV has one type of BlockLength - // - FvbMapEntry = &FwVolHeader->BlockMap[0]; - for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { - if ((FtwDevice->WorkSpaceAddress >= (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1))) - && (FtwDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex))) { - FtwDevice->FtwWorkSpaceLba = LbaIndex - 1; - // - // Get the Work space size and Base(Offset) - // - FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength; - FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1))); - break; - } - } - } - } - - if ((FtwDevice->SpareAreaAddress >= BaseAddress) && - ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (BaseAddress + FwVolHeader->FvLength)) - ) { - FtwDevice->FtwBackupFvb = Fvb; - // - // To get the LBA of spare - // - if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { - // - // Now, one FV has one type of BlockLength - // - FvbMapEntry = &FwVolHeader->BlockMap[0]; - for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { - if ((FtwDevice->SpareAreaAddress >= (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1))) - && (FtwDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex))) { - // - // Get the NumberOfSpareBlock and BlockSize - // - FtwDevice->FtwSpareLba = LbaIndex - 1; - FtwDevice->BlockSize = FvbMapEntry->Length; - FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize; - // - // Check the range of spare area to make sure that it's in FV range - // - if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > FvbMapEntry->NumBlocks) { - DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n")); - FreePool (FtwDevice); - return EFI_ABORTED; - } - break; - } - } - } - } - } // - // Calculate the start LBA of working block. Working block is an area which - // contains working space in its last block and has the same size as spare - // block, unless there are not enough blocks before the block that contains - // working space. - // - FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1; - if ((INT64) (FtwDevice->FtwWorkBlockLba) < 0) { - DEBUG ((EFI_D_ERROR, "Ftw: The spare block range is too large than the working block range!\n")); - FreePool (FtwDevice); - return EFI_ABORTED; - } - - if ((FtwDevice->FtwFvBlock == NULL) || - (FtwDevice->FtwBackupFvb == NULL) || - (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || - (FtwDevice->FtwSpareLba == (EFI_LBA) (-1)) - ) { - DEBUG ((EFI_D_ERROR, "Ftw: Working or spare FVB not ready\n")); - FreePool (FtwDevice); - return EFI_ABORTED; - } - // - // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE. - // - FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1); - FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace; - - FtwDevice->FtwLastWriteHeader = NULL; - FtwDevice->FtwLastWriteRecord = NULL; - - // - // Refresh the working space data from working block - // - Status = WorkSpaceRefresh (FtwDevice); - if (EFI_ERROR (Status)) { - goto Recovery; - } - // - // If the working block workspace is not valid, try the spare block - // - if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) { - // - // Read from spare block - // - Length = FtwDevice->FtwWorkSpaceSize; - Status = FtwDevice->FtwBackupFvb->Read ( - FtwDevice->FtwBackupFvb, - FtwDevice->FtwSpareLba, - FtwDevice->FtwWorkSpaceBase, - &Length, - FtwDevice->FtwWorkSpace - ); - if (EFI_ERROR (Status)) { - goto Recovery; - } - // - // If spare block is valid, then replace working block content. - // - if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) { - Status = FlushSpareBlockToWorkingBlock (FtwDevice); - DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in Init() - %r\n", Status)); - FtwAbort (&FtwDevice->FtwInstance); - // - // Refresh work space. - // - Status = WorkSpaceRefresh (FtwDevice); - if (EFI_ERROR (Status)) { - goto Recovery; - } - } else { - DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n")); - // - // If both are invalid, then initialize work space. - // - SetMem ( - FtwDevice->FtwWorkSpace, - FtwDevice->FtwWorkSpaceSize, - FTW_ERASED_BYTE - ); - InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader); - // - // Initialize the work space - // - Status = FtwReclaimWorkSpace (FtwDevice, FALSE); - if (EFI_ERROR (Status)) { - goto Recovery; - } - } - } - - // - // If the FtwDevice->FtwLastWriteRecord is 1st record of write header && - // (! SpareComplete) THEN call Abort(). - // - if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) && - (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) && - IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord) - ) { - DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n")); - FtwAbort (&FtwDevice->FtwInstance); - } - // - // If Header is incompleted and the last record has completed, then - // call Abort() to set the Header->Complete FLAG. - // - if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) && - (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) && - IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord) - ) { - DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n")); - FtwAbort (&FtwDevice->FtwInstance); - } - // - // To check the workspace buffer following last Write header/records is EMPTY or not. - // If it's not EMPTY, FTW also need to call reclaim(). - // - FtwHeader = FtwDevice->FtwLastWriteHeader; - Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace; - if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) { - Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize); - } - - if (!IsErasedFlashBuffer ( - FtwDevice->FtwWorkSpace + Offset, - FtwDevice->FtwWorkSpaceSize - Offset - )) { - Status = FtwReclaimWorkSpace (FtwDevice, TRUE); - if (EFI_ERROR (Status)) { - goto Recovery; - } - } - // - // Restart if it's boot block - // - if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) && - (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE) - ) { - if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) { - Status = FlushSpareBlockToBootBlock (FtwDevice); - DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status)); - if (EFI_ERROR (Status)) { - goto Recovery; - } - - FtwAbort (&FtwDevice->FtwInstance); - } else { - // - // if (SpareCompleted) THEN Restart to fault tolerant write. - // - FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb); - if (FvbHandle != NULL) { - Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle); - DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status)); - if (EFI_ERROR (Status)) { - goto Recovery; - } - } - FtwAbort (&FtwDevice->FtwInstance); - } - } - - // - // Hook the protocol API - // - FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize; - FtwDevice->FtwInstance.Allocate = FtwAllocate; - FtwDevice->FtwInstance.Write = FtwWrite; - FtwDevice->FtwInstance.Restart = FtwRestart; - FtwDevice->FtwInstance.Abort = FtwAbort; - FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite; - - // - // Install protocol interface - // - Status = gBS->InstallProtocolInterface ( - &FtwDevice->Handle, - &gEfiFaultTolerantWriteProtocolGuid, - EFI_NATIVE_INTERFACE, - &FtwDevice->FtwInstance - ); - if (EFI_ERROR (Status)) { - goto Recovery; - } + // Register FvbNotificationEvent () notify function. + // + EfiCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeBlockProtocolGuid, + TPL_CALLBACK, + FvbNotificationEvent, + (VOID *)FtwDevice, + &mFvbRegistration + ); return EFI_SUCCESS; - -Recovery: - - if (FtwDevice != NULL) { - FreePool (FtwDevice); - } - - DEBUG ((EFI_D_ERROR, "Ftw: Severe Error occurs, need to recovery\n")); - - return EFI_VOLUME_CORRUPTED; } diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h index 3cc6572e55..cd0c637936 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h @@ -26,6 +26,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include #include #include #include diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf index cf526e701d..720c591990 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf @@ -44,6 +44,7 @@ BaseMemoryLib UefiDriverEntryPoint DebugLib + UefiLib [Guids] gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header @@ -63,5 +64,5 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize [Depex] - gEfiFirmwareVolumeBlockProtocolGuid AND gEfiAlternateFvBlockGuid ## gEfiAlternateFvBlockGuid specifies FVB protocol with read, write/erase flash access. + gEfiFirmwareVolumeBlockProtocolGuid diff --git a/Nt32Pkg/FvbServicesRuntimeDxe/FWBlockService.c b/Nt32Pkg/FvbServicesRuntimeDxe/FWBlockService.c index 8d1b7e3c28..350672448f 100644 --- a/Nt32Pkg/FvbServicesRuntimeDxe/FWBlockService.c +++ b/Nt32Pkg/FvbServicesRuntimeDxe/FWBlockService.c @@ -29,7 +29,6 @@ Revision History // #include #include -#include #include // // The Library classes this module consumes @@ -1390,15 +1389,6 @@ Returns: ASSERT (FALSE); } - Status = gBS->InstallMultipleProtocolInterfaces ( - &FwbHandle, - &gEfiAlternateFvBlockGuid, - NULL, - NULL - ); - - ASSERT_EFI_ERROR (Status); - FwhInstance = (EFI_FW_VOL_INSTANCE *) ( (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + diff --git a/Nt32Pkg/FvbServicesRuntimeDxe/FvbInfo.c b/Nt32Pkg/FvbServicesRuntimeDxe/FvbInfo.c index e05e205aae..aee8201dfe 100644 --- a/Nt32Pkg/FvbServicesRuntimeDxe/FvbInfo.c +++ b/Nt32Pkg/FvbServicesRuntimeDxe/FvbInfo.c @@ -32,7 +32,6 @@ Abstract: #include #include #include -#include #include // // The Library classes this module consumes diff --git a/Nt32Pkg/FvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf b/Nt32Pkg/FvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf index a36a9a3fc0..2982500841 100644 --- a/Nt32Pkg/FvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf +++ b/Nt32Pkg/FvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf @@ -60,7 +60,6 @@ [Guids] gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED Create Event: EVENT_GROUP_GUID - gEfiAlternateFvBlockGuid # ALWAYS_CONSUME [Protocols] gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_PRODUCED @@ -85,4 +84,4 @@ [depex] TRUE - \ No newline at end of file + diff --git a/UnixPkg/FvbServicesRuntimeDxe/FWBlockService.c b/UnixPkg/FvbServicesRuntimeDxe/FWBlockService.c index f3a2898802..132442b6b9 100644 --- a/UnixPkg/FvbServicesRuntimeDxe/FWBlockService.c +++ b/UnixPkg/FvbServicesRuntimeDxe/FWBlockService.c @@ -22,7 +22,6 @@ Revision History #include "PiDxe.h" #include #include -#include #include #include @@ -1355,15 +1354,6 @@ Returns: ASSERT (FALSE); } - Status = gBS->InstallMultipleProtocolInterfaces ( - &FwbHandle, - &gEfiAlternateFvBlockGuid, - NULL, - NULL - ); - - ASSERT_EFI_ERROR (Status); - FwhInstance = (EFI_FW_VOL_INSTANCE *) ( (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + diff --git a/UnixPkg/FvbServicesRuntimeDxe/FvbInfo.c b/UnixPkg/FvbServicesRuntimeDxe/FvbInfo.c index b7a5a30271..d73f809273 100644 --- a/UnixPkg/FvbServicesRuntimeDxe/FvbInfo.c +++ b/UnixPkg/FvbServicesRuntimeDxe/FvbInfo.c @@ -22,7 +22,6 @@ Abstract: #include "PiDxe.h" #include #include -#include #include #include diff --git a/UnixPkg/FvbServicesRuntimeDxe/UnixFwh.inf b/UnixPkg/FvbServicesRuntimeDxe/UnixFwh.inf index 58aee9a06b..05fc427091 100644 --- a/UnixPkg/FvbServicesRuntimeDxe/UnixFwh.inf +++ b/UnixPkg/FvbServicesRuntimeDxe/UnixFwh.inf @@ -59,8 +59,6 @@ [Guids] gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED Create Event: EVENT_GROUP_GUID - gEfiAlternateFvBlockGuid # ALWAYS_PRODUCED - [Protocols] gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_PRODUCED