From 6f8ffb644334d2f42abd5d17e13e7ab3d214dbd5 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 7 Apr 2015 16:06:11 +0800 Subject: [PATCH 1/2] BlockVariable: remove hacking shadow buffer Avoid hacking shadow buffer as temporary buffer. Use allocated buffer instead since the shadow buffer isn't reserved first. Signed-off-by: Haojian Zhuang --- .../BlockVariableDxe/BlockVariableDxe.c | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c b/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c index 617d792a755c..f16270040a03 100644 --- a/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c +++ b/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c @@ -111,19 +111,29 @@ FvbRead ( EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_STATUS Status; UINTN Bytes; + VOID *DataPtr; Instance = CR (This, BLOCK_VARIABLE_INSTANCE, FvbProtocol, BLOCK_VARIABLE_SIGNATURE); BlockIo = Instance->BlockIoProtocol; Bytes = (Offset + *NumBytes + Instance->Media.BlockSize - 1) / Instance->Media.BlockSize * Instance->Media.BlockSize; + DataPtr = AllocateZeroPool (Bytes); + if (DataPtr == NULL) { + DEBUG ((EFI_D_ERROR, "FvbWrite: failed to allocate buffer.\n")); + return EFI_BUFFER_TOO_SMALL; + } + WriteBackDataCacheRange (DataPtr, Bytes); + InvalidateDataCacheRange (Buffer, *NumBytes); Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, - Bytes, Instance->ShadowBuffer); + Bytes, DataPtr); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "FvbRead StartLba:%x, Lba:%x, Offset:%x, Status:%x\n", Instance->StartLba, Lba, Offset, Status)); - return Status; + goto exit; } - CopyMem (Buffer, Instance->ShadowBuffer + Offset, *NumBytes); + CopyMem (Buffer, DataPtr + Offset, *NumBytes); WriteBackDataCacheRange (Buffer, *NumBytes); +exit: + FreePool (DataPtr); return Status; } @@ -141,29 +151,33 @@ FvbWrite ( EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_STATUS Status; UINTN Bytes; + VOID *DataPtr; Instance = CR (This, BLOCK_VARIABLE_INSTANCE, FvbProtocol, BLOCK_VARIABLE_SIGNATURE); BlockIo = Instance->BlockIoProtocol; Bytes = (Offset + *NumBytes + Instance->Media.BlockSize - 1) / Instance->Media.BlockSize * Instance->Media.BlockSize; - if (*NumBytes < Bytes) { - Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, - Bytes, Instance->ShadowBuffer); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "FvbWrite: failed on reading blocks.\n")); - return Status; - } - CopyMem (Instance->ShadowBuffer + Offset, Buffer, *NumBytes); - WriteBackDataCacheRange (Instance->ShadowBuffer, Bytes); - Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, - Bytes, Instance->ShadowBuffer); - } else { - Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, - Bytes, Buffer); + DataPtr = AllocateZeroPool (Bytes); + if (DataPtr == NULL) { + DEBUG ((EFI_D_ERROR, "FvbWrite: failed to allocate buffer.\n")); + return EFI_BUFFER_TOO_SMALL; } + WriteBackDataCacheRange (DataPtr, Bytes); + Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, + Bytes, DataPtr); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FvbWrite: failed on reading blocks.\n")); + goto exit; + } + CopyMem (DataPtr + Offset, Buffer, *NumBytes); + WriteBackDataCacheRange (DataPtr, Bytes); + Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, + Bytes, DataPtr); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "FvbWrite StartLba:%x, Lba:%x, Offset:%x, Status:%x\n", Instance->StartLba, Lba, Offset, Status)); } +exit: + FreePool (DataPtr); return Status; } @@ -231,7 +245,6 @@ InitNonVolatileVariableStore ( NvStorageData = (UINT8 *) (UINTN) PcdGet32(PcdFlashNvStorageVariableBase); mMapNvStorageVariableBase = PcdGet32(PcdFlashNvStorageVariableBase); NvBlockDevicePath = &Instance->DevicePath; - Instance->ShadowBuffer = (VOID *)(NvStorageData + 0x800000); NvBlockDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdNvStorageVariableBlockDevicePath)); Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &NvBlockDevicePath, &Instance->Handle); From cbf165c5c5f1a890d9e5fe7e1272580b7fdadf66 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 7 Apr 2015 16:10:23 +0800 Subject: [PATCH 2/2] BlockVariable: flush variable twice If it's the last flush operation, variable may not be flushed into the block device. So flush it twice. It could make sure that everything is flushed into block device. Signed-off-by: Haojian Zhuang --- .../HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c b/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c index f16270040a03..360900199ea1 100644 --- a/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c +++ b/HisiPkg/HiKeyPkg/Drivers/BlockVariableDxe/BlockVariableDxe.c @@ -176,6 +176,14 @@ FvbWrite ( DEBUG ((EFI_D_ERROR, "FvbWrite StartLba:%x, Lba:%x, Offset:%x, Status:%x\n", Instance->StartLba, Lba, Offset, Status)); } + // Sometimes the variable isn't flushed into block device if it's the last flush operation. + // So flush it again. + Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, + Bytes, DataPtr); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FvbWrite StartLba:%x, Lba:%x, Offset:%x, Status:%x\n", + Instance->StartLba, Lba, Offset, Status)); + } exit: FreePool (DataPtr); return Status;