]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
Add Tper Reset Logic by using MOR bit.
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaBusDxe / AtaBus.c
index 8fa0b3f626cea7b3b7786d45f878743235ba0624..17e2614b87d288d3ed2e0648fef96f1f0c036877 100644 (file)
@@ -18,6 +18,9 @@
 \r
 #include "AtaBus.h"\r
 \r
+UINT8   mMorControl;\r
+BOOLEAN mHasMor;\r
+\r
 //\r
 // ATA Bus Driver Binding Protocol Instance\r
 //\r
@@ -364,6 +367,19 @@ RegisterAtaDevice (
     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
@@ -1638,6 +1654,7 @@ InitializeAtaBus(
   )\r
 {\r
   EFI_STATUS              Status;\r
+  UINTN                   DataSize;\r
 \r
   //\r
   // Install driver model protocol(s).\r
@@ -1652,5 +1669,196 @@ InitializeAtaBus(
              );\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