]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
Add TPM2 implementation.
[mirror_edk2.git] / SecurityPkg / Library / Tpm2CommandLib / Tpm2Hierarchy.c
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2Hierarchy.c
new file mode 100644 (file)
index 0000000..c6935d9
--- /dev/null
@@ -0,0 +1,635 @@
+/** @file\r
+  Implement TPM2 Hierarchy related command.\r
+\r
+Copyright (c) 2013, 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
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/Tpm2DeviceLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_CLEAR             AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_CLEAR_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CLEAR_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_CLEAR             AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPMI_YES_NO               Disable;\r
+} TPM2_CLEAR_CONTROL_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CLEAR_CONTROL_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_HIERARCHY_AUTH    AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPM2B_AUTH                NewAuth;\r
+} TPM2_HIERARCHY_CHANGE_AUTH_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PLATFORM          AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_CHANGE_EPS_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CHANGE_EPS_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_PLATFORM          AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+} TPM2_CHANGE_PPS_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_CHANGE_PPS_RESPONSE;\r
+\r
+typedef struct {\r
+  TPM2_COMMAND_HEADER       Header;\r
+  TPMI_RH_HIERARCHY         AuthHandle;\r
+  UINT32                    AuthorizationSize;\r
+  TPMS_AUTH_COMMAND         AuthSession;\r
+  TPMI_RH_HIERARCHY         Hierarchy;\r
+  TPMI_YES_NO               State;\r
+} TPM2_HIERARCHY_CONTROL_COMMAND;\r
+\r
+typedef struct {\r
+  TPM2_RESPONSE_HEADER       Header;\r
+  UINT32                     ParameterSize;\r
+  TPMS_AUTH_RESPONSE         AuthSession;\r
+} TPM2_HIERARCHY_CONTROL_RESPONSE;\r
+\r
+#pragma pack()\r
+\r
+/**\r
+  This command removes all TPM context associated with a specific Owner.\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2Clear (\r
+  IN TPMI_RH_CLEAR             AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_CLEAR_COMMAND                Cmd;\r
+  TPM2_CLEAR_RESPONSE               Res;\r
+  UINT32                            ResultBufSize;\r
+  UINT32                            CmdSize;\r
+  UINT32                            RespSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_Clear);\r
+  Cmd.AuthHandle         = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize   = SwapBytes32(CmdSize);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "Clear: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "Clear: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  // None\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Disables and enables the execution of TPM2_Clear().\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] Disable           YES if the disableOwnerClear flag is to be SET,\r
+                               NO if the flag is to be CLEAR.\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ClearControl (\r
+  IN TPMI_RH_CLEAR             AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession, OPTIONAL\r
+  IN TPMI_YES_NO               Disable\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  TPM2_CLEAR_CONTROL_COMMAND        Cmd;\r
+  TPM2_CLEAR_CONTROL_RESPONSE       Res;\r
+  UINT32                            ResultBufSize;\r
+  UINT32                            CmdSize;\r
+  UINT32                            RespSize;\r
+  UINT8                             *Buffer;\r
+  UINT32                            SessionInfoSize;\r
+\r
+  Cmd.Header.tag         = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.commandCode = SwapBytes32(TPM_CC_ClearControl);\r
+  Cmd.AuthHandle         = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // disable\r
+  *(UINT8 *)Buffer = Disable;\r
+  Buffer += sizeof(UINT8);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize   = SwapBytes32(CmdSize);\r
+\r
+  ResultBufSize = sizeof(Res);\r
+  Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ClearControl: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ClearControl: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG ((EFI_D_ERROR, "ClearControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Unmarshal the response\r
+  //\r
+\r
+  // None\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command allows the authorization secret for a hierarchy or lockout to be changed using the current\r
+  authorization value as the command authorization.\r
+\r
+  @param[in] AuthHandle        TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] NewAuth           New authorization secret\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HierarchyChangeAuth (\r
+  IN TPMI_RH_HIERARCHY_AUTH    AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN TPM2B_AUTH                *NewAuth\r
+  )\r
+{\r
+  EFI_STATUS                           Status;\r
+  TPM2_HIERARCHY_CHANGE_AUTH_COMMAND   Cmd;\r
+  TPM2_HIERARCHY_CHANGE_AUTH_RESPONSE  Res;\r
+  UINT32                               CmdSize;\r
+  UINT32                               RespSize;\r
+  UINT8                                *Buffer;\r
+  UINT32                               SessionInfoSize;\r
+  UINT8                                *ResultBuf;\r
+  UINT32                               ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_HierarchyChangeAuth);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  // New Authorization size\r
+  WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NewAuth->size));\r
+  Buffer += sizeof(UINT16);\r
+\r
+  // New Authorizeation\r
+  CopyMem(Buffer, NewAuth->buffer, NewAuth->size);\r
+  Buffer += NewAuth->size;\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyChangeAuth: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"HierarchyChangeAuth: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This replaces the current EPS with a value from the RNG and sets the Endorsement hierarchy controls to\r
+  their default initialization values.\r
+\r
+  @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ChangeEPS (\r
+  IN TPMI_RH_PLATFORM          AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPM2_CHANGE_EPS_COMMAND   Cmd;\r
+  TPM2_CHANGE_EPS_RESPONSE  Res;\r
+  UINT32                    CmdSize;\r
+  UINT32                    RespSize;\r
+  UINT8                     *Buffer;\r
+  UINT32                    SessionInfoSize;\r
+  UINT8                     *ResultBuf;\r
+  UINT32                    ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_ChangeEPS);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangeEPS: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangeEPS: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"ChangeEPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This replaces the current PPS with a value from the RNG and sets platformPolicy to the default\r
+  initialization value (the Empty Buffer).\r
+\r
+  @param[in] AuthHandle        TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2ChangePPS (\r
+  IN TPMI_RH_PLATFORM          AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TPM2_CHANGE_PPS_COMMAND   Cmd;\r
+  TPM2_CHANGE_PPS_RESPONSE  Res;\r
+  UINT32                    CmdSize;\r
+  UINT32                    RespSize;\r
+  UINT8                     *Buffer;\r
+  UINT32                    SessionInfoSize;\r
+  UINT8                     *ResultBuf;\r
+  UINT32                    ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_ChangePPS);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangePPS: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "ChangePPS: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"ChangePPS: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This command enables and disables use of a hierarchy.\r
+\r
+  @param[in] AuthHandle        TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}\r
+  @param[in] AuthSession       Auth Session context\r
+  @param[in] Hierarchy         Hierarchy of the enable being modified\r
+  @param[in] State             YES if the enable should be SET,\r
+                               NO if the enable should be CLEAR\r
+\r
+  @retval EFI_SUCCESS      Operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tpm2HierarchyControl (\r
+  IN TPMI_RH_HIERARCHY         AuthHandle,\r
+  IN TPMS_AUTH_COMMAND         *AuthSession,\r
+  IN TPMI_RH_HIERARCHY         Hierarchy,\r
+  IN TPMI_YES_NO               State\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  TPM2_HIERARCHY_CONTROL_COMMAND   Cmd;\r
+  TPM2_HIERARCHY_CONTROL_RESPONSE  Res;\r
+  UINT32                           CmdSize;\r
+  UINT32                           RespSize;\r
+  UINT8                            *Buffer;\r
+  UINT32                           SessionInfoSize;\r
+  UINT8                            *ResultBuf;\r
+  UINT32                           ResultBufSize;\r
+\r
+  //\r
+  // Construct command\r
+  //\r
+  Cmd.Header.tag          = SwapBytes16(TPM_ST_SESSIONS);\r
+  Cmd.Header.paramSize    = SwapBytes32(sizeof(Cmd));\r
+  Cmd.Header.commandCode  = SwapBytes32(TPM_CC_HierarchyControl);\r
+  Cmd.AuthHandle          = SwapBytes32(AuthHandle);\r
+\r
+  //\r
+  // Add in Auth session\r
+  //\r
+  Buffer = (UINT8 *)&Cmd.AuthSession;\r
+\r
+  // sessionInfoSize\r
+  SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);\r
+  Buffer += SessionInfoSize;\r
+  Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize);\r
+\r
+  WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Hierarchy));\r
+  Buffer += sizeof(UINT32);\r
+\r
+  *(UINT8 *)Buffer = State;\r
+  Buffer += sizeof(UINT8);\r
+\r
+  CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);\r
+  Cmd.Header.paramSize = SwapBytes32(CmdSize);\r
+\r
+  ResultBuf     = (UINT8 *) &Res;\r
+  ResultBufSize = sizeof(Res);\r
+\r
+  //\r
+  // Call the TPM\r
+  //\r
+  Status = Tpm2SubmitCommand (\r
+             CmdSize, \r
+             (UINT8 *)&Cmd, \r
+             &ResultBufSize,\r
+             ResultBuf\r
+             );\r
+\r
+  if (ResultBufSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyControl: Failed ExecuteCommand: Buffer Too Small\r\n"));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Validate response headers\r
+  //\r
+  RespSize = SwapBytes32(Res.Header.paramSize);\r
+  if (RespSize > sizeof(Res)) {\r
+    DEBUG ((EFI_D_ERROR, "HierarchyControl: Response size too large! %d\r\n", RespSize));\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  //\r
+  // Fail if command failed\r
+  //\r
+  if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) {\r
+    DEBUG((EFI_D_ERROR,"HierarchyControl: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode)));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r