| /** @file | |
| Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <PiDxe.h> | |
| #include <Protocol/FirmwareVolumeBlock.h> | |
| #include <Library/PcdLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/BaseLib.h> | |
| #include <Guid/FirmwareFileSystem2.h> | |
| #include <Guid/SystemNvDataGuid.h> | |
| #include <Guid/NvVariableInfoGuid.h> | |
| #include <Library/HobLib.h> | |
| #define FVB_MEDIA_BLOCK_SIZE 0x1000 | |
| typedef struct { | |
| EFI_FIRMWARE_VOLUME_HEADER FvInfo; | |
| EFI_FV_BLOCK_MAP_ENTRY End[1]; | |
| } EFI_FVB2_MEDIA_INFO; | |
| // | |
| // This data structure contains a template of FV header which is used to restore | |
| // Fv header if it's corrupted. | |
| // | |
| EFI_FVB2_MEDIA_INFO mFvbMediaInfo = { | |
| { | |
| { 0, }, // ZeroVector[16] | |
| EFI_SYSTEM_NV_DATA_FV_GUID, | |
| 0, | |
| EFI_FVH_SIGNATURE, | |
| 0x0004feff, // check PiFirmwareVolume.h for details on EFI_FVB_ATTRIBUTES_2 | |
| sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), | |
| 0, // CheckSum which will be calucated dynamically. | |
| 0, // ExtHeaderOffset | |
| { 0, }, | |
| EFI_FVH_REVISION, | |
| { | |
| { | |
| 0, | |
| FVB_MEDIA_BLOCK_SIZE, | |
| } | |
| } | |
| }, | |
| { | |
| { | |
| 0, | |
| 0 | |
| } | |
| } | |
| }; | |
| /** | |
| Initialize the variable store | |
| @retval EFI_SUCCESS if initialize the store success. | |
| **/ | |
| EFI_STATUS | |
| InitVariableStore ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINT32 NvStorageBase; | |
| UINT32 NvStorageSize; | |
| UINT32 NvVariableSize; | |
| UINT32 FtwWorkingSize; | |
| UINT32 FtwSpareSize; | |
| EFI_HOB_GUID_TYPE *GuidHob; | |
| NV_VARIABLE_INFO *NvVariableInfo; | |
| // | |
| // Find SPI flash variable hob | |
| // | |
| GuidHob = GetFirstGuidHob (&gNvVariableInfoGuid); | |
| if (GuidHob == NULL) { | |
| ASSERT (FALSE); | |
| return EFI_NOT_FOUND; | |
| } | |
| NvVariableInfo = (NV_VARIABLE_INFO *)GET_GUID_HOB_DATA (GuidHob); | |
| // | |
| // Get variable region base and size. | |
| // | |
| NvStorageSize = NvVariableInfo->VariableStoreSize; | |
| NvStorageBase = NvVariableInfo->VariableStoreBase; | |
| // | |
| // NvStorageBase needs to be 4KB aligned, NvStorageSize needs to be 8KB * n | |
| // | |
| if (((NvStorageBase & (SIZE_4KB - 1)) != 0) || ((NvStorageSize & (SIZE_8KB - 1)) != 0)) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| FtwSpareSize = NvStorageSize / 2; | |
| FtwWorkingSize = 0x2000; | |
| NvVariableSize = NvStorageSize / 2 - FtwWorkingSize; | |
| DEBUG ((DEBUG_INFO, "NvStorageBase:0x%x, NvStorageSize:0x%x\n", NvStorageBase, NvStorageSize)); | |
| if (NvVariableSize >= 0x80000000) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Status = PcdSet32S (PcdFlashNvStorageVariableSize, NvVariableSize); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = PcdSet32S (PcdFlashNvStorageVariableBase, NvStorageBase); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = PcdSet64S (PcdFlashNvStorageVariableBase64, NvStorageBase); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = PcdSet32S (PcdFlashNvStorageFtwWorkingSize, FtwWorkingSize); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, NvStorageBase + NvVariableSize); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = PcdSet32S (PcdFlashNvStorageFtwSpareSize, FtwSpareSize); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, NvStorageBase + FtwSpareSize); | |
| ASSERT_EFI_ERROR (Status); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Get a heathy FV header used for variable store recovery | |
| @retval The FV header. | |
| **/ | |
| EFI_FIRMWARE_VOLUME_HEADER * | |
| GetFvHeaderTemplate ( | |
| VOID | |
| ) | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER *FvHeader; | |
| UINTN FvSize; | |
| FvSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize) * 2; | |
| FvHeader = &mFvbMediaInfo.FvInfo; | |
| FvHeader->FvLength = FvSize; | |
| FvHeader->BlockMap[0].NumBlocks = (UINT32)(FvSize / FvHeader->BlockMap[0].Length); | |
| FvHeader->Checksum = 0; | |
| FvHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FvHeader, FvHeader->HeaderLength); | |
| return FvHeader; | |
| } |