| /** @file | |
| The module entry point for Tcg2 configuration module. | |
| Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "Tcg2ConfigImpl.h" | |
| extern TPM_INSTANCE_ID mTpmInstanceId[TPM_DEVICE_MAX + 1]; | |
| /** | |
| Update default PCR banks data. | |
| @param[in] HiiPackage HII Package. | |
| @param[in] HiiPackageSize HII Package size. | |
| @param[in] PCRBanks PCR Banks data. | |
| **/ | |
| VOID | |
| UpdateDefaultPCRBanks ( | |
| IN VOID *HiiPackage, | |
| IN UINTN HiiPackageSize, | |
| IN UINT32 PCRBanks | |
| ) | |
| { | |
| EFI_HII_PACKAGE_HEADER *HiiPackageHeader; | |
| EFI_IFR_OP_HEADER *IfrOpCodeHeader; | |
| EFI_IFR_CHECKBOX *IfrCheckBox; | |
| EFI_IFR_DEFAULT *IfrDefault; | |
| HiiPackageHeader = (EFI_HII_PACKAGE_HEADER *)HiiPackage; | |
| switch (HiiPackageHeader->Type) { | |
| case EFI_HII_PACKAGE_FORMS: | |
| IfrOpCodeHeader = (EFI_IFR_OP_HEADER *)(HiiPackageHeader + 1); | |
| while ((UINTN)IfrOpCodeHeader < (UINTN)HiiPackageHeader + HiiPackageHeader->Length) { | |
| switch (IfrOpCodeHeader->OpCode) { | |
| case EFI_IFR_CHECKBOX_OP: | |
| IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpCodeHeader; | |
| if ((IfrCheckBox->Question.QuestionId >= KEY_TPM2_PCR_BANKS_REQUEST_0) && (IfrCheckBox->Question.QuestionId <= KEY_TPM2_PCR_BANKS_REQUEST_4)) { | |
| IfrDefault = (EFI_IFR_DEFAULT *)(IfrCheckBox + 1); | |
| ASSERT (IfrDefault->Header.OpCode == EFI_IFR_DEFAULT_OP); | |
| ASSERT (IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN); | |
| IfrDefault->Value.b = (BOOLEAN)((PCRBanks >> (IfrCheckBox->Question.QuestionId - KEY_TPM2_PCR_BANKS_REQUEST_0)) & 0x1); | |
| } | |
| break; | |
| } | |
| IfrOpCodeHeader = (EFI_IFR_OP_HEADER *)((UINTN)IfrOpCodeHeader + IfrOpCodeHeader->Length); | |
| } | |
| break; | |
| } | |
| return ; | |
| } | |
| /** | |
| Initialize TCG2 version information. | |
| This function will initialize efi varstore configuration data for | |
| TCG2_VERSION_NAME variable, check the value of related PCD with | |
| the variable value and set string for the version state content | |
| according to the PCD value. | |
| @param[in] PrivateData Points to TCG2 configuration private data. | |
| **/ | |
| VOID | |
| InitializeTcg2VersionInfo ( | |
| IN TCG2_CONFIG_PRIVATE_DATA *PrivateData | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_STRING ConfigRequestHdr; | |
| BOOLEAN ActionFlag; | |
| TCG2_VERSION Tcg2Version; | |
| UINTN DataSize; | |
| UINT64 PcdTcg2PpiVersion; | |
| UINT8 PcdTpm2AcpiTableRev; | |
| // | |
| // Get the PCD value before initializing efi varstore configuration data. | |
| // | |
| PcdTcg2PpiVersion = 0; | |
| CopyMem ( | |
| &PcdTcg2PpiVersion, | |
| PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer), | |
| AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer)) | |
| ); | |
| PcdTpm2AcpiTableRev = PcdGet8 (PcdTpm2AcpiTableRev); | |
| // | |
| // Initialize efi varstore configuration data. | |
| // | |
| ZeroMem (&Tcg2Version, sizeof (Tcg2Version)); | |
| ConfigRequestHdr = HiiConstructConfigHdr ( | |
| &gTcg2ConfigFormSetGuid, | |
| TCG2_VERSION_NAME, | |
| PrivateData->DriverHandle | |
| ); | |
| ASSERT (ConfigRequestHdr != NULL); | |
| DataSize = sizeof (Tcg2Version); | |
| Status = gRT->GetVariable ( | |
| TCG2_VERSION_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| NULL, | |
| &DataSize, | |
| &Tcg2Version | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| // | |
| // EFI variable does exist and validate current setting. | |
| // | |
| ActionFlag = HiiValidateSettings (ConfigRequestHdr); | |
| if (!ActionFlag) { | |
| // | |
| // Current configuration is invalid, reset to defaults. | |
| // | |
| ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD); | |
| ASSERT (ActionFlag); | |
| // | |
| // Get the default values from variable. | |
| // | |
| DataSize = sizeof (Tcg2Version); | |
| Status = gRT->GetVariable ( | |
| TCG2_VERSION_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| NULL, | |
| &DataSize, | |
| &Tcg2Version | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| } | |
| } else { | |
| // | |
| // EFI variable doesn't exist or variable size is not expected. | |
| // | |
| // | |
| // Store zero data Buffer Storage to EFI variable. | |
| // | |
| Status = gRT->SetVariable ( | |
| TCG2_VERSION_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, | |
| sizeof (Tcg2Version), | |
| &Tcg2Version | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| DEBUG ((DEBUG_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_VERSION_NAME\n")); | |
| return; | |
| } else { | |
| // | |
| // Build this variable based on default values stored in IFR. | |
| // | |
| ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD); | |
| ASSERT (ActionFlag); | |
| // | |
| // Get the default values from variable. | |
| // | |
| DataSize = sizeof (Tcg2Version); | |
| Status = gRT->GetVariable ( | |
| TCG2_VERSION_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| NULL, | |
| &DataSize, | |
| &Tcg2Version | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| if (PcdTcg2PpiVersion != Tcg2Version.PpiVersion) { | |
| DEBUG ((DEBUG_WARN, "WARNING: PcdTcgPhysicalPresenceInterfaceVer default value is not same with the default value in VFR\n")); | |
| DEBUG ((DEBUG_WARN, "WARNING: The default value in VFR has be chosen\n")); | |
| } | |
| if (PcdTpm2AcpiTableRev != Tcg2Version.Tpm2AcpiTableRev) { | |
| DEBUG ((DEBUG_WARN, "WARNING: PcdTpm2AcpiTableRev default value is not same with the default value in VFR\n")); | |
| DEBUG ((DEBUG_WARN, "WARNING: The default value in VFR has be chosen\n")); | |
| } | |
| } | |
| } | |
| FreePool (ConfigRequestHdr); | |
| // | |
| // Get the PCD value again. | |
| // If the PCD value is not equal to the value in variable, | |
| // the PCD is not DynamicHii type and does not map to the setup option. | |
| // | |
| PcdTcg2PpiVersion = 0; | |
| CopyMem ( | |
| &PcdTcg2PpiVersion, | |
| PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer), | |
| AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer)) | |
| ); | |
| if (PcdTcg2PpiVersion != Tcg2Version.PpiVersion) { | |
| DEBUG ((DEBUG_WARN, "WARNING: PcdTcgPhysicalPresenceInterfaceVer is not DynamicHii type and does not map to TCG2_VERSION.PpiVersion\n")); | |
| DEBUG ((DEBUG_WARN, "WARNING: The TCG2 PPI version configuring from setup page will not work\n")); | |
| } | |
| switch (PcdTcg2PpiVersion) { | |
| case TCG2_PPI_VERSION_1_2: | |
| HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_PPI_VERSION_STATE_CONTENT), L"1.2", NULL); | |
| break; | |
| case TCG2_PPI_VERSION_1_3: | |
| HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TCG2_PPI_VERSION_STATE_CONTENT), L"1.3", NULL); | |
| break; | |
| default: | |
| ASSERT (FALSE); | |
| break; | |
| } | |
| // | |
| // Get the PcdTpm2AcpiTableRev value again. | |
| // If the PCD value is not equal to the value in variable, | |
| // the PCD is not DynamicHii type and does not map to TCG2_VERSION Variable. | |
| // | |
| PcdTpm2AcpiTableRev = PcdGet8 (PcdTpm2AcpiTableRev); | |
| if (PcdTpm2AcpiTableRev != Tcg2Version.Tpm2AcpiTableRev) { | |
| DEBUG ((DEBUG_WARN, "WARNING: PcdTpm2AcpiTableRev is not DynamicHii type and does not map to TCG2_VERSION.Tpm2AcpiTableRev\n")); | |
| DEBUG ((DEBUG_WARN, "WARNING: The Tpm2 ACPI Revision configuring from setup page will not work\n")); | |
| } | |
| switch (PcdTpm2AcpiTableRev) { | |
| case EFI_TPM2_ACPI_TABLE_REVISION_3: | |
| HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_ACPI_REVISION_STATE_CONTENT), L"Rev 3", NULL); | |
| break; | |
| case EFI_TPM2_ACPI_TABLE_REVISION_4: | |
| HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_ACPI_REVISION_STATE_CONTENT), L"Rev 4", NULL); | |
| break; | |
| default: | |
| ASSERT (FALSE); | |
| break; | |
| } | |
| } | |
| /** | |
| The entry point for Tcg2 configuration driver. | |
| @param[in] ImageHandle The image handle of the driver. | |
| @param[in] SystemTable The system table. | |
| @retval EFI_ALREADY_STARTED The driver already exists in system. | |
| @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of resources. | |
| @retval EFI_SUCCES All the related protocols are installed on the driver. | |
| @retval Others Fail to install protocols as indicated. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| Tcg2ConfigDriverEntryPoint ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| TCG2_CONFIG_PRIVATE_DATA *PrivateData; | |
| TCG2_CONFIGURATION Tcg2Configuration; | |
| TCG2_DEVICE_DETECTION Tcg2DeviceDetection; | |
| UINTN Index; | |
| UINTN DataSize; | |
| EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol; | |
| UINT32 CurrentActivePCRBanks; | |
| Status = gBS->OpenProtocol ( | |
| ImageHandle, | |
| &gEfiCallerIdGuid, | |
| NULL, | |
| ImageHandle, | |
| ImageHandle, | |
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| return EFI_ALREADY_STARTED; | |
| } | |
| // | |
| // Create a private data structure. | |
| // | |
| PrivateData = AllocateCopyPool (sizeof (TCG2_CONFIG_PRIVATE_DATA), &mTcg2ConfigPrivateDateTemplate); | |
| ASSERT (PrivateData != NULL); | |
| mTcg2ConfigPrivateDate = PrivateData; | |
| // | |
| // Install private GUID. | |
| // | |
| Status = gBS->InstallMultipleProtocolInterfaces ( | |
| &ImageHandle, | |
| &gEfiCallerIdGuid, | |
| PrivateData, | |
| NULL | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &PrivateData->Tcg2Protocol); | |
| ASSERT_EFI_ERROR (Status); | |
| PrivateData->ProtocolCapability.Size = sizeof(PrivateData->ProtocolCapability); | |
| Status = PrivateData->Tcg2Protocol->GetCapability ( | |
| PrivateData->Tcg2Protocol, | |
| &PrivateData->ProtocolCapability | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| DataSize = sizeof(Tcg2Configuration); | |
| Status = gRT->GetVariable ( | |
| TCG2_STORAGE_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| NULL, | |
| &DataSize, | |
| &Tcg2Configuration | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // Variable not ready, set default value | |
| // | |
| Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT; | |
| } | |
| // | |
| // Validation | |
| // | |
| if ((Tcg2Configuration.TpmDevice > TPM_DEVICE_MAX) || (Tcg2Configuration.TpmDevice < TPM_DEVICE_MIN)) { | |
| Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT; | |
| } | |
| // | |
| // Set value for Tcg2CurrentActivePCRBanks | |
| // Search Tcg2ConfigBin[] and update default value there | |
| // | |
| Status = PrivateData->Tcg2Protocol->GetActivePcrBanks (PrivateData->Tcg2Protocol, &CurrentActivePCRBanks); | |
| ASSERT_EFI_ERROR (Status); | |
| PrivateData->PCRBanksDesired = CurrentActivePCRBanks; | |
| UpdateDefaultPCRBanks (Tcg2ConfigBin + sizeof(UINT32), ReadUnaligned32((UINT32 *)Tcg2ConfigBin) - sizeof(UINT32), CurrentActivePCRBanks); | |
| // | |
| // Sync data from PCD to variable, so that we do not need detect again in S3 phase. | |
| // | |
| Tcg2DeviceDetection.TpmDeviceDetected = TPM_DEVICE_NULL; | |
| for (Index = 0; Index < sizeof(mTpmInstanceId)/sizeof(mTpmInstanceId[0]); Index++) { | |
| if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &mTpmInstanceId[Index].TpmInstanceGuid)) { | |
| Tcg2DeviceDetection.TpmDeviceDetected = mTpmInstanceId[Index].TpmDevice; | |
| break; | |
| } | |
| } | |
| PrivateData->TpmDeviceDetected = Tcg2DeviceDetection.TpmDeviceDetected; | |
| Tcg2Configuration.TpmDevice = Tcg2DeviceDetection.TpmDeviceDetected; | |
| // | |
| // Save to variable so platform driver can get it. | |
| // | |
| Status = gRT->SetVariable ( | |
| TCG2_DEVICE_DETECTION_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, | |
| sizeof(Tcg2DeviceDetection), | |
| &Tcg2DeviceDetection | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_DEVICE_DETECTION_NAME\n")); | |
| Status = gRT->SetVariable ( | |
| TCG2_DEVICE_DETECTION_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, | |
| 0, | |
| NULL | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| } | |
| // | |
| // Save to variable so platform driver can get it. | |
| // | |
| Status = gRT->SetVariable ( | |
| TCG2_STORAGE_NAME, | |
| &gTcg2ConfigFormSetGuid, | |
| EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, | |
| sizeof(Tcg2Configuration), | |
| &Tcg2Configuration | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| DEBUG ((EFI_D_ERROR, "Tcg2ConfigDriver: Fail to set TCG2_STORAGE_NAME\n")); | |
| } | |
| // | |
| // We should lock Tcg2DeviceDetection, because it contains information needed at S3. | |
| // | |
| Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol); | |
| if (!EFI_ERROR (Status)) { | |
| Status = VariableLockProtocol->RequestToLock ( | |
| VariableLockProtocol, | |
| TCG2_DEVICE_DETECTION_NAME, | |
| &gTcg2ConfigFormSetGuid | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| } | |
| // | |
| // Install Tcg2 configuration form | |
| // | |
| Status = InstallTcg2ConfigForm (PrivateData); | |
| if (EFI_ERROR (Status)) { | |
| goto ErrorExit; | |
| } | |
| InitializeTcg2VersionInfo (PrivateData); | |
| return EFI_SUCCESS; | |
| ErrorExit: | |
| if (PrivateData != NULL) { | |
| UninstallTcg2ConfigForm (PrivateData); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Unload the Tcg2 configuration form. | |
| @param[in] ImageHandle The driver's image handle. | |
| @retval EFI_SUCCESS The Tcg2 configuration form is unloaded. | |
| @retval Others Failed to unload the form. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| Tcg2ConfigDriverUnload ( | |
| IN EFI_HANDLE ImageHandle | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| TCG2_CONFIG_PRIVATE_DATA *PrivateData; | |
| Status = gBS->HandleProtocol ( | |
| ImageHandle, | |
| &gEfiCallerIdGuid, | |
| (VOID **) &PrivateData | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| ASSERT (PrivateData->Signature == TCG2_CONFIG_PRIVATE_DATA_SIGNATURE); | |
| gBS->UninstallMultipleProtocolInterfaces ( | |
| &ImageHandle, | |
| &gEfiCallerIdGuid, | |
| PrivateData, | |
| NULL | |
| ); | |
| UninstallTcg2ConfigForm (PrivateData); | |
| return EFI_SUCCESS; | |
| } |