From c23f114d3cfbb29b8734b87213d1ec0de404197b Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 27 Apr 2017 11:05:07 +0800 Subject: MdeModulePkg: Move to new location Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../FaultTolerantWritePei/FaultTolerantWritePei.c | 321 +++++++++++++++++++++ .../FaultTolerantWritePei.inf | 67 +++++ .../FaultTolerantWritePei.uni | 21 ++ .../FaultTolerantWritePeiExtra.uni | 19 ++ 4 files changed, 428 insertions(+) create mode 100644 Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c create mode 100644 Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf create mode 100644 Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.uni create mode 100644 Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePeiExtra.uni (limited to 'Core/MdeModulePkg/Universal/FaultTolerantWritePei') diff --git a/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c new file mode 100644 index 0000000000..14e18e5ae2 --- /dev/null +++ b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c @@ -0,0 +1,321 @@ +/** @file + This driver installs gEdkiiFaultTolerantWriteGuid PPI to inform + the check for FTW last write data has been done. + +Copyright (c) 2013, 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. + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEdkiiFaultTolerantWriteGuid, + NULL +}; + +/** + Get the last Write Header pointer. + The last write header is the header whose 'complete' state hasn't been set. + After all, this header may be a EMPTY header entry for next Allocate. + + + @param FtwWorkSpaceHeader Pointer of the working block header + @param FtwWorkSpaceSize Size of the work space + @param FtwWriteHeader Pointer to retrieve the last write header + + @retval EFI_SUCCESS Get the last write record successfully + @retval EFI_ABORTED The FTW work space is damaged + +**/ +EFI_STATUS +FtwGetLastWriteHeader ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader, + IN UINTN FtwWorkSpaceSize, + OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader + ) +{ + UINTN Offset; + EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader; + + *FtwWriteHeader = NULL; + FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) (FtwWorkSpaceHeader + 1); + Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER); + + while (FtwHeader->Complete == FTW_VALID_STATE) { + Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize); + // + // If Offset exceed the FTW work space boudary, return error. + // + if (Offset >= FtwWorkSpaceSize) { + *FtwWriteHeader = FtwHeader; + return EFI_ABORTED; + } + + FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) ((UINT8 *) FtwWorkSpaceHeader + Offset); + } + // + // Last write header is found + // + *FtwWriteHeader = FtwHeader; + + return EFI_SUCCESS; +} + +/** + Get the last Write Record pointer. The last write Record is the Record + whose DestinationCompleted state hasn't been set. After all, this Record + may be a EMPTY record entry for next write. + + + @param FtwWriteHeader Pointer to the write record header + @param FtwWriteRecord Pointer to retrieve the last write record + + @retval EFI_SUCCESS Get the last write record successfully + @retval EFI_ABORTED The FTW work space is damaged + +**/ +EFI_STATUS +FtwGetLastWriteRecord ( + IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader, + OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwWriteRecord + ) +{ + UINTN Index; + EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord; + + *FtwWriteRecord = NULL; + FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) (FtwWriteHeader + 1); + + // + // Try to find the last write record "that has not completed" + // + for (Index = 0; Index < FtwWriteHeader->NumberOfWrites; Index += 1) { + if (FtwRecord->DestinationComplete != FTW_VALID_STATE) { + // + // The last write record is found + // + *FtwWriteRecord = FtwRecord; + return EFI_SUCCESS; + } + + FtwRecord++; + + if (FtwWriteHeader->PrivateDataSize != 0) { + FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + (UINTN) FtwWriteHeader->PrivateDataSize); + } + } + // + // if Index == NumberOfWrites, then + // the last record has been written successfully, + // but the Header->Complete Flag has not been set. + // also return the last record. + // + if (Index == FtwWriteHeader->NumberOfWrites) { + *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize)); + return EFI_SUCCESS; + } + + return EFI_ABORTED; +} + +/** + Check to see if it is a valid work space. + + + @param WorkingHeader Pointer of working block header + @param WorkingLength Working block length + + @retval TRUE The work space is valid. + @retval FALSE The work space is invalid. + +**/ +BOOLEAN +IsValidWorkSpace ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader, + IN UINTN WorkingLength + ) +{ + UINT8 Data; + + if (WorkingHeader == NULL) { + return FALSE; + } + + if ((WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) || (WorkingHeader->WorkingBlockInvalid == FTW_VALID_STATE)) { + DEBUG ((EFI_D_ERROR, "FtwPei: Work block header valid bit check error\n")); + return FALSE; + } + + if (WorkingHeader->WriteQueueSize != (WorkingLength - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER))) { + DEBUG ((EFI_D_ERROR, "FtwPei: Work block header WriteQueueSize check error\n")); + return FALSE; + } + + // + // Check signature with gEdkiiWorkingBlockSignatureGuid + // + if (!CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &WorkingHeader->Signature)) { + DEBUG ((EFI_D_ERROR, "FtwPei: Work block header signature check error, it should be gEdkiiWorkingBlockSignatureGuid\n")); + // + // To be compatible with old signature gEfiSystemNvDataFvGuid. + // + if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) { + return FALSE; + } else { + Data = *(UINT8 *) (WorkingHeader + 1); + if (Data != 0xff) { + DEBUG ((EFI_D_ERROR, "FtwPei: Old format FTW structure can't be handled\n")); + ASSERT (FALSE); + return FALSE; + } + } + } + + return TRUE; + +} + +/** + Main entry for Fault Tolerant Write PEIM. + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Pointer to PEI Services table. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() + +**/ +EFI_STATUS +EFIAPI +PeimFaultTolerantWriteInitialize ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkingBlockHeader; + EFI_FAULT_TOLERANT_WRITE_HEADER *FtwLastWriteHeader; + EFI_FAULT_TOLERANT_WRITE_RECORD *FtwLastWriteRecord; + EFI_PHYSICAL_ADDRESS WorkSpaceAddress; + UINTN WorkSpaceLength; + EFI_PHYSICAL_ADDRESS SpareAreaAddress; + UINTN SpareAreaLength; + EFI_PHYSICAL_ADDRESS WorkSpaceInSpareArea; + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA FtwLastWrite; + + FtwWorkingBlockHeader = NULL; + FtwLastWriteHeader = NULL; + FtwLastWriteRecord = NULL; + + WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64); + if (WorkSpaceAddress == 0) { + WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase); + } + WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize); + + SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64); + if (SpareAreaAddress == 0) { + SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase); + } + SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize); + + // + // The address of FTW working base and spare base must not be 0. + // + ASSERT ((WorkSpaceAddress != 0) && (SpareAreaAddress != 0)); + + FtwWorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (UINTN) WorkSpaceAddress; + if (IsValidWorkSpace (FtwWorkingBlockHeader, WorkSpaceLength)) { + Status = FtwGetLastWriteHeader ( + FtwWorkingBlockHeader, + WorkSpaceLength, + &FtwLastWriteHeader + ); + if (!EFI_ERROR (Status)) { + Status = FtwGetLastWriteRecord ( + FtwLastWriteHeader, + &FtwLastWriteRecord + ); + } + + if (!EFI_ERROR (Status)) { + ASSERT (FtwLastWriteRecord != NULL); + if ((FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE) && (FtwLastWriteRecord->DestinationComplete != FTW_VALID_STATE)) { + // + // If FTW last write was still in progress with SpareComplete set and DestinationComplete not set. + // It means the target buffer has been backed up in spare block, then target block has been erased, + // but the target buffer has not been writen in target block from spare block, we need to build + // FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob to hold the FTW last write data. + // + FtwLastWrite.TargetAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) ((INT64) SpareAreaAddress + FtwLastWriteRecord->RelativeOffset); + FtwLastWrite.SpareAddress = SpareAreaAddress; + FtwLastWrite.Length = SpareAreaLength; + DEBUG (( + EFI_D_INFO, + "FtwPei last write data: TargetAddress - 0x%x SpareAddress - 0x%x Length - 0x%x\n", + (UINTN) FtwLastWrite.TargetAddress, + (UINTN) FtwLastWrite.SpareAddress, + (UINTN) FtwLastWrite.Length)); + BuildGuidDataHob (&gEdkiiFaultTolerantWriteGuid, (VOID *) &FtwLastWrite, sizeof (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA)); + } + } + } else { + FtwWorkingBlockHeader = NULL; + // + // If the working block workspace is not valid, try to find workspace in the spare block. + // + WorkSpaceInSpareArea = SpareAreaAddress + SpareAreaLength - WorkSpaceLength; + while (WorkSpaceInSpareArea >= SpareAreaAddress) { + if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, (EFI_GUID *) (UINTN) WorkSpaceInSpareArea)) { + // + // Found the workspace. + // + DEBUG ((EFI_D_INFO, "FtwPei: workspace in spare block is at 0x%x.\n", (UINTN) WorkSpaceInSpareArea)); + FtwWorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (UINTN) WorkSpaceInSpareArea; + break; + } + WorkSpaceInSpareArea = WorkSpaceInSpareArea - sizeof (EFI_GUID); + } + if ((FtwWorkingBlockHeader != NULL) && IsValidWorkSpace (FtwWorkingBlockHeader, WorkSpaceLength)) { + // + // It was workspace self reclaim, build FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob for it. + // + FtwLastWrite.TargetAddress = WorkSpaceAddress - (WorkSpaceInSpareArea - SpareAreaAddress); + FtwLastWrite.SpareAddress = SpareAreaAddress; + FtwLastWrite.Length = SpareAreaLength; + DEBUG (( + EFI_D_INFO, + "FtwPei last write data: TargetAddress - 0x%x SpareAddress - 0x%x Length - 0x%x\n", + (UINTN) FtwLastWrite.TargetAddress, + (UINTN) FtwLastWrite.SpareAddress, + (UINTN) FtwLastWrite.Length)); + BuildGuidDataHob (&gEdkiiFaultTolerantWriteGuid, (VOID *) &FtwLastWrite, sizeof (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA)); + } else { + // + // Both are invalid. + // + DEBUG ((EFI_D_ERROR, "FtwPei: Both working and spare block are invalid.\n")); + } + } + + // + // Install gEdkiiFaultTolerantWriteGuid PPI to inform the check for FTW last write data has been done. + // + return PeiServicesInstallPpi (&mPpiListVariable); +} diff --git a/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf new file mode 100644 index 0000000000..12b26604e2 --- /dev/null +++ b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf @@ -0,0 +1,67 @@ +## @file +# Fault Tolerant Write PEI Driver. +# +# This module installs gEdkiiFaultTolerantWriteGuid PPI to inform the check for FTW last write data has been done. +# +# Copyright (c) 2013 - 2014, 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FaultTolerantWritePei + MODULE_UNI_FILE = FaultTolerantWritePei.uni + FILE_GUID = AAC33064-9ED0-4b89-A5AD-3EA767960B22 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = PeimFaultTolerantWriteInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + FaultTolerantWritePei.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PeimEntryPoint + PeiServicesLib + BaseLib + DebugLib + HobLib + BaseMemoryLib + PcdLib + +[Guids] + ## SOMETIMES_PRODUCES ## HOB + ## PRODUCES ## GUID # Install ppi + gEdkiiFaultTolerantWriteGuid + gEdkiiWorkingBlockSignatureGuid ## SOMETIMES_CONSUMES ## GUID + gEfiSystemNvDataFvGuid ## SOMETIMES_CONSUMES ## GUID + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES + +[Depex] + TRUE + +[UserExtensions.TianoCore."ExtraFiles"] + FaultTolerantWritePeiExtra.uni diff --git a/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.uni b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.uni new file mode 100644 index 0000000000..49dcc7b2bc --- /dev/null +++ b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.uni @@ -0,0 +1,21 @@ +// /** @file +// Fault Tolerant Write PEI Driver. +// +// This module installs gEdkiiFaultTolerantWriteGuid PPI to inform the check for FTW last write data has been done. +// +// Copyright (c) 2013 - 2014, 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. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "This module installs gEdkiiFaultTolerantWriteGuid PPI to inform the check for FTW last write data has been done." + +#string STR_MODULE_DESCRIPTION #language en-US "This module installs gEdkiiFaultTolerantWriteGuid PPI to inform the check for FTW last write data has been done." + diff --git a/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePeiExtra.uni b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePeiExtra.uni new file mode 100644 index 0000000000..b9fd9425a9 --- /dev/null +++ b/Core/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePeiExtra.uni @@ -0,0 +1,19 @@ +// /** @file +// FaultTolerantWritePei Localized Strings and Content +// +// Copyright (c) 2014, 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. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"FaultTolerantWrite PEI Module" + + -- cgit v1.2.3