\r
#include "AtaBus.h"\r
\r
+UINT8 mMorControl;\r
+BOOLEAN mHasMor;\r
+\r
//\r
// ATA Bus Driver Binding Protocol Instance\r
//\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
+ DEBUG ((EFI_D_INFO, "Successfully Install Storage Security Protocol on the ATA device\n"));\r
+ }\r
+\r
+ if (mHasMor) {\r
+ if (((mMorControl & 0x01) == 0x01) && ((AtaDevice->IdentifyData->trusted_computing_support & BIT0) != 0)) {\r
+ DEBUG ((EFI_D_INFO,\r
+ "mMorControl = %x, AtaDevice->IdentifyData->trusted_computing_support & BIT0 = %x\n",\r
+ mMorControl,\r
+ (AtaDevice->IdentifyData->trusted_computing_support & BIT0)\r
+ ));\r
+ DEBUG ((EFI_D_INFO, "Try to lock device by sending TPer Reset command...\n"));\r
+ InitiateTPerReset(AtaDevice);\r
+ }\r
}\r
\r
gBS->OpenProtocol (\r
)\r
{\r
EFI_STATUS Status;\r
+ UINTN DataSize;\r
\r
//\r
// Install driver model protocol(s).\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Get the MorControl bit.\r
+ //\r
+ DataSize = sizeof (mMorControl);\r
+ Status = gRT->GetVariable (\r
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,\r
+ &gEfiMemoryOverwriteControlDataGuid,\r
+ NULL,\r
+ &DataSize,\r
+ &mMorControl\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO, "AtaBus:gEfiMemoryOverwriteControlDataGuid doesn't exist!!***\n"));\r
+ mHasMor = FALSE;\r
+ mMorControl = 0;\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ DEBUG ((EFI_D_INFO, "AtaBus:Get the gEfiMemoryOverwriteControlDataGuid = %x!!***\n", mMorControl));\r
+ mHasMor = TRUE;\r
+ }\r
+\r
return Status;\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] AtaDevice ATA_DEVICE pointer.\r
+\r
+**/\r
+VOID\r
+InitiateTPerReset (\r
+ IN ATA_DEVICE *AtaDevice\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
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Ssp;\r
+ SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA *Data;\r
+\r
+ Buffer = NULL;\r
+ TcgFlag = FALSE;\r
+ IeeeFlag = FALSE;\r
+ Ssp = &AtaDevice->StorageSecurity;\r
+ BlockIo = &AtaDevice->BlockIo;\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
+ BlockIo->Media->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
+ BlockIo->Media->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
+ BlockIo->Media->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
#include <Uefi.h>\r
\r
+#include <Guid/MemoryOverwriteControl.h>\r
#include <Protocol/AtaPassThru.h>\r
#include <Protocol/BlockIo.h>\r
#include <Protocol/BlockIo2.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/DevicePathLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
#include <Library/TimerLib.h>\r
\r
#include <IndustryStandard/Atapi.h>\r
#define ATA_SUB_TASK_SIGNATURE SIGNATURE_32 ('A', 'S', 'T', 'S')\r
#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)\r
\r
+#define ROUNDUP512(x) (((x) % 512 == 0) ? (x) : ((x) / 512 + 1) * 512)\r
+\r
+#define SECURITY_PROTOCOL_TCG 0x02\r
+#define SECURITY_PROTOCOL_IEEE1667 0xEE\r
+\r
+//\r
+// ATA Supported Security Protocols List Description.\r
+// Refer to ATA8-ACS Spec 7.57.6.2 Table 69.\r
+//\r
+typedef struct {\r
+ UINT8 Reserved1[6];\r
+ UINT8 SupportedSecurityListLength[2];\r
+ UINT8 SupportedSecurityProtocol[1];\r
+} SUPPORTED_SECURITY_PROTOCOLS_PARAMETER_DATA;\r
+\r
//\r
// ATA bus data structure for ATA controller\r
//\r
IN VOID *PayloadBuffer\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] AtaDevice ATA_DEVICE pointer.\r
+\r
+**/\r
+VOID\r
+InitiateTPerReset (\r
+ IN ATA_DEVICE *AtaDevice\r
+ );\r
+\r
#endif\r