]> git.proxmox.com Git - mirror_edk2.git/commitdiff
SecurityPkg/TcgStorageOpalLib: Add supports for pyrite 2.0 spec.
authorEric Dong <eric.dong@intel.com>
Mon, 7 May 2018 05:31:43 +0000 (13:31 +0800)
committerEric Dong <eric.dong@intel.com>
Mon, 7 May 2018 07:03:24 +0000 (15:03 +0800)
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Hao Wu <hao.a.wu@intel.com>
SecurityPkg/Include/Library/TcgStorageOpalLib.h
SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c
SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLib.inf
SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLibInternal.h [new file with mode: 0644]
SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalUtil.c

index 9b64a8e5cdf4f5b152bddc75c1231079d369aa39..2947c0eaf1e15abf13bdff2cbd5108261bd74c25 100644 (file)
@@ -82,6 +82,15 @@ typedef struct {
     //\r
     UINT32 BlockSid : 1;\r
 \r
+    //\r
+    // Pyrite SSC V2 support  (0 - not supported, 1 - supported)\r
+    //\r
+    UINT32 PyriteSscV2 : 1;\r
+\r
+    //\r
+    // Supported Data Removal Mechanism support  (0 - not supported, 1 - supported)\r
+    //\r
+    UINT32 DataRemoval : 1;\r
 } OPAL_DISK_SUPPORT_ATTRIBUTE;\r
 \r
 //\r
@@ -834,4 +843,36 @@ OpalUtilAdminPasswordExists(
   IN  TCG_LOCKING_FEATURE_DESCRIPTOR   *LockingFeature\r
   );\r
 \r
+/**\r
+  Get Active Data Removal Mechanism Value.\r
+\r
+  @param[in]      Session,                       The session info for one opal device.\r
+  @param[in]      GeneratedSid                   Generated SID of disk\r
+  @param[in]      SidLength                      Length of generatedSid in bytes\r
+  @param[out]     ActiveDataRemovalMechanism     Return the active data removal mechanism.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalUtilGetActiveDataRemovalMechanism (\r
+  OPAL_SESSION      *Session,\r
+  const VOID        *GeneratedSid,\r
+  UINT32            SidLength,\r
+  UINT8             *ActiveDataRemovalMechanism\r
+  );\r
+\r
+/**\r
+  Get the supported Data Removal Mechanism list.\r
+\r
+  @param[in]      Session,                       The session info for one opal device.\r
+  @param[out]     RemovalMechanismLists          Return the supported data removal mechanism lists.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalUtilGetDataRemovalMechanismLists (\r
+  IN  OPAL_SESSION      *Session,\r
+  OUT UINT32            *RemovalMechanismLists\r
+  );\r
+\r
 #endif // _OPAL_CORE_H_\r
index 90cc51a24c170e829873f5a7180fa9f0a183657f..d794a91aad41d53c51b336554b562a44c11d522a 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Public API for Opal Core library.\r
 \r
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2016 - 2018, 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
@@ -19,6 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/DebugLib.h>\r
 #include <Library/TcgStorageOpalLib.h>\r
 \r
+#include "TcgStorageOpalLibInternal.h"\r
+\r
 #pragma pack(1)\r
 typedef struct {\r
     UINT8 HardwareReset : 1;\r
@@ -89,6 +91,7 @@ OpalTrustedSend(
   @param[in]      SpSpecific            Security Protocol Specific\r
   @param[in]      Buffer                Address of Data to transfer\r
   @param[in]      BufferSize            Full Size of Buffer, including space that may be used for padding.\r
+  @param[in]      EstimateTimeCost      Estimate the time needed.\r
 \r
 **/\r
 TCG_RESULT\r
@@ -98,10 +101,10 @@ OpalTrustedRecv(
   UINT8                                  SecurityProtocol,\r
   UINT16                                 SpSpecific,\r
   VOID                                   *Buffer,\r
-  UINTN                                  BufferSize\r
+  UINTN                                  BufferSize,\r
+  UINT32                                 EstimateTimeCost\r
   )\r
 {\r
-\r
   UINTN           TransferLength512;\r
   UINT32          Tries;\r
   TCG_COM_PACKET  *ComPacket;\r
@@ -129,9 +132,15 @@ OpalTrustedRecv(
   // so we need to retry the IF-RECV to get the actual Data.\r
   // See TCG Core Spec v2 Table 45 IF-RECV ComPacket Field Values Summary\r
   // This is an arbitrary number of retries, not from the spec.\r
-  // have a max timeout of 10 seconds, 5000 tries * 2ms = 10s\r
   //\r
-  Tries = 5000;\r
+  // if user input estimate time cost(second level) value bigger than 10s, base on user input value to wait.\r
+  // Else, Use a max timeout of 10 seconds to wait, 5000 tries * 2ms = 10s\r
+  //\r
+  if (EstimateTimeCost > 10) {\r
+    Tries = EstimateTimeCost * 500; // 500 = 1000 * 1000 / 2000;\r
+  } else {\r
+    Tries = 5000;\r
+  }\r
   while ((Tries--) > 0) {\r
     ZeroMem( Buffer, BufferSize );\r
     TransferSize = 0;\r
@@ -146,7 +155,6 @@ OpalTrustedRecv(
                  Buffer,\r
                  &TransferSize\r
              );\r
-\r
     if (EFI_ERROR (Status)) {\r
       return TcgResultFailure;\r
     }\r
@@ -179,23 +187,24 @@ OpalTrustedRecv(
 /**\r
   The function performs send, recv, check comIDs, check method status action.\r
 \r
-  @param[in]      Session         OPAL_SESSION related to this method..\r
-  @param[in]      SendSize        Transfer Length of Buffer (in bytes) - always a multiple of 512\r
-  @param[in]      Buffer          Address of Data to transfer\r
-  @param[in]      BufferSize      Full Size of Buffer, including space that may be used for padding.\r
-  @param[in]      ParseStruct     Structure used to parse received TCG response.\r
-  @param[in]      MethodStatus    Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.\r
-\r
+  @param[in]      Session           OPAL_SESSION related to this method..\r
+  @param[in]      SendSize          Transfer Length of Buffer (in bytes) - always a multiple of 512\r
+  @param[in]      Buffer            Address of Data to transfer\r
+  @param[in]      BufferSize        Full Size of Buffer, including space that may be used for padding.\r
+  @param[in]      ParseStruct       Structure used to parse received TCG response.\r
+  @param[in]      MethodStatus      Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.\r
+  @param[in]      EstimateTimeCost  Estimate the time need to for the method.\r
 **/\r
 TCG_RESULT\r
 EFIAPI\r
-OpalPerformMethod(\r
+OpalPerformMethod (\r
   OPAL_SESSION     *Session,\r
   UINT32           SendSize,\r
   VOID             *Buffer,\r
   UINT32           BufferSize,\r
   TCG_PARSE_STRUCT *ParseStruct,\r
-  UINT8            *MethodStatus\r
+  UINT8            *MethodStatus,\r
+  UINT32           EstimateTimeCost\r
   )\r
 {\r
   NULL_CHECK(Session);\r
@@ -217,7 +226,8 @@ OpalPerformMethod(
                   TCG_OPAL_SECURITY_PROTOCOL_1,\r
                   Session->OpalBaseComId,\r
                   Buffer,\r
-                  BufferSize\r
+                  BufferSize,\r
+                  EstimateTimeCost\r
               ));\r
 \r
   ERROR_CHECK(TcgInitTcgParseStruct(ParseStruct, Buffer, BufferSize));\r
@@ -309,7 +319,60 @@ OpalPsidRevert(
   //\r
   // Send Revert Method Call\r
   //\r
-  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));\r
+  METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);\r
+\r
+  return TcgResultSuccess;\r
+}\r
+\r
+/**\r
+\r
+  Reverts device using Admin SP Revert method.\r
+\r
+  @param[in]  AdminSpSession      OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.\r
+  @param[in]  EstimateTimeCost    Estimate the time needed.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalPyrite2PsidRevert(\r
+  OPAL_SESSION              *AdminSpSession,\r
+  UINT32                    EstimateTimeCost\r
+  )\r
+{\r
+  //\r
+  // Now that base comid is known, start Session\r
+  // we'll attempt to start Session as PSID authority\r
+  // verify PSID Authority is defined in ADMIN SP authority table... is this possible?\r
+  //\r
+  TCG_CREATE_STRUCT  CreateStruct;\r
+  TCG_PARSE_STRUCT   ParseStruct;\r
+  UINT32             Size;\r
+  UINT8              Buffer[BUFFER_SIZE];\r
+  UINT8              MethodStatus;\r
+\r
+\r
+  NULL_CHECK(AdminSpSession);\r
+\r
+  //\r
+  // Send Revert action on Admin SP\r
+  //\r
+  ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));\r
+  ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));\r
+  ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));\r
+  ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));\r
+  ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD));\r
+  ERROR_CHECK(TcgStartParameters(&CreateStruct));\r
+  ERROR_CHECK(TcgEndParameters(&CreateStruct));\r
+  ERROR_CHECK(TcgEndMethodCall(&CreateStruct));\r
+  ERROR_CHECK(TcgEndSubPacket(&CreateStruct));\r
+  ERROR_CHECK(TcgEndPacket(&CreateStruct));\r
+  ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));\r
+\r
+  //\r
+  // Send Revert Method Call\r
+  //\r
+  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, EstimateTimeCost));\r
   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);\r
 \r
   return TcgResultSuccess;\r
@@ -339,7 +402,8 @@ OpalRetrieveLevel0DiscoveryHeader(
               TCG_OPAL_SECURITY_PROTOCOL_1,   // SP\r
               TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY, // SP_Specific\r
               BuffAddress,\r
-              BufferSize\r
+              BufferSize,\r
+              0\r
             ));\r
 }\r
 \r
@@ -367,7 +431,8 @@ OpalRetrieveSupportedProtocolList(
               TCG_SECURITY_PROTOCOL_INFO, // SP\r
               TCG_SP_SPECIFIC_PROTOCOL_LIST, // SP_Specific\r
               BuffAddress,\r
-              BufferSize\r
+              BufferSize,\r
+              0\r
           ));\r
 }\r
 \r
@@ -430,7 +495,7 @@ OpalStartSession(
                     HostChallenge,\r
                     HostSigningAuthority\r
                 ));\r
-  ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
     return TcgResultSuccess; // return early if method failed - user must check MethodStatus\r
   }\r
@@ -487,7 +552,8 @@ OpalEndSession(
                   TCG_OPAL_SECURITY_PROTOCOL_1,\r
                   Session->OpalBaseComId,\r
                   Buffer,\r
-                  sizeof(Buffer)\r
+                  sizeof(Buffer),\r
+                  0\r
               ));\r
 \r
   ERROR_CHECK(TcgInitTcgParseStruct(&ParseStruct, Buffer, sizeof(Buffer)));\r
@@ -558,7 +624,7 @@ OpalGetMsid(
   //\r
   // Send MSID Method Call\r
   //\r
-  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));\r
   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);\r
 \r
   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));\r
@@ -592,6 +658,86 @@ OpalGetMsid(
   return TcgResultSuccess;\r
 }\r
 \r
+/**\r
+\r
+  The function retrieves the MSID from the device specified\r
+\r
+  @param[in]  AdminSpSession              OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_ANYBODY_AUTHORITY\r
+  @param[out] ActiveDataRemovalMechanism  Active Data Removal Mechanism that the device will use for Revert/RevertSP calls.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalPyrite2GetActiveDataRemovalMechanism (\r
+  IN  OPAL_SESSION    *AdminSpSession,\r
+  OUT UINT8           *ActiveDataRemovalMechanism\r
+  )\r
+{\r
+  TCG_CREATE_STRUCT CreateStruct;\r
+  TCG_PARSE_STRUCT  ParseStruct;\r
+  UINT32            Size;\r
+  UINT8             MethodStatus;\r
+  UINT32            Col;\r
+  UINT8             RecvActiveDataRemovalMechanism;\r
+  UINT8             Buffer[BUFFER_SIZE];\r
+\r
+  NULL_CHECK(AdminSpSession);\r
+  NULL_CHECK(ActiveDataRemovalMechanism);\r
+\r
+  ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));\r
+  ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));\r
+  ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));\r
+  ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));\r
+  ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP_DATA_REMOVAL_MECHANISM, TCG_UID_METHOD_GET));\r
+  ERROR_CHECK(TcgStartParameters(&CreateStruct));\r
+  ERROR_CHECK(TcgAddStartList(&CreateStruct));\r
+  ERROR_CHECK(TcgAddStartName(&CreateStruct));\r
+  ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));\r
+  ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));\r
+  ERROR_CHECK(TcgAddEndName(&CreateStruct));\r
+  ERROR_CHECK(TcgAddStartName(&CreateStruct));\r
+  ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));\r
+  ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));\r
+  ERROR_CHECK(TcgAddEndName(&CreateStruct));\r
+  ERROR_CHECK(TcgAddEndList(&CreateStruct));\r
+  ERROR_CHECK(TcgEndParameters(&CreateStruct));\r
+  ERROR_CHECK(TcgEndMethodCall(&CreateStruct));\r
+  ERROR_CHECK(TcgEndSubPacket(&CreateStruct));\r
+  ERROR_CHECK(TcgEndPacket(&CreateStruct));\r
+  ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));\r
+\r
+  //\r
+  // Send Get Active Data Removal Mechanism Method Call\r
+  //\r
+  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));\r
+  METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);\r
+\r
+  ERROR_CHECK(TcgGetNextStartList(&ParseStruct));\r
+  ERROR_CHECK(TcgGetNextStartList(&ParseStruct));\r
+  ERROR_CHECK(TcgGetNextStartName(&ParseStruct));\r
+  ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));\r
+  ERROR_CHECK(TcgGetNextUINT8(&ParseStruct, &RecvActiveDataRemovalMechanism));\r
+  ERROR_CHECK(TcgGetNextEndName(&ParseStruct));\r
+  ERROR_CHECK(TcgGetNextEndList(&ParseStruct));\r
+  ERROR_CHECK(TcgGetNextEndList(&ParseStruct));\r
+  ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));\r
+\r
+  if (Col != OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL) {\r
+    DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));\r
+    return TcgResultFailure;\r
+  }\r
+\r
+  if (RecvActiveDataRemovalMechanism >= ResearvedMechanism) {\r
+    return TcgResultFailure;\r
+  }\r
+\r
+  //\r
+  // Copy active data removal mechanism into Buffer\r
+  //\r
+  CopyMem(ActiveDataRemovalMechanism, &RecvActiveDataRemovalMechanism, sizeof(RecvActiveDataRemovalMechanism));\r
+  return TcgResultSuccess;\r
+}\r
+\r
 /**\r
 \r
   The function calls the Admin SP RevertSP method on the Locking SP.  If KeepUserData is True, then the optional parameter\r
@@ -666,7 +812,104 @@ OpalAdminRevert(
   //\r
   // Send RevertSP method call\r
   //\r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
+\r
+  //\r
+  // Session is immediately ended by device after successful revertsp, so no need to end Session\r
+  //\r
+  if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {\r
+    //\r
+    // Caller should take ownership again\r
+    //\r
+    return TcgResultSuccess;\r
+  } else {\r
+    //\r
+    // End Session\r
+    //\r
+    METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);     // exit with success on method failure - user must inspect MethodStatus\r
+  }\r
+\r
+  return TcgResultSuccess;\r
+}\r
+\r
+\r
+/**\r
+\r
+  The function calls the Admin SP RevertSP method on the Locking SP.  If KeepUserData is True, then the optional parameter\r
+  to keep the user Data is set to True, otherwise the optional parameter is not provided.\r
+\r
+  @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP\r
+  @param[in]      KeepUserData        Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data.\r
+  @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.\r
+  @param[in]      EstimateTimeCost    Estimate the time needed.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalPyrite2AdminRevert(\r
+  OPAL_SESSION    *LockingSpSession,\r
+  BOOLEAN         KeepUserData,\r
+  UINT8           *MethodStatus,\r
+  UINT32          EstimateTimeCost\r
+  )\r
+{\r
+  UINT8             Buf[BUFFER_SIZE];\r
+  TCG_CREATE_STRUCT CreateStruct;\r
+  UINT32            Size;\r
+  TCG_PARSE_STRUCT  ParseStruct;\r
+  TCG_RESULT        Ret;\r
+\r
+  NULL_CHECK(LockingSpSession);\r
+  NULL_CHECK(MethodStatus);\r
+\r
+  //\r
+  // ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data\r
+  //\r
+  if (KeepUserData) {\r
+    //\r
+    // set readlocked and writelocked to false\r
+    //\r
+    Ret = OpalUpdateGlobalLockingRange(\r
+                        LockingSpSession,\r
+                        FALSE,\r
+                        FALSE,\r
+                        MethodStatus);\r
+\r
+    if (Ret != TcgResultSuccess || *MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
+      //\r
+      // bail out\r
+      //\r
+      return Ret;\r
+    }\r
+  }\r
+\r
+  ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));\r
+  ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));\r
+  ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));\r
+  ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));\r
+  ERROR_CHECK(TcgStartMethodCall(&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD));\r
+  ERROR_CHECK(TcgStartParameters(&CreateStruct));\r
+\r
+  if (KeepUserData) {\r
+    //\r
+    // optional parameter to keep Data after revert\r
+    //\r
+    ERROR_CHECK(TcgAddStartName(&CreateStruct));\r
+    ERROR_CHECK(TcgAddUINT32(&CreateStruct, 0x060000));      // weird Value but that's what spec says\r
+    ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, KeepUserData));\r
+    ERROR_CHECK(TcgAddEndName(&CreateStruct));\r
+  }\r
+\r
+  ERROR_CHECK(TcgEndParameters(&CreateStruct));\r
+  ERROR_CHECK(TcgEndMethodCall(&CreateStruct));\r
+  ERROR_CHECK(TcgEndSubPacket(&CreateStruct));\r
+  ERROR_CHECK(TcgEndPacket(&CreateStruct));\r
+  ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));\r
+\r
+  //\r
+  // Send RevertSP method call\r
+  //\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, EstimateTimeCost));\r
 \r
   //\r
   // Session is immediately ended by device after successful revertsp, so no need to end Session\r
@@ -729,7 +972,7 @@ OpalActivateLockingSp(
   //\r
   // Send Activate method call\r
   //\r
-  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus\r
 \r
   return TcgResultSuccess;\r
@@ -778,7 +1021,7 @@ OpalSetPassword(
                          NewPinLength\r
                          ));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
   // exit with success on method failure - user must inspect MethodStatus\r
   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);\r
 \r
@@ -831,7 +1074,7 @@ OpalSetLockingSpAuthorityEnabledAndPin(
                   AuthorityUid,\r
                   TRUE));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
     DEBUG ((DEBUG_INFO, "Send Set Authority error\n"));\r
@@ -851,7 +1094,7 @@ OpalSetLockingSpAuthorityEnabledAndPin(
                   NewPin,\r
                   NewPinLength));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   //\r
   // allow user1 to set global range to unlocked/locked by modifying ACE_Locking_GlobalRange_SetRdLocked/SetWrLocked\r
@@ -870,7 +1113,7 @@ OpalSetLockingSpAuthorityEnabledAndPin(
                   OPAL_LOCKING_SP_ADMINS_AUTHORITY\r
               ));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
     DEBUG ((DEBUG_INFO, "Update ACE for RDLOCKED failed\n"));\r
@@ -891,7 +1134,7 @@ OpalSetLockingSpAuthorityEnabledAndPin(
                   OPAL_LOCKING_SP_ADMINS_AUTHORITY\r
               ));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
     DEBUG ((DEBUG_INFO, "Update ACE for WRLOCKED failed\n"));\r
@@ -900,7 +1143,7 @@ OpalSetLockingSpAuthorityEnabledAndPin(
 \r
   ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));\r
   ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));\r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   //\r
   // For Pyrite type SSC, it not supports Active Key. \r
@@ -922,7 +1165,7 @@ OpalSetLockingSpAuthorityEnabledAndPin(
                     OPAL_LOCKING_SP_ADMINS_AUTHORITY\r
                 ));\r
 \r
-    ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+    ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
     if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
       DEBUG ((DEBUG_INFO, "Update ACE for GLOBALRANGE_GENKEY failed\n"));\r
@@ -947,7 +1190,7 @@ OpalSetLockingSpAuthorityEnabledAndPin(
                   OPAL_LOCKING_SP_ADMINS_AUTHORITY\r
               ));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
     DEBUG ((DEBUG_INFO, "Update ACE for OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL failed\n"));\r
@@ -991,7 +1234,7 @@ OpalDisableUser(
                   OPAL_LOCKING_SP_USER1_AUTHORITY,\r
                   FALSE));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   return TcgResultSuccess;\r
 }\r
@@ -1026,7 +1269,7 @@ OpalGlobalLockingRangeGenKey(
   // retrieve the activekey in order to know which globalrange key to generate\r
   //\r
   ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));\r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);\r
 \r
@@ -1047,7 +1290,7 @@ OpalGlobalLockingRangeGenKey(
   ERROR_CHECK(TcgEndPacket(&CreateStruct));\r
   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
 \r
   return TcgResultSuccess;\r
 }\r
@@ -1113,7 +1356,7 @@ OpalUpdateGlobalLockingRange(
   ERROR_CHECK(TcgEndPacket(&CreateStruct));\r
   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);\r
 \r
   return TcgResultSuccess;\r
@@ -1214,7 +1457,7 @@ OpalSetLockingRange(
   ERROR_CHECK(TcgEndPacket(&CreateStruct));\r
   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));\r
   // Exit with success on method failure - user must inspect MethodStatus\r
   METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);\r
 \r
@@ -1362,7 +1605,7 @@ OpalGetTryLimit(
   ERROR_CHECK(TcgEndPacket(&CreateStruct));\r
   ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));\r
 \r
-  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, &MethodStatus));\r
+  ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, &MethodStatus, 0));\r
   METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);\r
 \r
   ERROR_CHECK(TcgGetNextStartList(&ParseStruct));\r
@@ -1404,7 +1647,9 @@ OpalGetSupportedAttributesInfo(
   TCG_SUPPORTED_SECURITY_PROTOCOLS   *SupportedProtocols;\r
   TCG_LEVEL0_DISCOVERY_HEADER        *DiscoveryHeader;\r
   OPAL_LEVEL0_FEATURE_DESCRIPTOR     *Feat;\r
+  OPAL_LEVEL0_FEATURE_DESCRIPTOR     *Feat2;\r
   UINTN                              Size;\r
+  UINTN                              Size2;\r
 \r
   NULL_CHECK(Session);\r
   NULL_CHECK(SupportedAttributes);\r
@@ -1491,19 +1736,38 @@ OpalGetSupportedAttributesInfo(
     }\r
   }\r
 \r
+  //\r
+  // For some pyrite 2.0 device, it contains both pyrite 1.0 and 2.0 feature data.\r
+  // so here try to get data from pyrite 2.0 feature data first.\r
+  //\r
   Size = 0;\r
   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC, &Size);\r
-  SupportedAttributes->PyriteSsc = (Feat != NULL);\r
-  if (Feat != NULL && Size >= sizeof (PYRITE_SSC_FEATURE_DESCRIPTOR)) {\r
+  Size2 = 0;\r
+  Feat2 = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC_V2_0_0, &Size2);\r
+  if (Feat2 != NULL && Size2 >= sizeof (PYRITE_SSCV2_FEATURE_DESCRIPTOR)) {\r
+    SupportedAttributes->PyriteSscV2 = TRUE;\r
     if (*OpalBaseComId == TCG_RESERVED_COMID) {\r
-      *OpalBaseComId = SwapBytes16 (Feat->PyriteSsc.BaseComdIdBE);\r
-      SupportedAttributes->InitCpinIndicator = (Feat->PyriteSsc.InitialCPINSIDPIN == 0);\r
-      SupportedAttributes->CpinUponRevert = (Feat->PyriteSsc.CPINSIDPINRevertBehavior == 0);\r
-      DEBUG ((DEBUG_INFO, "Pyrite SSC InitCpinIndicator %d  CpinUponRevert %d \n",\r
+      *OpalBaseComId = SwapBytes16 (Feat2->PyriteSscV2.BaseComdIdBE);\r
+      SupportedAttributes->InitCpinIndicator = (Feat2->PyriteSscV2.InitialCPINSIDPIN == 0);\r
+      SupportedAttributes->CpinUponRevert = (Feat2->PyriteSscV2.CPINSIDPINRevertBehavior == 0);\r
+      DEBUG ((DEBUG_INFO, "Pyrite SSC V2 InitCpinIndicator %d  CpinUponRevert %d \n",\r
                SupportedAttributes->InitCpinIndicator,\r
                SupportedAttributes->CpinUponRevert\r
               ));\r
     }\r
+  } else {\r
+    SupportedAttributes->PyriteSsc = (Feat != NULL);\r
+    if (Feat != NULL && Size >= sizeof (PYRITE_SSC_FEATURE_DESCRIPTOR)) {\r
+      if (*OpalBaseComId == TCG_RESERVED_COMID) {\r
+        *OpalBaseComId = SwapBytes16 (Feat->PyriteSsc.BaseComdIdBE);\r
+        SupportedAttributes->InitCpinIndicator = (Feat->PyriteSsc.InitialCPINSIDPIN == 0);\r
+        SupportedAttributes->CpinUponRevert = (Feat->PyriteSsc.CPINSIDPINRevertBehavior == 0);\r
+        DEBUG ((DEBUG_INFO, "Pyrite SSC InitCpinIndicator %d  CpinUponRevert %d \n",\r
+                 SupportedAttributes->InitCpinIndicator,\r
+                 SupportedAttributes->CpinUponRevert\r
+                ));\r
+      }\r
+    }\r
   }\r
 \r
   Size = 0;\r
@@ -1519,16 +1783,33 @@ OpalGetSupportedAttributesInfo(
   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size);\r
   if (Feat != NULL && Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)) {\r
     SupportedAttributes->MediaEncryption = Feat->Locking.MediaEncryption;\r
+    DEBUG ((DEBUG_INFO, "SupportedAttributes->MediaEncryption 0x%X \n", SupportedAttributes->MediaEncryption));\r
   }\r
 \r
   Size = 0;\r
   Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_BLOCK_SID, &Size);\r
   if (Feat != NULL && Size >= sizeof (TCG_BLOCK_SID_FEATURE_DESCRIPTOR)) {\r
     SupportedAttributes->BlockSid = TRUE;\r
+    DEBUG ((DEBUG_INFO, "BlockSid Supported!!! Current Status is 0x%X \n", Feat->BlockSid.SIDBlockedState));\r
+  } else {\r
+    DEBUG ((DEBUG_INFO, "BlockSid Unsupported!!!"));\r
   }\r
 \r
-  DEBUG ((DEBUG_INFO, "Base COMID 0x%04X \n", *OpalBaseComId));\r
+  Size = 0;\r
+  Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_DATA_REMOVAL, &Size);\r
+  if (Feat != NULL && Size >= sizeof (DATA_REMOVAL_FEATURE_DESCRIPTOR)) {\r
+    SupportedAttributes->DataRemoval = TRUE;\r
+    DEBUG ((DEBUG_INFO, "DataRemoval Feature Supported!\n"));\r
+    DEBUG ((DEBUG_INFO, "Operation Processing = 0x%x\n", Feat->DataRemoval.OperationProcessing));\r
+    DEBUG ((DEBUG_INFO, "RemovalMechanism = 0x%x\n", Feat->DataRemoval.RemovalMechanism));\r
+    DEBUG ((DEBUG_INFO, "BIT0 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit0, SwapBytes16 (Feat->DataRemoval.TimeBit0)));\r
+    DEBUG ((DEBUG_INFO, "BIT1 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit1, SwapBytes16 (Feat->DataRemoval.TimeBit1)));\r
+    DEBUG ((DEBUG_INFO, "BIT2 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit2, SwapBytes16 (Feat->DataRemoval.TimeBit2)));\r
+    DEBUG ((DEBUG_INFO, "BIT3 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit3, SwapBytes16 (Feat->DataRemoval.TimeBit3)));\r
+    DEBUG ((DEBUG_INFO, "BIT4 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit4, SwapBytes16 (Feat->DataRemoval.TimeBit4)));\r
+  }\r
 \r
+  DEBUG ((DEBUG_INFO, "Base COMID 0x%04X \n", *OpalBaseComId));\r
 \r
   return TcgResultSuccess;\r
 }\r
@@ -1574,6 +1855,58 @@ OpalGetLockingInfo(
   return TcgResultSuccess;\r
 }\r
 \r
+/**\r
+\r
+  Get the descriptor for the specific feature code.\r
+\r
+  @param[in]      Session             OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.\r
+  @param[in]      FeatureCode         The feature code user request.\r
+  @param[in, out] DataSize            The data size.\r
+  @param[out]     Data                The data buffer used to save the feature descriptor.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalGetFeatureDescriptor (\r
+  IN     OPAL_SESSION              *Session,\r
+  IN     UINT16                    FeatureCode,\r
+  IN OUT UINTN                     *DataSize,\r
+  OUT    VOID                      *Data\r
+  )\r
+{\r
+  UINT8                              Buffer[BUFFER_SIZE];\r
+  TCG_LEVEL0_DISCOVERY_HEADER        *DiscoveryHeader;\r
+  OPAL_LEVEL0_FEATURE_DESCRIPTOR     *Feat;\r
+  UINTN                              Size;\r
+\r
+  NULL_CHECK(Session);\r
+  NULL_CHECK(DataSize);\r
+  NULL_CHECK(Data);\r
+\r
+  ZeroMem(Buffer, BUFFER_SIZE);\r
+  ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));\r
+\r
+  if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {\r
+    DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));\r
+    return TcgResultFailure;\r
+  }\r
+  DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;\r
+\r
+  Size = 0;\r
+  Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, FeatureCode, &Size);\r
+  if (Feat != NULL) {\r
+    if (Size > *DataSize) {\r
+      *DataSize = Size;\r
+      return TcgResultFailureBufferTooSmall;\r
+    }\r
+\r
+    *DataSize = Size;\r
+    CopyMem (Data, Feat, Size);\r
+  }\r
+\r
+  return TcgResultSuccess;\r
+}\r
+\r
 /**\r
 \r
   The function determines whether or not all of the requirements for the Opal Feature (not full specification)\r
@@ -1597,7 +1930,8 @@ OpalFeatureSupported(
   if (SupportedAttributes->OpalSscLite == 0 &&\r
       SupportedAttributes->OpalSsc1 == 0 &&\r
       SupportedAttributes->OpalSsc2 == 0 &&\r
-      SupportedAttributes->PyriteSsc == 0\r
+      SupportedAttributes->PyriteSsc == 0 &&\r
+      SupportedAttributes->PyriteSscV2 == 0\r
      ) {\r
     return FALSE;\r
   }\r
index 78e47387a98188c26d5f3dd8169620dcca8accbc..70f54f7f8ad8a9821fd16d4651cbf055191c7f2f 100644 (file)
@@ -29,6 +29,7 @@
 [Sources]\r
   TcgStorageOpalCore.c\r
   TcgStorageOpalUtil.c\r
+  TcgStorageOpalLibInternal.h\r
 \r
 [LibraryClasses]\r
   BaseLib\r
diff --git a/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLibInternal.h b/SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalLibInternal.h
new file mode 100644 (file)
index 0000000..cd16c51
--- /dev/null
@@ -0,0 +1,98 @@
+/** @file\r
+  Internal functions for Opal Core library.\r
+\r
+Copyright (c) 2018, 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
+\r
+**/\r
+\r
+#ifndef _OPAL_INTERNAL_H_\r
+#define _OPAL_INTERNAL_H_\r
+\r
+#include <Library/TcgStorageOpalLib.h>\r
+\r
+\r
+/**\r
+\r
+  The function retrieves the MSID from the device specified\r
+\r
+  @param[in]  AdminSpSession              OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_ANYBODY_AUTHORITY\r
+  @param[out] ActiveDataRemovalMechanism  Active Data Removal Mechanism that the device will use for Revert/RevertSP calls.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalPyrite2GetActiveDataRemovalMechanism (\r
+  OPAL_SESSION    *AdminSpSession,\r
+  UINT8           *ActiveDataRemovalMechanism\r
+  );\r
+\r
+/**\r
+\r
+  Get the support attribute info.\r
+\r
+  @param[in]      Session             OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.\r
+  @param[in]      FeatureCode         The feature code user request.\r
+  @param[in, out] DataSize            The data size.\r
+  @param[out]     Data                The data buffer used to save the feature descriptor.\r
+\r
+**/\r
+TCG_RESULT\r
+OpalGetFeatureDescriptor (\r
+  IN     OPAL_SESSION              *Session,\r
+  IN     UINT16                    FeatureCode,\r
+  IN OUT UINTN                     *DataSize,\r
+  OUT    VOID                      *Data\r
+  );\r
+\r
+/**\r
+  Get revert timeout value.\r
+\r
+  @param[in]      Session                       The session info for one opal device.\r
+\r
+**/\r
+UINT32\r
+GetRevertTimeOut (\r
+  IN OPAL_SESSION                *Session\r
+  );\r
+\r
+/**\r
+\r
+  Reverts device using Admin SP Revert method.\r
+\r
+  @param[in]  AdminSpSession      OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.\r
+  @param[in]  EstimateTimeCost    Input the timeout value.\r
+\r
+**/\r
+TCG_RESULT\r
+OpalPyrite2PsidRevert(\r
+  OPAL_SESSION              *AdminSpSession,\r
+  UINT32                    EstimateTimeCost\r
+  );\r
+\r
+/**\r
+\r
+  The function calls the Admin SP RevertSP method on the Locking SP.  If KeepUserData is True, then the optional parameter\r
+  to keep the user Data is set to True, otherwise the optional parameter is not provided.\r
+\r
+  @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP\r
+  @param[in]      KeepUserData        Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data.\r
+  @param[in/out]  MethodStatus        Method status of last action performed.  If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.\r
+  @param[in]      EstimateTimeCost    Input the timeout value.\r
+\r
+**/\r
+TCG_RESULT\r
+OpalPyrite2AdminRevert(\r
+  OPAL_SESSION    *LockingSpSession,\r
+  BOOLEAN         KeepUserData,\r
+  UINT8           *MethodStatus,\r
+  UINT32          EstimateTimeCost\r
+  );\r
+\r
+#endif // _OPAL_CORE_H_\r
index f77fbe25c1043fda255cbd9abe2cbb18fbd7b60b..a8bf3a916036e7a29c84e9ddd063e52a1d3a6a82 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Public API for Opal Core library.\r
 \r
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2016 - 2018, 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
@@ -15,7 +15,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/BaseLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <Library/TcgStorageOpalLib.h>\r
+#include "TcgStorageOpalLibInternal.h"\r
 \r
+#define OPAL_MSID_LENGHT        128\r
 \r
 /**\r
   Creates a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts device using Admin SP Revert method.\r
@@ -35,10 +37,14 @@ OpalUtilPsidRevert(
 {\r
   UINT8        MethodStatus;\r
   TCG_RESULT   Ret;\r
+  UINT32       RemovalTimeOut;\r
 \r
   NULL_CHECK(Session);\r
   NULL_CHECK(Psid);\r
 \r
+  RemovalTimeOut = GetRevertTimeOut (Session);\r
+  DEBUG ((DEBUG_INFO, "OpalUtilPsidRevert: Timeout value = %d\n", RemovalTimeOut));\r
+\r
   Ret = OpalStartSession(\r
                       Session,\r
                       OPAL_UID_ADMIN_SP,\r
@@ -48,7 +54,7 @@ OpalUtilPsidRevert(
                       OPAL_ADMIN_SP_PSID_AUTHORITY,\r
                       &MethodStatus);\r
   if (Ret == TcgResultSuccess && MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {\r
-    Ret = OpalPsidRevert(Session);\r
+    Ret = OpalPyrite2PsidRevert(Session, RemovalTimeOut);\r
     if (Ret != TcgResultSuccess) {\r
       //\r
       // If revert was successful, session was already ended by TPer, so only end session on failure\r
@@ -599,12 +605,16 @@ OpalUtilRevert(
 {\r
   UINT8        MethodStatus;\r
   TCG_RESULT   Ret;\r
+  UINT32       RemovalTimeOut;\r
 \r
   NULL_CHECK(Session);\r
   NULL_CHECK(Msid);\r
   NULL_CHECK(Password);\r
   NULL_CHECK(PasswordFailed);\r
 \r
+  RemovalTimeOut = GetRevertTimeOut (Session);\r
+  DEBUG ((DEBUG_INFO, "OpalUtilRevert: Timeout value = %d\n", RemovalTimeOut));\r
+\r
   Ret = OpalStartSession(\r
                    Session,\r
                    OPAL_UID_LOCKING_SP,\r
@@ -625,7 +635,7 @@ OpalUtilRevert(
   //\r
   // Try to revert with admin1\r
   //\r
-  Ret = OpalAdminRevert(Session, KeepUserData, &MethodStatus);\r
+  Ret = OpalPyrite2AdminRevert(Session, KeepUserData, &MethodStatus, RemovalTimeOut);\r
   if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
     //\r
     // Device ends the session on successful revert, so only call OpalEndSession when fail.\r
@@ -912,3 +922,201 @@ OpalUtilAdminPasswordExists(
   return (OwnerShip == OpalOwnershipUnknown && LockingFeature->LockingEnabled);\r
 }\r
 \r
+/**\r
+  Get Active Data Removal Mechanism Value.\r
+\r
+  @param[in]      Session                        The session info for one opal device.\r
+  @param[in]      GeneratedSid                   Generated SID of disk\r
+  @param[in]      SidLength                      Length of generatedSid in bytes\r
+  @param[out]     ActiveDataRemovalMechanism     Return the active data removal mechanism.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalUtilGetActiveDataRemovalMechanism (\r
+  OPAL_SESSION      *Session,\r
+  const VOID        *GeneratedSid,\r
+  UINT32            SidLength,\r
+  UINT8             *ActiveDataRemovalMechanism\r
+  )\r
+{\r
+  TCG_RESULT   Ret;\r
+  UINT8        MethodStatus;\r
+\r
+  NULL_CHECK(Session);\r
+  NULL_CHECK(GeneratedSid);\r
+  NULL_CHECK(ActiveDataRemovalMechanism);\r
+\r
+  Ret = OpalStartSession(\r
+                    Session,\r
+                    OPAL_UID_ADMIN_SP,\r
+                    TRUE,\r
+                    SidLength,\r
+                    GeneratedSid,\r
+                    OPAL_ADMIN_SP_ANYBODY_AUTHORITY,\r
+                    &MethodStatus\r
+                    );\r
+  if (Ret != TcgResultSuccess || MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
+    DEBUG ((DEBUG_INFO, "Start session with admin SP as SID authority failed: Ret=%d MethodStatus=%u\n", Ret, MethodStatus));\r
+    if (MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {\r
+      Ret = TcgResultFailure;\r
+    }\r
+    return Ret;\r
+  }\r
+\r
+  Ret = OpalPyrite2GetActiveDataRemovalMechanism (\r
+                    Session,\r
+                    ActiveDataRemovalMechanism\r
+                    );\r
+\r
+  if (Ret != TcgResultSuccess) {\r
+    DEBUG ((DEBUG_INFO, "Pyrite2 Get Active Data Removal Mechanism failed: Ret=%d\n", Ret));\r
+  }\r
+\r
+  OpalEndSession(Session);\r
+\r
+  return Ret;\r
+}\r
+\r
+/**\r
+  Calculate the estimated time.\r
+\r
+  @param[in]      IsMinite               Whether the input time value is minute type or second type.\r
+  @param[in]      Time                   The input time value.\r
+\r
+**/\r
+UINT32\r
+CalculateDataRemovalTime (\r
+  IN BOOLEAN               IsMinute,\r
+  IN UINT16                Time\r
+  )\r
+{\r
+  if (IsMinute) {\r
+    return Time * 2 * 60;\r
+  } else {\r
+    return Time * 2;\r
+  }\r
+}\r
+\r
+/**\r
+  Return the estimated time for specific type.\r
+\r
+  @param[in]      Index               The input data removal type.\r
+  @param[in]      Descriptor          DATA_REMOVAL_FEATURE_DESCRIPTOR\r
+\r
+**/\r
+UINT32\r
+GetDataRemovalTime (\r
+  IN  UINT8                            Index,\r
+  IN  DATA_REMOVAL_FEATURE_DESCRIPTOR  *Descriptor\r
+  )\r
+{\r
+  switch (Index) {\r
+  case OverwriteDataErase:\r
+    return CalculateDataRemovalTime (Descriptor->FormatBit0, SwapBytes16 (Descriptor->TimeBit0));\r
+\r
+  case BlockErase:\r
+    return CalculateDataRemovalTime (Descriptor->FormatBit1, SwapBytes16 (Descriptor->TimeBit1));\r
+\r
+  case CryptoErase:\r
+    return CalculateDataRemovalTime (Descriptor->FormatBit2, SwapBytes16 (Descriptor->TimeBit2));\r
+\r
+  case Unmap:\r
+    return CalculateDataRemovalTime (Descriptor->FormatBit3, SwapBytes16 (Descriptor->TimeBit3));\r
+\r
+  case ResetWritePointers:\r
+    return CalculateDataRemovalTime (Descriptor->FormatBit4, SwapBytes16 (Descriptor->TimeBit4));\r
+\r
+  case VendorSpecificErase:\r
+    return CalculateDataRemovalTime (Descriptor->FormatBit5, SwapBytes16 (Descriptor->TimeBit5));\r
+\r
+  default:\r
+    return 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Get the supported Data Removal Mechanism list.\r
+\r
+  @param[in]      Session                        The session info for one opal device.\r
+  @param[out]     RemovalMechanismLists          Return the supported data removal mechanism lists.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalUtilGetDataRemovalMechanismLists (\r
+  IN  OPAL_SESSION      *Session,\r
+  OUT UINT32            *RemovalMechanismLists\r
+  )\r
+{\r
+  TCG_RESULT                       Ret;\r
+  UINTN                            DataSize;\r
+  DATA_REMOVAL_FEATURE_DESCRIPTOR  Descriptor;\r
+  UINT8                            Index;\r
+  UINT8                            BitValue;\r
+\r
+  NULL_CHECK(Session);\r
+  NULL_CHECK(RemovalMechanismLists);\r
+\r
+  DataSize = sizeof (Descriptor);\r
+  Ret = OpalGetFeatureDescriptor (Session, TCG_FEATURE_DATA_REMOVAL, &DataSize, &Descriptor);\r
+  if (Ret != TcgResultSuccess) {\r
+    return TcgResultFailure;\r
+  }\r
+\r
+  ASSERT (Descriptor.RemovalMechanism != 0);\r
+\r
+  for (Index = 0; Index < ResearvedMechanism; Index ++) {\r
+    BitValue = (BOOLEAN) BitFieldRead8 (Descriptor.RemovalMechanism, Index, Index);\r
+\r
+    if (BitValue == 0) {\r
+      RemovalMechanismLists[Index] = 0;\r
+    } else {\r
+      RemovalMechanismLists[Index] = GetDataRemovalTime (Index, &Descriptor);\r
+    }\r
+  }\r
+\r
+  return TcgResultSuccess;\r
+}\r
+\r
+/**\r
+  Get revert timeout value.\r
+\r
+  @param[in]      Session                       The session info for one opal device.\r
+\r
+**/\r
+UINT32\r
+GetRevertTimeOut (\r
+  IN OPAL_SESSION                *Session\r
+  )\r
+{\r
+  TCG_RESULT                   TcgResult;\r
+  OPAL_DISK_SUPPORT_ATTRIBUTE  SupportedAttributes;\r
+  UINT16                       BaseComId;\r
+  UINT32                       MsidLength;\r
+  UINT8                        Msid[OPAL_MSID_LENGHT];\r
+  UINT32                       RemovalMechanishLists[ResearvedMechanism];\r
+  UINT8                        ActiveDataRemovalMechanism;\r
+\r
+  TcgResult = OpalGetSupportedAttributesInfo (Session, &SupportedAttributes, &BaseComId);\r
+  if (TcgResult != TcgResultSuccess || SupportedAttributes.DataRemoval == 0) {\r
+    return 0;\r
+  }\r
+\r
+  TcgResult = OpalUtilGetMsid (Session, Msid, OPAL_MSID_LENGHT, &MsidLength);\r
+  if (TcgResult != TcgResultSuccess) {\r
+    return 0;\r
+  }\r
+\r
+  TcgResult = OpalUtilGetDataRemovalMechanismLists (Session, RemovalMechanishLists);\r
+  if (TcgResult != TcgResultSuccess) {\r
+    return 0;\r
+  }\r
+\r
+  TcgResult = OpalUtilGetActiveDataRemovalMechanism (Session, Msid, MsidLength, &ActiveDataRemovalMechanism);\r
+  if (TcgResult != TcgResultSuccess) {\r
+    return 0;\r
+  }\r
+\r
+  return RemovalMechanishLists[ActiveDataRemovalMechanism];\r
+}\r