/** @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; | |
} |