]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c
SecurityPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / SecurityPkg / Library / TcgStorageOpalLib / TcgStorageOpalCore.c
index cc8d5ef3f00033d2a9530732f47a44192de9da58..b58597e61f93ebf2dbfce61362e79e7889b3a40b 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   Public API for Opal Core library.\r
 \r
-Copyright (c) 2016, 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) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -19,6 +13,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 +85,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 +95,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 +126,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 +149,6 @@ OpalTrustedRecv(
                  Buffer,\r
                  &TransferSize\r
              );\r
-\r
     if (EFI_ERROR (Status)) {\r
       return TcgResultFailure;\r
     }\r
@@ -179,23 +181,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 +220,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 +313,59 @@ 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
+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 +395,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 +424,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 +488,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 +545,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 +617,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 +651,85 @@ 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
+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 +804,103 @@ 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
+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 +963,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 +1012,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 +1065,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 +1085,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 +1104,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 +1125,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,10 +1134,10 @@ 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
+  // For Pyrite type SSC, it not supports Active Key.\r
   // So here add check logic before enable it.\r
   //\r
   Ret = OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey);\r
@@ -922,12 +1156,12 @@ 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
       //\r
-      // TODO do we want to disable user1 if all permissions are not granted\r
+      // Disable user1 if all permissions are not granted.\r
       //\r
       return TcgResultFailure;\r
     }\r
@@ -947,7 +1181,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 +1225,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 +1260,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 +1281,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
@@ -1055,7 +1289,7 @@ OpalGlobalLockingRangeGenKey(
 /**\r
 \r
   The function updates the ReadLocked and WriteLocked columns of the Global Locking Range.\r
-  This funciton is required for a user1 authority, since a user1 authority shall only have access to ReadLocked and WriteLocked columns\r
+  This function is required for a user1 authority, since a user1 authority shall only have access to ReadLocked and WriteLocked columns\r
   (not ReadLockEnabled and WriteLockEnabled columns).\r
 \r
   @param[in]      LockingSpSession    OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key\r
@@ -1113,7 +1347,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 +1448,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 +1596,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 +1638,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 +1727,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 +1774,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 +1846,57 @@ 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
+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 +1920,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