/**@file @copyright INTEL CONFIDENTIAL Copyright 2003 - 2021 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains a 'Sample Driver' and is licensed as such under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to the additional terms of the license agreement. @par Specification Reference: **/ #include #include #include #include // TCG2 implementation #include #include #include "MeSetup.h" #include GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID mTcg2ConfigFormSetGuid = TCG2_CONFIG_FORM_SET_GUID; extern BOOLEAN mMeReset; /** Initialize TCG Strings Populates the form's current TPM device strings based on the contents of the TCG2CONFIGURATION and TCG_SETUP variables populated by the TPM detection at runtime. @param[in] HiiHandle HiiHandle Handle to HII database @param[in] Class Indicates the setup class **/ VOID InitTcgStrings ( EFI_HII_HANDLE HiiHandle, UINT16 Class ) { EFI_STATUS Status; TCG2_CONFIGURATION *Tcg2Configuration; UINT32 Tcg2VarAttr; UINTN Tcg2Size; TCG_SETUP *TcgSetup; UINT32 TcgSetupAttr; UINTN TcgSetupSize; DEBUG ((DEBUG_INFO, "\n")); // // The TCG2_CONFIGURATION variable stores the detected TPM family type: TPM 1.2 or TPM 2.0 // Tcg2Configuration = NULL; Tcg2Size = 0; Status = gRT->GetVariable ( TCG2_STORAGE_NAME, &mTcg2ConfigFormSetGuid, &Tcg2VarAttr, &Tcg2Size, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { Tcg2Configuration = AllocateZeroPool (Tcg2Size); if (Tcg2Configuration == NULL) { Status = EFI_OUT_OF_RESOURCES; ASSERT_EFI_ERROR (Status); } else { Status = EFI_SUCCESS; } if (!EFI_ERROR (Status)) { Status = gRT->GetVariable ( TCG2_STORAGE_NAME, &mTcg2ConfigFormSetGuid, &Tcg2VarAttr, &Tcg2Size, Tcg2Configuration ); } } // // The TCG_SETUP variable encodes additional details regarding the TPM, // including the identification of PTT or a discrete module. // TcgSetup = NULL; TcgSetupSize = 0; if (!EFI_ERROR (Status)) { Status = gRT->GetVariable ( TCG_SETUP_NAME, &gSetupVariableGuid, &TcgSetupAttr, &TcgSetupSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { TcgSetup = AllocateZeroPool (Tcg2Size); if (TcgSetup == NULL) { Status = EFI_OUT_OF_RESOURCES; ASSERT_EFI_ERROR (Status); } else { Status = EFI_SUCCESS; } if (!EFI_ERROR (Status)) { Status = gRT->GetVariable ( TCG_SETUP_NAME, &gSetupVariableGuid, &TcgSetupAttr, &TcgSetupSize, TcgSetup ); } } } if (EFI_ERROR (Status)) { HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"TPM Detection Error", NULL); if (TcgSetup != NULL) { FreePool (TcgSetup); } if (Tcg2Configuration != NULL) { FreePool (Tcg2Configuration); } return; } if (Tcg2Configuration == NULL) { HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"TPM Detection Error", NULL); return; } // // Identify the current TPM device and populate the strings reported in the menu form. // switch (Tcg2Configuration->TpmDevice) { case TPM_DEVICE_NULL: HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"Not Found", NULL); break; case TPM_DEVICE_1_2: HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"dTPM 1.2", NULL); break; case TPM_DEVICE_2_0_DTPM: // // Differentiate between dTPM and PTT // if (TcgSetup == NULL) { HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"TPM Detection Error", NULL); } else if (TcgSetup->PttPresent == TRUE) { HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"PTT", NULL); } else { HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"dTPM 2.0", NULL); } break; default: HiiSetString (HiiHandle, STRING_TOKEN (STR_TCG2_DEVICE_STATE_CONTENT), L"Unknown", NULL); break; } if (TcgSetup != NULL) { FreePool (TcgSetup); } if (Tcg2Configuration != NULL) { FreePool (Tcg2Configuration); } return; } /** Return the Tcg form handle. @return Tcg form handle. **/ EFI_HII_HANDLE GetTcgFormHandle ( VOID ) { EFI_STATUS Status; UINTN BufferSize; EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; UINT8 *Package; UINT8 *OpCodeData; UINT32 Offset; UINT32 Offset2; UINT32 PackageListLength; EFI_HII_PACKAGE_HEADER PackageHeader; EFI_HII_DATABASE_PROTOCOL *HiiDatabase; UINTN HandleBufferLength; EFI_HII_HANDLE *HiiHandleBuffer; UINTN Index; EFI_HII_HANDLE TcgHandle; EFI_GUID TcgFormGuid = TCG_FORM_SET_GUID; Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase); ASSERT_EFI_ERROR (Status); HandleBufferLength = 0; Status = HiiDatabase->ListPackageLists ( HiiDatabase, EFI_HII_PACKAGE_TYPE_ALL, NULL, &HandleBufferLength, NULL ); ASSERT (Status == EFI_BUFFER_TOO_SMALL); HiiHandleBuffer = AllocateZeroPool (HandleBufferLength); if (HiiHandleBuffer == NULL) { return NULL; } Status = HiiDatabase->ListPackageLists ( HiiDatabase, EFI_HII_PACKAGE_TYPE_ALL, NULL, &HandleBufferLength, HiiHandleBuffer ); ASSERT_EFI_ERROR (Status); for (Index = 0; Index < HandleBufferLength / sizeof (EFI_HII_HANDLE); Index++) { // // Get HII PackageList // BufferSize = 0; HiiPackageList = NULL; Status = HiiDatabase->ExportPackageLists ( HiiDatabase, HiiHandleBuffer[Index], &BufferSize, HiiPackageList); // // Handle is a invalid handle. Check if Handle is corrupted. // ASSERT (Status != EFI_NOT_FOUND); // // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. // ASSERT (Status == EFI_BUFFER_TOO_SMALL); HiiPackageList = AllocatePool (BufferSize); ASSERT (HiiPackageList != NULL); if (HiiPackageList == NULL) { return NULL; } Status = HiiDatabase->ExportPackageLists ( HiiDatabase, HiiHandleBuffer[Index], &BufferSize, HiiPackageList); if (EFI_ERROR (Status)) { continue; } // // Get Form package from this HII package List // PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); for ( Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER) ; Offset < PackageListLength ; Offset += PackageHeader.Length ) { Package = ((UINT8 *) HiiPackageList) + Offset; CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { // // Search FormSet Opcode in this Form Package // for ( Offset2 = sizeof (EFI_HII_PACKAGE_HEADER) ; Offset2 < PackageHeader.Length ; Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length ) { OpCodeData = Package + Offset2; if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) && CompareGuid ((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) OpCodeData)->Guid, &TcgFormGuid)) { // // Find TCG FormSet // break; } } if (Offset2 < PackageHeader.Length) { break; } } } FreePool (HiiPackageList); if (Offset < PackageListLength) { break; } } if (Index < HandleBufferLength / sizeof (EFI_HII_HANDLE)) { TcgHandle = HiiHandleBuffer[Index]; } else { TcgHandle = NULL; } FreePool (HiiHandleBuffer); return TcgHandle; } /** Return the TrEE form handle. @return TrEE form handle. **/ EFI_HII_HANDLE GetTcg2FormHandle( VOID ) { EFI_STATUS Status; UINTN BufferSize; EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; UINT8 *Package; UINT8 *OpCodeData; UINT32 Offset; UINT32 Offset2; UINT32 PackageListLength; EFI_HII_PACKAGE_HEADER PackageHeader; EFI_HII_DATABASE_PROTOCOL *HiiDatabase; UINTN HandleBufferLength; EFI_HII_HANDLE *HiiHandleBuffer; UINTN Index; EFI_HII_HANDLE Tcg2Handle; EFI_GUID Tcg2FormGuid = { 0x6339d487, 0x26ba, 0x424b, { 0x9a, 0x5d, 0x68, 0x7e, 0x25, 0xd7, 0x40, 0xbc } }; Status = gBS->LocateProtocol(&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase); ASSERT_EFI_ERROR(Status); DEBUG((DEBUG_INFO, "Tcg2FormGuid = %g\n", &Tcg2FormGuid)); HandleBufferLength = 0; Status = HiiDatabase->ListPackageLists( HiiDatabase, EFI_HII_PACKAGE_TYPE_ALL, NULL, &HandleBufferLength, NULL ); ASSERT(Status == EFI_BUFFER_TOO_SMALL); HiiHandleBuffer = AllocateZeroPool(HandleBufferLength); if (HiiHandleBuffer == NULL) { return NULL; } Status = HiiDatabase->ListPackageLists( HiiDatabase, EFI_HII_PACKAGE_TYPE_ALL, NULL, &HandleBufferLength, HiiHandleBuffer ); ASSERT_EFI_ERROR(Status); for (Index = 0; Index < HandleBufferLength / sizeof (EFI_HII_HANDLE); Index++) { // // Get HII PackageList // BufferSize = 0; HiiPackageList = NULL; Status = HiiDatabase->ExportPackageLists ( HiiDatabase, HiiHandleBuffer[Index], &BufferSize, HiiPackageList); // // Handle is a invalid handle. Check if Handle is corrupted. // ASSERT (Status != EFI_NOT_FOUND); // // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. // ASSERT (Status == EFI_BUFFER_TOO_SMALL); HiiPackageList = AllocatePool (BufferSize); ASSERT (HiiPackageList != NULL); if (HiiPackageList == NULL) { return NULL; } Status = HiiDatabase->ExportPackageLists ( HiiDatabase, HiiHandleBuffer[Index], &BufferSize, HiiPackageList); if (EFI_ERROR (Status)) { continue; } // // Get Form package from this HII package List // PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); for ( Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER) ; Offset < PackageListLength ; Offset += PackageHeader.Length ) { Package = ((UINT8 *) HiiPackageList) + Offset; CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { // // Search FormSet Opcode in this Form Package // for ( Offset2 = sizeof (EFI_HII_PACKAGE_HEADER) ; Offset2 < PackageHeader.Length ; Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length ) { OpCodeData = Package + Offset2; if ((((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) && CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *)OpCodeData)->Guid, &Tcg2FormGuid)) { // // Find TCG FormSet // break; } } if (Offset2 < PackageHeader.Length) { break; } } } FreePool (HiiPackageList); if (Offset < PackageListLength) { break; } } if (Index < HandleBufferLength / sizeof(EFI_HII_HANDLE)) { Tcg2Handle = HiiHandleBuffer[Index]; } else { Tcg2Handle = NULL; } FreePool(HiiHandleBuffer); return Tcg2Handle; } /** Handle requests to change the Platform Trust Technology (PTT) state. If the current state differs from the requested state, a HECI message will be send to toggle the PTT state. @param[in] RequestedPttState New PTT state. 0 = Disabled, 1 = Enabled @retval EFI_SUCCESS PTT state change request sent successfully. @retval EFI_NOT_FOUND Setup data not found. **/ EFI_STATUS PttToggleState ( IN UINT8 RequestedPttState ) { EFI_STATUS Status; UINTN DataSize; TCG_SETUP TcgSetup; UINT32 TcgSetupAttr; ME_SETUP_STORAGE MeSetupStorage; UINT32 MeSetupStorageAttr; // // Load current variable values // DataSize = sizeof (TCG_SETUP); Status = gRT->GetVariable( TCG_SETUP_NAME, &gSetupVariableGuid, &TcgSetupAttr, &DataSize, &TcgSetup ); // // If TcgSetup Variable doesn't exist, return with error. // if (EFI_ERROR (Status)) { DEBUG((DEBUG_ERROR, "PttToggleState - ERROR: TCG_SETUP variable not available. Unable to read PTT current state.")); ASSERT_EFI_ERROR (Status); return Status; } // // Request changing PTT state if required // if (TcgSetup.PttPresent != RequestedPttState) { DEBUG((DEBUG_ERROR, "PttToggleState: PTT state change requested. Current: 0x%x, Requested: 0x%x", TcgSetup.PttPresent, RequestedPttState)); DataSize = sizeof (ME_SETUP_STORAGE); Status = gRT->GetVariable ( L"MeSetupStorage", &gMeSetupVariableGuid, &MeSetupStorageAttr, &DataSize, &MeSetupStorage ); ASSERT_EFI_ERROR (Status); MeSetupStorage.PttState = (BOOLEAN) RequestedPttState; Status = gRT->SetVariable ( L"MeSetupStorage", &gMeSetupVariableGuid, MeSetupStorageAttr, sizeof (ME_SETUP_STORAGE), &MeSetupStorage ); ASSERT_EFI_ERROR (Status); if (RequestedPttState == 1) { PttHeciSetState (TRUE); } else { PttHeciSetState (FALSE); } mMeReset = TRUE; } return EFI_SUCCESS; } EFI_STATUS EFIAPI TpmOptionCallback ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN EFI_BROWSER_ACTION Action, IN EFI_QUESTION_ID KeyValue, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ) /*++ Routine Description: This is the function that is called to provide results data to the driver. This data consists of a unique key which is used to identify what data is either being passed back or being asked for. Arguments: KeyValue - A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. The format of the data tends to vary based on the op-code that geerated the callback. Data - A pointer to the data being sent to the original exporting driver. Returns: --*/ { EFI_STATUS Status; EFI_HII_HANDLE TcgHandle; EFI_HII_HANDLE Tcg2Handle; EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { return EFI_UNSUPPORTED; } if (Value == NULL) { return EFI_INVALID_PARAMETER; } Status = EFI_SUCCESS; switch (KeyValue) { case KEY_TPM_GOTO: TcgHandle = GetTcgFormHandle (); if (TcgHandle != NULL) { Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); ASSERT_EFI_ERROR (Status); Status = FormBrowser2->SendForm ( FormBrowser2, &TcgHandle, 1, NULL, 0, NULL, NULL ); } break; case KEY_TPM2_GOTO: Tcg2Handle = GetTcg2FormHandle (); if (Tcg2Handle != NULL) { DEBUG((DEBUG_ERROR, "Tcg2Handle is NOT NULL, send Form")); Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); ASSERT_EFI_ERROR (Status); Status = FormBrowser2->SendForm ( FormBrowser2, &Tcg2Handle, 1, NULL, 0, NULL, NULL ); } DEBUG((DEBUG_ERROR, "Tcg2Handle is NULL!!!")); break; case KEY_PTT_DEVICE_TOGGLE: if (Action == EFI_BROWSER_ACTION_CHANGED) { PttToggleState (Value->u8); } break; }; return Status; }