summaryrefslogtreecommitdiff
path: root/HisiPkg/HiKeyPkg/Drivers
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@linaro.org>2015-08-04 09:53:17 +0800
committerHaojian Zhuang <haojian.zhuang@linaro.org>2015-08-04 10:10:04 +0800
commit2ff62a1ff82359905b3774884bb9a358fc044278 (patch)
treeefaa5e8c6cdfadc7ec2501177279f249d508e691 /HisiPkg/HiKeyPkg/Drivers
parent4984b346feac2c20f67cd823f6cfcf5947fa68d3 (diff)
HiKeyPkg: BlockVariable: fix always init NV area
commit 4f350aedce9c5da5fd682d7775380d02bf959485 Author: Daniel Thompson <daniel.thompson@linaro.org> Date: Mon Jul 27 15:15:19 2015 +0100 HiKeyPkg: BlockVariable: Fix memory leak initializing the variable store Currently Headers is allocated but never used. Removing this allocation resolves FLASH reliability problems during large fastboot downloads (such as the system partition). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org> The commit from Daniel doesn't fix the FLASH reliability issue at all. And this commit doesn't fix FLASH reliability issue also. It's used to refresh the initialization code. And it fixed the issue of NV area (nvme partition) is always inited. Actually it's caused by wrong checking on checksum. Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Diffstat (limited to 'HisiPkg/HiKeyPkg/Drivers')
-rw-r--r--HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c244
1 files changed, 164 insertions, 80 deletions
diff --git a/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c b/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c
index eb82ce3d5..fb4c08252 100644
--- a/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c
+++ b/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c
@@ -226,22 +226,149 @@ STATIC BLOCK_VARIABLE_INSTANCE mBlockVariableInstance = {
};
EFI_STATUS
+ValidateFvHeader (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
+ )
+{
+ UINT16 Checksum, TempChecksum;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FvLength = (UINTN) (PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize));
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
+ {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: No Firmware Volume header present\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ // Verify the header checksum
+ TempChecksum = FwVolHeader->Checksum;
+ FwVolHeader->Checksum = 0;
+ Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != TempChecksum) {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n",Checksum));
+ return EFI_NOT_FOUND;
+ }
+ FwVolHeader->Checksum = Checksum;
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
+
+ // Check the Variable Store Guid
+ if( CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) == FALSE ) {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Guid non-compatible\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Length does not match\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
InitNonVolatileVariableStore (
- IN BLOCK_VARIABLE_INSTANCE *Instance
+ IN BLOCK_VARIABLE_INSTANCE *Instance,
+ IN VOID *Headers,
+ IN UINTN HeadersLength
)
{
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
- UINT8 *NvStorageData;
- UINT32 NvStorageSize;
- UINT32 Count;
- EFI_LBA Lba;
- EFI_DEVICE_PATH_PROTOCOL *NvBlockDevicePath;
- EFI_BLOCK_IO_PROTOCOL *NvStorageBlockIo;
+ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
EFI_STATUS Status;
- UINTN HeadersLength;
- UINTN HeadersBlockLength;
VARIABLE_STORE_HEADER *VariableStoreHeader;
+ // Check if the size of the area is at least one block size
+ ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / Instance->BlockIoProtocol->Media->BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->BlockIoProtocol->Media->BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->BlockIoProtocol->Media->BlockSize > 0));
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength =
+ PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+ FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = PcdGet32 (PcdNvStorageVariableBlockCount);
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockIoProtocol->Media->BlockSize;
+ // BlockMap Terminator
+ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
+ FirmwareVolumeHeader->BlockMap[1].Length = 0;
+ FirmwareVolumeHeader->Checksum = 0;
+ FirmwareVolumeHeader->Checksum = CalculateSum16 ((UINT16*)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
+
+ //
+ // VARIABLE_STORE_HEADER
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FirmwareVolumeHeader + FirmwareVolumeHeader->HeaderLength);
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
+ VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+ return Status;
+}
+
+EFI_STATUS
+BlockVariableDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ BLOCK_VARIABLE_INSTANCE *Instance = &mBlockVariableInstance;
+ UINT32 Count;
+ EFI_LBA Lba;
+ UINTN NvStorageSize;
+ EFI_DEVICE_PATH_PROTOCOL *NvBlockDevicePath;
+ UINT8 *NvStorageData;
+ VOID *Headers;
+ UINTN HeadersLength;
+
+ Instance->Signature = BLOCK_VARIABLE_SIGNATURE;
+
+ HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
+ Headers = AllocateZeroPool(HeadersLength);
+ if (Headers == NULL) {
+ DEBUG ((EFI_D_ERROR, "%a: failed to allocate memory of Headers\n", __func__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
Lba = (EFI_LBA) PcdGet32 (PcdNvStorageVariableBlockLba);
Count = PcdGet32 (PcdNvStorageVariableBlockCount);
Instance->Media.BlockSize = PcdGet32 (PcdNvStorageVariableBlockSize);
@@ -251,7 +378,6 @@ InitNonVolatileVariableStore (
if (NvStorageSize < HeadersLength) {
return EFI_BAD_BUFFER_SIZE;
}
- HeadersBlockLength = (HeadersLength + Instance->Media.BlockSize - 1) / Instance->Media.BlockSize * Instance->Media.BlockSize;
NvStorageData = (UINT8 *) (UINTN) PcdGet32(PcdFlashNvStorageVariableBase);
mMapNvStorageVariableBase = PcdGet32(PcdFlashNvStorageVariableBase);
NvBlockDevicePath = &Instance->DevicePath;
@@ -275,75 +401,6 @@ InitNonVolatileVariableStore (
return EFI_DEVICE_ERROR;
}
WriteBackDataCacheRange (Instance, sizeof(BLOCK_VARIABLE_INSTANCE));
- NvStorageBlockIo = Instance->BlockIoProtocol;
- Status = NvStorageBlockIo->ReadBlocks (NvStorageBlockIo, NvStorageBlockIo->Media->MediaId, Lba, HeadersBlockLength, (VOID *)NvStorageData);
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) NvStorageData;
- if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
- // Check if the size of the area is at least one block size
- ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / NvStorageBlockIo->Media->BlockSize > 0));
- ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / NvStorageBlockIo->Media->BlockSize > 0));
- ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / NvStorageBlockIo->Media->BlockSize > 0));
-
- //
- // EFI_FIRMWARE_VOLUME_HEADER
- //
- CopyGuid (&FvHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
- FvHeader->FvLength =
- PcdGet32(PcdFlashNvStorageVariableSize) +
- PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
- PcdGet32(PcdFlashNvStorageFtwSpareSize);
- FvHeader->Signature = EFI_FVH_SIGNATURE;
- FvHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
- EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
- EFI_FVB2_READ_STATUS | // Reads are currently enabled
- EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
- EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
- EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
- EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
- EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
- );
- FvHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
- FvHeader->Revision = EFI_FVH_REVISION;
- FvHeader->BlockMap[0].NumBlocks = Count;
- FvHeader->BlockMap[0].Length = NvStorageBlockIo->Media->BlockSize;
- // BlockMap Terminator
- FvHeader->BlockMap[1].NumBlocks = 0;
- FvHeader->BlockMap[1].Length = 0;
- FvHeader->Checksum = CalculateCheckSum16 ((UINT16*)FvHeader,FvHeader->HeaderLength);
-
- //
- // VARIABLE_STORE_HEADER
- //
- VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FvHeader + FvHeader->HeaderLength);
- CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
- VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FvHeader->HeaderLength;
- VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
- VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
-
- Status = NvStorageBlockIo->WriteBlocks (NvStorageBlockIo, NvStorageBlockIo->Media->MediaId, Lba, HeadersBlockLength, (VOID *)NvStorageData);
- }
- return Status;
-}
-
-EFI_STATUS
-BlockVariableDxeInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_HANDLE Handle;
- EFI_STATUS Status;
- BLOCK_VARIABLE_INSTANCE *Instance = &mBlockVariableInstance;
-
- Instance->Signature = BLOCK_VARIABLE_SIGNATURE;
- Status = InitNonVolatileVariableStore (Instance);
- if (EFI_ERROR (Status)) {
- goto exit;
- }
Handle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
@@ -355,6 +412,33 @@ BlockVariableDxeInitialize (
goto exit;
}
+ Status = FvbRead (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ValidateFvHeader (Headers);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "%a, Found invalid Fv Header\n", __func__));
+
+ // Erase all the block device that is reserved for variable storage
+ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, Count, EFI_LBA_LIST_TERMINATOR);
+ if (EFI_ERROR (Status)) {
+ goto exit;
+ }
+
+ Status = InitNonVolatileVariableStore (Instance, Headers, HeadersLength);
+ if (EFI_ERROR (Status)) {
+ goto exit;
+ }
+ }
+
+ if (NvStorageSize > ((EFI_FIRMWARE_VOLUME_HEADER*)Headers)->FvLength) {
+ NvStorageSize = ((EFI_FIRMWARE_VOLUME_HEADER*)Headers)->FvLength;
+ NvStorageSize = ((NvStorageSize + Instance->Media.BlockSize - 1) / Instance->Media.BlockSize) * Instance->Media.BlockSize;
+ }
+ Status = FvbRead (&Instance->FvbProtocol, 0, 0, &NvStorageSize, NvStorageData);
+
exit:
return Status;
}