--- /dev/null
+/** @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