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