/** @file
  The module entry point for Tcg2 configuration module.

Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#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_SUCCESS            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 ((DEBUG_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 ((DEBUG_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;
}
