Initialize a local work space header to be used by IsValidWorkSpace() and InitWorkSpaceHeader() to avoid executing code(gBS->CalculateCrc32 ()) outside SMRAM while inside SMM.

Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14012 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lzeng14 2012-12-21 00:52:57 +00:00
parent 83d06ed90f
commit 05cfd5f286
3 changed files with 79 additions and 90 deletions

View File

@ -3,7 +3,7 @@
The internal header file includes the common header files, defines The internal header file includes the common header files, defines
internal structure and functions used by FtwLite module. internal structure and functions used by FtwLite module.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <PiDxe.h> #include <PiDxe.h>
#include <Guid/SystemNvDataGuid.h> #include <Guid/SystemNvDataGuid.h>
#include <Guid/ZeroGuid.h>
#include <Protocol/FaultTolerantWrite.h> #include <Protocol/FaultTolerantWrite.h>
#include <Protocol/FirmwareVolumeBlock.h> #include <Protocol/FirmwareVolumeBlock.h>
#include <Protocol/SwapAddressRange.h> #include <Protocol/SwapAddressRange.h>
@ -736,5 +737,16 @@ EFI_STATUS
InitFtwProtocol ( InitFtwProtocol (
IN OUT EFI_FTW_DEVICE *FtwDevice IN OUT EFI_FTW_DEVICE *FtwDevice
); );
/**
Initialize a local work space header.
Since Signature and WriteQueueSize have been known, Crc can be calculated out,
then the work space header will be fixed.
**/
VOID
InitializeLocalWorkSpaceHeader (
VOID
);
#endif #endif

View File

@ -1174,6 +1174,8 @@ InitFtwProtocol (
FtwDevice->FtwLastWriteHeader = NULL; FtwDevice->FtwLastWriteHeader = NULL;
FtwDevice->FtwLastWriteRecord = NULL; FtwDevice->FtwLastWriteRecord = NULL;
InitializeLocalWorkSpaceHeader ();
// //
// Refresh the working space data from working block // Refresh the working space data from working block
// //

View File

@ -16,6 +16,65 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "FaultTolerantWrite.h" #include "FaultTolerantWrite.h"
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER mWorkingBlockHeader = {ZERO_GUID, 0, 0, 0, 0, {0, 0, 0}, 0};
/**
Initialize a local work space header.
Since Signature and WriteQueueSize have been known, Crc can be calculated out,
then the work space header will be fixed.
**/
VOID
InitializeLocalWorkSpaceHeader (
VOID
)
{
EFI_STATUS Status;
//
// Check signature with gEfiSystemNvDataFvGuid.
//
if (CompareGuid (&gEfiSystemNvDataFvGuid, &mWorkingBlockHeader.Signature)) {
//
// The local work space header has been initialized.
//
return;
}
SetMem (
&mWorkingBlockHeader,
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
FTW_ERASED_BYTE
);
//
// Here using gEfiSystemNvDataFvGuid as the signature.
//
CopyMem (
&mWorkingBlockHeader.Signature,
&gEfiSystemNvDataFvGuid,
sizeof (EFI_GUID)
);
mWorkingBlockHeader.WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
//
// Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.
//
//
// Calculate the Crc of woking block header
//
Status = gBS->CalculateCrc32 (
&mWorkingBlockHeader,
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
&mWorkingBlockHeader.Crc
);
ASSERT_EFI_ERROR (Status);
mWorkingBlockHeader.WorkingBlockValid = FTW_VALID_STATE;
mWorkingBlockHeader.WorkingBlockInvalid = FTW_INVALID_STATE;
}
/** /**
Check to see if it is a valid work space. Check to see if it is a valid work space.
@ -31,62 +90,16 @@ IsValidWorkSpace (
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
) )
{ {
EFI_STATUS Status;
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER WorkingBlockHeader;
if (WorkingHeader == NULL) { if (WorkingHeader == NULL) {
return FALSE; return FALSE;
} }
if (WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) { if (CompareMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) == 0) {
DEBUG ((EFI_D_ERROR, "Ftw: Work block header valid bit check error\n")); return TRUE;
return FALSE;
}
//
// Check signature with gEfiSystemNvDataFvGuid
//
if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) {
DEBUG ((EFI_D_ERROR, "Ftw: Work block header signature check error\n"));
return FALSE;
}
//
// Check the CRC of header
//
CopyMem (
&WorkingBlockHeader,
WorkingHeader,
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
);
//
// Filter out the Crc and State fields
//
SetMem (
&WorkingBlockHeader.Crc,
sizeof (UINT32),
FTW_ERASED_BYTE
);
WorkingBlockHeader.WorkingBlockValid = FTW_ERASE_POLARITY;
WorkingBlockHeader.WorkingBlockInvalid = FTW_ERASE_POLARITY;
//
// Calculate the Crc of woking block header
//
Status = gBS->CalculateCrc32 (
(UINT8 *) &WorkingBlockHeader,
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
&WorkingBlockHeader.Crc
);
if (EFI_ERROR (Status)) {
return FALSE;
} }
if (WorkingBlockHeader.Crc != WorkingHeader->Crc) { DEBUG ((EFI_D_ERROR, "Ftw: Work block header check error\n"));
DEBUG ((EFI_D_ERROR, "Ftw: Work block header CRC check error\n")); return FALSE;
return FALSE;
}
return TRUE;
} }
/** /**
@ -103,49 +116,11 @@ InitWorkSpaceHeader (
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
) )
{ {
EFI_STATUS Status;
if (WorkingHeader == NULL) { if (WorkingHeader == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
//
// Here using gEfiSystemNvDataFvGuid as the signature.
//
CopyMem (
&WorkingHeader->Signature,
&gEfiSystemNvDataFvGuid,
sizeof (EFI_GUID)
);
WorkingHeader->WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
// CopyMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
// Crc is calculated with all the fields except Crc and STATE
//
WorkingHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
WorkingHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
SetMem (
&WorkingHeader->Crc,
sizeof (UINT32),
FTW_ERASED_BYTE
);
//
// Calculate the CRC value
//
Status = gBS->CalculateCrc32 (
(UINT8 *) WorkingHeader,
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
&WorkingHeader->Crc
);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
//
// Restore the WorkingBlockValid flag to VALID state
//
WorkingHeader->WorkingBlockValid = FTW_VALID_STATE;
WorkingHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
return EFI_SUCCESS; return EFI_SUCCESS;
} }