X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=SecurityPkg%2FTcg%2FMemoryOverwriteControl%2FTcgMor.c;h=c16761bb3dd99cc71d807f4af625b2490352da3b;hp=ce53112dc57070f11c3bc949a145713d551a1863;hb=b3548d32ddb553a9e95503457c66d11462622d16;hpb=0c18794ea4289f03fefc7117b56740414cc0536c
diff --git a/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c
index ce53112dc5..c16761bb3d 100644
--- a/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c
+++ b/SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.c
@@ -1,29 +1,310 @@
/** @file
TCG MOR (Memory Overwrite Request) Control Driver.
- This driver initilize MemoryOverwriteRequestControl variable. It
- will clear MOR_CLEAR_MEMORY_BIT bit if it is set.
+ This driver initilize MemoryOverwriteRequestControl variable. It
+ will clear MOR_CLEAR_MEMORY_BIT bit if it is set. It will also do TPer Reset for
+ those encrypted drives through EFI_STORAGE_SECURITY_COMMAND_PROTOCOL at EndOfDxe.
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
-This program and the accompanying materials
-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
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+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
http://opensource.org/licenses/bsd-license.php
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "TcgMor.h"
+UINT8 mMorControl;
+
+/**
+ Ready to Boot Event notification handler.
+
+ @param[in] Event Event whose notification function is being invoked
+ @param[in] Context Pointer to the notification function's context
+
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+
+ if (MOR_CLEAR_MEMORY_VALUE (mMorControl) == 0x0) {
+ //
+ // MorControl is expected, directly return to avoid unnecessary variable operation
+ //
+ return ;
+ }
+ //
+ // Clear MOR_CLEAR_MEMORY_BIT
+ //
+ DEBUG ((EFI_D_INFO, "TcgMor: Clear MorClearMemory bit\n"));
+ mMorControl &= 0xFE;
+
+ DataSize = sizeof (mMorControl);
+ Status = gRT->SetVariable (
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ &gEfiMemoryOverwriteControlDataGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ &mMorControl
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "TcgMor: Clear MOR_CLEAR_MEMORY_BIT failure, Status = %r\n"));
+ }
+}
+
+/**
+ Send TPer Reset command to reset eDrive to lock all protected bands.
+ Typically, there are 2 mechanism for resetting eDrive. They are:
+ 1. TPer Reset through IEEE 1667 protocol.
+ 2. TPer Reset through native TCG protocol.
+ This routine will detect what protocol the attached eDrive comform to, TCG or
+ IEEE 1667 protocol. Then send out TPer Reset command separately.
+
+ @param[in] Ssp The pointer to EFI_STORAGE_SECURITY_COMMAND_PROTOCOL instance.
+ @param[in] MediaId ID of the medium to receive data from or send data to.
+
+**/
+VOID
+InitiateTPerReset (
+ IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp,
+ IN UINT32 MediaId
+ )
+{
+
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+ UINTN XferSize;
+ UINTN Len;
+ UINTN Index;
+ BOOLEAN TcgFlag;
+ BOOLEAN IeeeFlag;
+ SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *Data;
+
+ Buffer = NULL;
+ TcgFlag = FALSE;
+ IeeeFlag = FALSE;
+
+ //
+ // ATA8-ACS 7.57.6.1 indicates the Transfer Length field requirements a multiple of 512.
+ // If the length of the TRUSTED RECEIVE parameter data is greater than the Transfer Length,
+ // then the device shall return the TRUSTED RECEIVE parameter data truncated to the requested Transfer Length.
+ //
+ Len = ROUNDUP512(sizeof(SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA));
+ Buffer = AllocateZeroPool(Len);
+
+ if (Buffer == NULL) {
+ return;
+ }
+
+ //
+ // When the Security Protocol field is set to 00h, and SP Specific is set to 0000h in a TRUSTED RECEIVE
+ // command, the device basic information data shall be returned.
+ //
+ Status = Ssp->ReceiveData (
+ Ssp,
+ MediaId,
+ 100000000, // Timeout 10-sec
+ 0, // SecurityProtocol
+ 0, // SecurityProtocolSpecifcData
+ Len, // PayloadBufferSize,
+ Buffer, // PayloadBuffer
+ &XferSize
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // In returned data, the ListLength field indicates the total length, in bytes,
+ // of the supported security protocol list.
+ //
+ Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA*)Buffer;
+ Len = ROUNDUP512(sizeof (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA) +
+ (Data->SupportedSecurityListLength[0] << 8) +
+ (Data->SupportedSecurityListLength[1])
+ );
+
+ //
+ // Free original buffer and allocate new buffer.
+ //
+ FreePool(Buffer);
+ Buffer = AllocateZeroPool(Len);
+ if (Buffer == NULL) {
+ return;
+ }
+
+ //
+ // Read full supported security protocol list from device.
+ //
+ Status = Ssp->ReceiveData (
+ Ssp,
+ MediaId,
+ 100000000, // Timeout 10-sec
+ 0, // SecurityProtocol
+ 0, // SecurityProtocolSpecifcData
+ Len, // PayloadBufferSize,
+ Buffer, // PayloadBuffer
+ &XferSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Data = (SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA*)Buffer;
+ Len = (Data->SupportedSecurityListLength[0] << 8) + Data->SupportedSecurityListLength[1];
+
+ //
+ // Iterate full supported security protocol list to check if TCG or IEEE 1667 protocol
+ // is supported.
+ //
+ for (Index = 0; Index < Len; Index++) {
+ if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_TCG) {
+ //
+ // Found a TCG device.
+ //
+ TcgFlag = TRUE;
+ DEBUG ((EFI_D_INFO, "This device is a TCG protocol device\n"));
+ break;
+ }
+
+ if (Data->SupportedSecurityProtocol[Index] == SECURITY_PROTOCOL_IEEE1667) {
+ //
+ // Found a IEEE 1667 device.
+ //
+ IeeeFlag = TRUE;
+ DEBUG ((EFI_D_INFO, "This device is a IEEE 1667 protocol device\n"));
+ break;
+ }
+ }
+
+ if (!TcgFlag && !IeeeFlag) {
+ DEBUG ((EFI_D_INFO, "Neither a TCG nor IEEE 1667 protocol device is found\n"));
+ goto Exit;
+ }
+
+ if (TcgFlag) {
+ //
+ // As long as TCG protocol is supported, send out a TPer Reset
+ // TCG command to the device via the TrustedSend command with a non-zero Transfer Length.
+ //
+ Status = Ssp->SendData (
+ Ssp,
+ MediaId,
+ 100000000, // Timeout 10-sec
+ SECURITY_PROTOCOL_TCG, // SecurityProtocol
+ 0x0400, // SecurityProtocolSpecifcData
+ 512, // PayloadBufferSize,
+ Buffer // PayloadBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Send TPer Reset Command Successfully !\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "Send TPer Reset Command Fail !\n"));
+ }
+ }
+
+ if (IeeeFlag) {
+ //
+ // TBD : Perform a TPer Reset via IEEE 1667 Protocol
+ //
+ DEBUG ((EFI_D_INFO, "IEEE 1667 Protocol didn't support yet!\n"));
+ }
+
+Exit:
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+}
+
+/**
+ Notification function of END_OF_DXE.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+TPerResetAtEndOfDxe (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ //
+ // Locate all SSP protocol instances.
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiStorageSecurityCommandProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+
+ if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) {
+ return;
+ }
+
+ for (Index = 0; Index < HandleCount; Index ++) {
+ //
+ // Get the SSP interface.
+ //
+ Status = gBS->HandleProtocol(
+ HandleBuffer[Index],
+ &gEfiStorageSecurityCommandProtocolGuid,
+ (VOID **) &Ssp
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol(
+ HandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ InitiateTPerReset (Ssp, BlockIo->Media->MediaId);
+ }
+
+ FreePool (HandleBuffer);
+}
+
/**
Entry Point for TCG MOR Control driver.
@param[in] ImageHandle Image handle of this driver.
@param[in] SystemTable A Pointer to the EFI System Table.
- @retval EFI_SUCEESS
+ @retval EFI_SUCEESS
@return Others Some error occurs.
**/
EFI_STATUS
@@ -34,48 +315,66 @@ MorDriverEntryPoint (
)
{
EFI_STATUS Status;
- UINT8 MorControl;
UINTN DataSize;
+ EFI_EVENT Event;
///
/// The firmware is required to create the MemoryOverwriteRequestControl UEFI variable.
///
- DataSize = sizeof (MorControl);
+ DataSize = sizeof (mMorControl);
Status = gRT->GetVariable (
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
- &gEfiMemoryOverwriteControlDataGuid,
- NULL,
- &DataSize,
- &MorControl
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ &gEfiMemoryOverwriteControlDataGuid,
+ NULL,
+ &DataSize,
+ &mMorControl
);
if (EFI_ERROR (Status)) {
//
// Set default value to 0
//
- MorControl = 0;
+ mMorControl = 0;
+ Status = gRT->SetVariable (
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ &gEfiMemoryOverwriteControlDataGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ &mMorControl
+ );
+ DEBUG ((EFI_D_INFO, "TcgMor: Create MOR variable! Status = %r\n", Status));
} else {
- if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
- //
- // MorControl is expected, directly return to avoid unnecessary variable operation
- //
- return EFI_SUCCESS;
+ //
+ // Create a Ready To Boot Event and Clear the MorControl bit in the call back function.
+ //
+ DEBUG ((EFI_D_INFO, "TcgMor: Create ReadyToBoot Event for MorControl Bit cleanning!\n"));
+ Status = EfiCreateEventReadyToBootEx (
+ TPL_CALLBACK,
+ OnReadyToBoot,
+ NULL,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
}
+
//
- // Clear MOR_CLEAR_MEMORY_BIT
+ // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
//
- DEBUG ((EFI_D_INFO, "TcgMor: Clear MorClearMemory bit\n"));
- MorControl &= 0xFE;
+ DEBUG ((EFI_D_INFO, "TcgMor: Create EndofDxe Event for Mor TPer Reset!\n"));
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ TPerResetAtEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
}
-
- Status = gRT->SetVariable (
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
- &gEfiMemoryOverwriteControlDataGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- DataSize,
- &MorControl
- );
- ASSERT_EFI_ERROR (Status);
+
return Status;
}