+ NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);\r
+ NvStorageBase = (EFI_PHYSICAL_ADDRESS) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?\r
+ PcdGet64 (PcdFlashNvStorageVariableBase64) :\r
+ PcdGet32 (PcdFlashNvStorageVariableBase)\r
+ );\r
+ //\r
+ // First let FvHeader point to NV storage base.\r
+ //\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) NvStorageBase;\r
+\r
+ //\r
+ // Check the FTW last write data hob.\r
+ //\r
+ BackUpOffset = 0;\r
+ GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);\r
+ if (GuidHob != NULL) {\r
+ FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);\r
+ if (FtwLastWriteData->TargetAddress == NvStorageBase) {\r
+ //\r
+ // Let FvHeader point to spare block.\r
+ //\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FtwLastWriteData->SpareAddress;\r
+ DEBUG ((EFI_D_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));\r
+ } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {\r
+ StoreInfo->FtwLastWriteData = FtwLastWriteData;\r
+ //\r
+ // Flash NV storage from the offset is backed up in spare block.\r
+ //\r
+ BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);\r
+ DEBUG ((EFI_D_INFO, "PeiVariable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));\r
+ //\r
+ // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.\r
+ //\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check if the Firmware Volume is not corrupted\r
+ //\r
+ if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {\r
+ DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));\r
+ break;\r
+ }\r
+\r
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);\r
+\r
+ StoreInfo->AuthFlag = (BOOLEAN) (CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid));\r
+\r
+ GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);\r
+ if (GuidHob != NULL) {\r
+ StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);\r
+ } else {\r
+ //\r
+ // If it's the first time to access variable region in flash, create a guid hob to record\r
+ // VAR_ADDED type variable info.\r
+ // Note that as the resource of PEI phase is limited, only store the limited number of\r
+ // VAR_ADDED type variables to reduce access time.\r
+ //\r
+ StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE *) BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));\r
+ StoreInfo->IndexTable->Length = 0;\r
+ StoreInfo->IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);\r
+ StoreInfo->IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);\r
+ StoreInfo->IndexTable->GoneThrough = 0;\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ StoreInfo->VariableStoreHeader = VariableStoreHeader;\r
+ return VariableStoreHeader;\r
+}\r
+\r
+/**\r
+ Get variable header that has consecutive content.\r
+\r
+ @param StoreInfo Pointer to variable store info structure.\r
+ @param Variable Pointer to the Variable Header.\r
+ @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.\r
+\r
+ @retval TRUE Variable header is valid.\r
+ @retval FALSE Variable header is not valid.\r
+\r
+**/\r
+BOOLEAN\r
+GetVariableHeader (\r
+ IN VARIABLE_STORE_INFO *StoreInfo,\r
+ IN VARIABLE_HEADER *Variable,\r
+ OUT VARIABLE_HEADER **VariableHeader\r
+ )\r