Home | History | Annotate | Download | only in DxeTcg2PhysicalPresenceLib
      1 /** @file
      2   Execute pending TPM2 requests from OS or BIOS.
      3 
      4   Caution: This module requires additional review when modified.
      5   This driver will have external input - variable.
      6   This external input must be validated carefully to avoid security issue.
      7 
      8   Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation.
      9 
     10 Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
     11 This program and the accompanying materials
     12 are licensed and made available under the terms and conditions of the BSD License
     13 which accompanies this distribution.  The full text of the license may be found at
     14 http://opensource.org/licenses/bsd-license.php
     15 
     16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     18 
     19 **/
     20 
     21 #include <PiDxe.h>
     22 
     23 #include <Protocol/Tcg2Protocol.h>
     24 #include <Protocol/VariableLock.h>
     25 #include <Library/DebugLib.h>
     26 #include <Library/BaseMemoryLib.h>
     27 #include <Library/UefiRuntimeServicesTableLib.h>
     28 #include <Library/UefiDriverEntryPoint.h>
     29 #include <Library/UefiBootServicesTableLib.h>
     30 #include <Library/UefiLib.h>
     31 #include <Library/MemoryAllocationLib.h>
     32 #include <Library/PrintLib.h>
     33 #include <Library/HiiLib.h>
     34 #include <Library/HobLib.h>
     35 #include <Guid/EventGroup.h>
     36 #include <Guid/Tcg2PhysicalPresenceData.h>
     37 #include <Library/Tpm2CommandLib.h>
     38 #include <Library/Tcg2PhysicalPresenceLib.h>
     39 #include <Library/Tcg2PpVendorLib.h>
     40 
     41 #define CONFIRM_BUFFER_SIZE         4096
     42 
     43 EFI_HII_HANDLE mTcg2PpStringPackHandle;
     44 
     45 /**
     46   Get string by string id from HII Interface.
     47 
     48   @param[in] Id          String ID.
     49 
     50   @retval    CHAR16 *    String from ID.
     51   @retval    NULL        If error occurs.
     52 
     53 **/
     54 CHAR16 *
     55 Tcg2PhysicalPresenceGetStringById (
     56   IN  EFI_STRING_ID   Id
     57   )
     58 {
     59   return HiiGetString (mTcg2PpStringPackHandle, Id, NULL);
     60 }
     61 
     62 /**
     63   Send ClearControl and Clear command to TPM.
     64 
     65   @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
     66 
     67   @retval EFI_SUCCESS           Operation completed successfully.
     68   @retval EFI_TIMEOUT           The register can't run into the expected status in time.
     69   @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.
     70   @retval EFI_DEVICE_ERROR      Unexpected device behavior.
     71 
     72 **/
     73 EFI_STATUS
     74 EFIAPI
     75 Tpm2CommandClear (
     76   IN TPM2B_AUTH                *PlatformAuth  OPTIONAL
     77   )
     78 {
     79   EFI_STATUS                Status;
     80   TPMS_AUTH_COMMAND         *AuthSession;
     81   TPMS_AUTH_COMMAND         LocalAuthSession;
     82 
     83   if (PlatformAuth == NULL) {
     84     AuthSession = NULL;
     85   } else {
     86     AuthSession = &LocalAuthSession;
     87     ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
     88     LocalAuthSession.sessionHandle = TPM_RS_PW;
     89     LocalAuthSession.hmac.size = PlatformAuth->size;
     90     CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
     91   }
     92 
     93   DEBUG ((EFI_D_INFO, "Tpm2ClearControl ... \n"));
     94   Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);
     95   DEBUG ((EFI_D_INFO, "Tpm2ClearControl - %r\n", Status));
     96   if (EFI_ERROR (Status)) {
     97     goto Done;
     98   }
     99   DEBUG ((EFI_D_INFO, "Tpm2Clear ... \n"));
    100   Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);
    101   DEBUG ((EFI_D_INFO, "Tpm2Clear - %r\n", Status));
    102 
    103 Done:
    104   ZeroMem (&LocalAuthSession.hmac, sizeof(LocalAuthSession.hmac));
    105   return Status;
    106 }
    107 
    108 /**
    109   Alloc PCR data.
    110 
    111   @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
    112   @param[in]  SupportedPCRBanks Supported PCR banks
    113   @param[in]  PCRBanks          PCR banks
    114 
    115   @retval EFI_SUCCESS Operation completed successfully.
    116 **/
    117 EFI_STATUS
    118 Tpm2CommandAllocPcr (
    119   IN TPM2B_AUTH                *PlatformAuth,  OPTIONAL
    120   IN UINT32                    SupportedPCRBanks,
    121   IN UINT32                    PCRBanks
    122   )
    123 {
    124   EFI_STATUS                Status;
    125   TPMS_AUTH_COMMAND         *AuthSession;
    126   TPMS_AUTH_COMMAND         LocalAuthSession;
    127   TPML_PCR_SELECTION        PcrAllocation;
    128   TPMI_YES_NO               AllocationSuccess;
    129   UINT32                    MaxPCR;
    130   UINT32                    SizeNeeded;
    131   UINT32                    SizeAvailable;
    132 
    133   if (PlatformAuth == NULL) {
    134     AuthSession = NULL;
    135   } else {
    136     AuthSession = &LocalAuthSession;
    137     ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
    138     LocalAuthSession.sessionHandle = TPM_RS_PW;
    139     LocalAuthSession.hmac.size = PlatformAuth->size;
    140     CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
    141   }
    142 
    143   //
    144   // Fill input
    145   //
    146   ZeroMem (&PcrAllocation, sizeof(PcrAllocation));
    147   if ((EFI_TCG2_BOOT_HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {
    148     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1;
    149     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    150     if ((EFI_TCG2_BOOT_HASH_ALG_SHA1 & PCRBanks) != 0) {
    151       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    152       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    153       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    154     } else {
    155       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    156       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    157       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    158     }
    159     PcrAllocation.count++;
    160   }
    161   if ((EFI_TCG2_BOOT_HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {
    162     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256;
    163     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    164     if ((EFI_TCG2_BOOT_HASH_ALG_SHA256 & PCRBanks) != 0) {
    165       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    166       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    167       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    168     } else {
    169       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    170       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    171       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    172     }
    173     PcrAllocation.count++;
    174   }
    175   if ((EFI_TCG2_BOOT_HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {
    176     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384;
    177     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    178     if ((EFI_TCG2_BOOT_HASH_ALG_SHA384 & PCRBanks) != 0) {
    179       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    180       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    181       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    182     } else {
    183       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    184       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    185       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    186     }
    187     PcrAllocation.count++;
    188   }
    189   if ((EFI_TCG2_BOOT_HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {
    190     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512;
    191     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    192     if ((EFI_TCG2_BOOT_HASH_ALG_SHA512 & PCRBanks) != 0) {
    193       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    194       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    195       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    196     } else {
    197       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    198       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    199       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    200     }
    201     PcrAllocation.count++;
    202   }
    203   if ((EFI_TCG2_BOOT_HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {
    204     PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256;
    205     PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
    206     if ((EFI_TCG2_BOOT_HASH_ALG_SM3_256 & PCRBanks) != 0) {
    207       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
    208       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
    209       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
    210     } else {
    211       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
    212       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
    213       PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
    214     }
    215     PcrAllocation.count++;
    216   }
    217   Status = Tpm2PcrAllocate (
    218              TPM_RH_PLATFORM,
    219              AuthSession,
    220              &PcrAllocation,
    221              &AllocationSuccess,
    222              &MaxPCR,
    223              &SizeNeeded,
    224              &SizeAvailable
    225              );
    226   DEBUG ((EFI_D_INFO, "Tpm2PcrAllocate - %r\n", Status));
    227   if (EFI_ERROR (Status)) {
    228     return Status;
    229   }
    230 
    231   DEBUG ((EFI_D_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
    232   DEBUG ((EFI_D_INFO, "MaxPCR            - %08x\n", MaxPCR));
    233   DEBUG ((EFI_D_INFO, "SizeNeeded        - %08x\n", SizeNeeded));
    234   DEBUG ((EFI_D_INFO, "SizeAvailable     - %08x\n", SizeAvailable));
    235 
    236   return EFI_SUCCESS;
    237 }
    238 
    239 /**
    240   Change EPS.
    241 
    242   @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
    243 
    244   @retval EFI_SUCCESS Operation completed successfully.
    245 **/
    246 EFI_STATUS
    247 Tpm2CommandChangeEps (
    248   IN TPM2B_AUTH                *PlatformAuth  OPTIONAL
    249   )
    250 {
    251   EFI_STATUS                Status;
    252   TPMS_AUTH_COMMAND         *AuthSession;
    253   TPMS_AUTH_COMMAND         LocalAuthSession;
    254 
    255   if (PlatformAuth == NULL) {
    256     AuthSession = NULL;
    257   } else {
    258     AuthSession = &LocalAuthSession;
    259     ZeroMem (&LocalAuthSession, sizeof(LocalAuthSession));
    260     LocalAuthSession.sessionHandle = TPM_RS_PW;
    261     LocalAuthSession.hmac.size = PlatformAuth->size;
    262     CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
    263   }
    264 
    265   Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession);
    266   DEBUG ((EFI_D_INFO, "Tpm2ChangeEPS - %r\n", Status));
    267   return Status;
    268 }
    269 
    270 /**
    271   Execute physical presence operation requested by the OS.
    272 
    273   @param[in]      PlatformAuth        platform auth value. NULL means no platform auth change.
    274   @param[in]      CommandCode         Physical presence operation value.
    275   @param[in]      CommandParameter    Physical presence operation parameter.
    276   @param[in, out] PpiFlags            The physical presence interface flags.
    277 
    278   @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Unknown physical presence operation.
    279   @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Error occurred during sending command to TPM or
    280                                                    receiving response from TPM.
    281   @retval Others                                   Return code from the TPM device after command execution.
    282 **/
    283 UINT32
    284 Tcg2ExecutePhysicalPresence (
    285   IN      TPM2B_AUTH                       *PlatformAuth,  OPTIONAL
    286   IN      UINT32                           CommandCode,
    287   IN      UINT32                           CommandParameter,
    288   IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags
    289   )
    290 {
    291   EFI_STATUS                        Status;
    292   EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
    293   EFI_TCG2_BOOT_SERVICE_CAPABILITY  ProtocolCapability;
    294 
    295   Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
    296   ASSERT_EFI_ERROR (Status);
    297 
    298   ProtocolCapability.Size = sizeof(ProtocolCapability);
    299   Status = Tcg2Protocol->GetCapability (
    300                            Tcg2Protocol,
    301                            &ProtocolCapability
    302                            );
    303   ASSERT_EFI_ERROR (Status);
    304 
    305   switch (CommandCode) {
    306     case TCG2_PHYSICAL_PRESENCE_CLEAR:
    307     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
    308     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
    309     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
    310       Status = Tpm2CommandClear (PlatformAuth);
    311       if (EFI_ERROR (Status)) {
    312         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
    313       } else {
    314         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
    315       }
    316 
    317     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
    318       PpiFlags->PPFlags |= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
    319       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
    320 
    321     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
    322       PpiFlags->PPFlags &= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
    323       return TCG_PP_OPERATION_RESPONSE_SUCCESS;
    324 
    325     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
    326       Status = Tpm2CommandAllocPcr (PlatformAuth, ProtocolCapability.HashAlgorithmBitmap, CommandParameter);
    327       if (EFI_ERROR (Status)) {
    328         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
    329       } else {
    330         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
    331       }
    332 
    333     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
    334       Status = Tpm2CommandChangeEps (PlatformAuth);
    335       if (EFI_ERROR (Status)) {
    336         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
    337       } else {
    338         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
    339       }
    340 
    341     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
    342       Status = Tpm2CommandAllocPcr (PlatformAuth, ProtocolCapability.HashAlgorithmBitmap, ProtocolCapability.HashAlgorithmBitmap);
    343       if (EFI_ERROR (Status)) {
    344         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
    345       } else {
    346         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
    347       }
    348 
    349     default:
    350       if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
    351         return TCG_PP_OPERATION_RESPONSE_SUCCESS;
    352       } else {
    353         return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
    354       }
    355   }
    356 }
    357 
    358 
    359 /**
    360   Read the specified key for user confirmation.
    361 
    362   @param[in]  CautionKey  If true,  F12 is used as confirm key;
    363                           If false, F10 is used as confirm key.
    364 
    365   @retval     TRUE        User confirmed the changes by input.
    366   @retval     FALSE       User discarded the changes.
    367 **/
    368 BOOLEAN
    369 Tcg2ReadUserKey (
    370   IN     BOOLEAN                    CautionKey
    371   )
    372 {
    373   EFI_STATUS                        Status;
    374   EFI_INPUT_KEY                     Key;
    375   UINT16                            InputKey;
    376 
    377   InputKey = 0;
    378   do {
    379     Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
    380     if (!EFI_ERROR (Status)) {
    381       Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
    382       if (Key.ScanCode == SCAN_ESC) {
    383         InputKey = Key.ScanCode;
    384       }
    385       if ((Key.ScanCode == SCAN_F10) && !CautionKey) {
    386         InputKey = Key.ScanCode;
    387       }
    388       if ((Key.ScanCode == SCAN_F12) && CautionKey) {
    389         InputKey = Key.ScanCode;
    390       }
    391     }
    392   } while (InputKey == 0);
    393 
    394   if (InputKey != SCAN_ESC) {
    395     return TRUE;
    396   }
    397 
    398   return FALSE;
    399 }
    400 
    401 /**
    402   Fill Buffer With BootHashAlg.
    403 
    404   @param[in] Buffer               Buffer to be filled.
    405   @param[in] BufferSize           Size of buffer.
    406   @param[in] BootHashAlg          BootHashAlg.
    407 
    408 **/
    409 VOID
    410 Tcg2FillBufferWithBootHashAlg (
    411   IN UINT16  *Buffer,
    412   IN UINTN   BufferSize,
    413   IN UINT32  BootHashAlg
    414   )
    415 {
    416   Buffer[0] = 0;
    417   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
    418     if (Buffer[0] != 0) {
    419       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    420     }
    421     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    422   }
    423   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
    424     if (Buffer[0] != 0) {
    425       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    426     }
    427     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    428   }
    429   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
    430     if (Buffer[0] != 0) {
    431       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    432     }
    433     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    434   }
    435   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {
    436     if (Buffer[0] != 0) {
    437       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    438     }
    439     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    440   }
    441   if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
    442     if (Buffer[0] != 0) {
    443       StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    444     }
    445     StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
    446   }
    447 }
    448 
    449 /**
    450   Display the confirm text and get user confirmation.
    451 
    452   @param[in] TpmPpCommand             The requested TPM physical presence command.
    453   @param[in] TpmPpCommandParameter    The requested TPM physical presence command parameter.
    454 
    455   @retval    TRUE          The user has confirmed the changes.
    456   @retval    FALSE         The user doesn't confirm the changes.
    457 **/
    458 BOOLEAN
    459 Tcg2UserConfirm (
    460   IN      UINT32                    TpmPpCommand,
    461   IN      UINT32                    TpmPpCommandParameter
    462   )
    463 {
    464   CHAR16                            *ConfirmText;
    465   CHAR16                            *TmpStr1;
    466   CHAR16                            *TmpStr2;
    467   UINTN                             BufSize;
    468   BOOLEAN                           CautionKey;
    469   BOOLEAN                           NoPpiInfo;
    470   UINT16                            Index;
    471   CHAR16                            DstStr[81];
    472   CHAR16                            TempBuffer[1024];
    473   CHAR16                            TempBuffer2[1024];
    474   EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
    475   EFI_TCG2_BOOT_SERVICE_CAPABILITY  ProtocolCapability;
    476   UINT32                            CurrentPCRBanks;
    477   EFI_STATUS                        Status;
    478 
    479   Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
    480   ASSERT_EFI_ERROR (Status);
    481 
    482   ProtocolCapability.Size = sizeof(ProtocolCapability);
    483   Status = Tcg2Protocol->GetCapability (
    484                            Tcg2Protocol,
    485                            &ProtocolCapability
    486                            );
    487   ASSERT_EFI_ERROR (Status);
    488 
    489   Status = Tcg2Protocol->GetActivePcrBanks (
    490                            Tcg2Protocol,
    491                            &CurrentPCRBanks
    492                            );
    493   ASSERT_EFI_ERROR (Status);
    494 
    495   TmpStr2     = NULL;
    496   CautionKey  = FALSE;
    497   NoPpiInfo   = FALSE;
    498   BufSize     = CONFIRM_BUFFER_SIZE;
    499   ConfirmText = AllocateZeroPool (BufSize);
    500   ASSERT (ConfirmText != NULL);
    501 
    502   switch (TpmPpCommand) {
    503 
    504     case TCG2_PHYSICAL_PRESENCE_CLEAR:
    505     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
    506     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
    507     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
    508       CautionKey = TRUE;
    509       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
    510 
    511       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
    512       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
    513       FreePool (TmpStr1);
    514 
    515       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
    516       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    517       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    518       FreePool (TmpStr1);
    519 
    520       break;
    521 
    522     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
    523       CautionKey = TRUE;
    524       NoPpiInfo  = TRUE;
    525       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
    526 
    527       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
    528       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
    529       FreePool (TmpStr1);
    530 
    531       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));
    532       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    533       FreePool (TmpStr1);
    534 
    535       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
    536       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    537       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    538       FreePool (TmpStr1);
    539 
    540       break;
    541 
    542     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
    543       CautionKey = TRUE;
    544       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS));
    545 
    546       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
    547       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
    548       FreePool (TmpStr1);
    549 
    550       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1));
    551       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    552       FreePool (TmpStr1);
    553 
    554       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2));
    555       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    556       FreePool (TmpStr1);
    557 
    558       Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), TpmPpCommandParameter);
    559       Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof(TempBuffer2), CurrentPCRBanks);
    560 
    561       TmpStr1 = AllocateZeroPool (BufSize);
    562       ASSERT (TmpStr1 != NULL);
    563       UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer);
    564 
    565       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    566       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    567       FreePool (TmpStr1);
    568 
    569       break;
    570 
    571     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
    572       CautionKey = TRUE;
    573       TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS));
    574 
    575       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
    576       UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
    577       FreePool (TmpStr1);
    578 
    579       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1));
    580       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    581       FreePool (TmpStr1);
    582 
    583       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2));
    584       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    585       FreePool (TmpStr1);
    586 
    587       break;
    588 
    589 
    590     default:
    591       ;
    592   }
    593 
    594   if (TmpStr2 == NULL) {
    595     FreePool (ConfirmText);
    596     return FALSE;
    597   }
    598 
    599   if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) {
    600     if (CautionKey) {
    601       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
    602     } else {
    603       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
    604     }
    605     StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    606     FreePool (TmpStr1);
    607 
    608     if (NoPpiInfo) {
    609       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
    610       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    611       FreePool (TmpStr1);
    612     }
    613 
    614     TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));
    615   } else {
    616     if (CautionKey) {
    617       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY));
    618     } else {
    619       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY));
    620     }
    621     StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    622     FreePool (TmpStr1);
    623 
    624     if (NoPpiInfo) {
    625       TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO));
    626       StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
    627       FreePool (TmpStr1);
    628     }
    629 
    630     TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY));
    631   }
    632   BufSize -= StrSize (ConfirmText);
    633   UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);
    634 
    635   DstStr[80] = L'\0';
    636   for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {
    637     StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1);
    638     Print (DstStr);
    639   }
    640 
    641   FreePool (TmpStr1);
    642   FreePool (TmpStr2);
    643   FreePool (ConfirmText);
    644 
    645   if (Tcg2ReadUserKey (CautionKey)) {
    646     return TRUE;
    647   }
    648 
    649   return FALSE;
    650 }
    651 
    652 /**
    653   Check if there is a valid physical presence command request. Also updates parameter value
    654   to whether the requested physical presence command already confirmed by user
    655 
    656    @param[in]  TcgPpData                 EFI Tcg2 Physical Presence request data.
    657    @param[in]  Flags                     The physical presence interface flags.
    658    @param[out] RequestConfirmed            If the physical presence operation command required user confirm from UI.
    659                                              True, it indicates the command doesn't require user confirm, or already confirmed
    660                                                    in last boot cycle by user.
    661                                              False, it indicates the command need user confirm from UI.
    662 
    663    @retval  TRUE        Physical Presence operation command is valid.
    664    @retval  FALSE       Physical Presence operation command is invalid.
    665 
    666 **/
    667 BOOLEAN
    668 Tcg2HaveValidTpmRequest  (
    669   IN      EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,
    670   IN      EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags,
    671   OUT     BOOLEAN                          *RequestConfirmed
    672   )
    673 {
    674   BOOLEAN  IsRequestValid;
    675 
    676   *RequestConfirmed = FALSE;
    677 
    678   switch (TcgPpData->PPRequest) {
    679     case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
    680       *RequestConfirmed = TRUE;
    681       return TRUE;
    682 
    683     case TCG2_PHYSICAL_PRESENCE_CLEAR:
    684     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
    685     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
    686     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
    687       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
    688         *RequestConfirmed = TRUE;
    689       }
    690       break;
    691 
    692     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
    693       *RequestConfirmed = TRUE;
    694       break;
    695 
    696     case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
    697       break;
    698 
    699     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
    700       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
    701         *RequestConfirmed = TRUE;
    702       }
    703       break;
    704 
    705     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
    706       if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
    707         *RequestConfirmed = TRUE;
    708       }
    709       break;
    710 
    711     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
    712       *RequestConfirmed = TRUE;
    713       break;
    714 
    715     default:
    716       if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
    717         IsRequestValid = Tcg2PpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);
    718         if (!IsRequestValid) {
    719           return FALSE;
    720         } else {
    721           break;
    722         }
    723       } else {
    724         //
    725         // Wrong Physical Presence command
    726         //
    727         return FALSE;
    728       }
    729   }
    730 
    731   if ((Flags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) != 0) {
    732     //
    733     // It had been confirmed in last boot, it doesn't need confirm again.
    734     //
    735     *RequestConfirmed = TRUE;
    736   }
    737 
    738   //
    739   // Physical Presence command is correct
    740   //
    741   return TRUE;
    742 }
    743 
    744 
    745 /**
    746   Check and execute the requested physical presence command.
    747 
    748   Caution: This function may receive untrusted input.
    749   TcgPpData variable is external input, so this function will validate
    750   its data structure to be valid value.
    751 
    752   @param[in] PlatformAuth         platform auth value. NULL means no platform auth change.
    753   @param[in] TcgPpData            Point to the physical presence NV variable.
    754   @param[in] Flags                The physical presence interface flags.
    755 **/
    756 VOID
    757 Tcg2ExecutePendingTpmRequest (
    758   IN      TPM2B_AUTH                       *PlatformAuth,  OPTIONAL
    759   IN      EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,
    760   IN      EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags
    761   )
    762 {
    763   EFI_STATUS                        Status;
    764   UINTN                             DataSize;
    765   BOOLEAN                           RequestConfirmed;
    766   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  NewFlags;
    767   BOOLEAN                           ResetRequired;
    768   UINT32                            NewPPFlags;
    769 
    770   if (TcgPpData->PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
    771     //
    772     // No operation request
    773     //
    774     return;
    775   }
    776 
    777   if (!Tcg2HaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) {
    778     //
    779     // Invalid operation request.
    780     //
    781     if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
    782       TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_SUCCESS;
    783     } else {
    784       TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
    785     }
    786     TcgPpData->LastPPRequest = TcgPpData->PPRequest;
    787     TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
    788     TcgPpData->PPRequestParameter = 0;
    789 
    790     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
    791     Status = gRT->SetVariable (
    792                     TCG2_PHYSICAL_PRESENCE_VARIABLE,
    793                     &gEfiTcg2PhysicalPresenceGuid,
    794                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    795                     DataSize,
    796                     TcgPpData
    797                     );
    798     return;
    799   }
    800 
    801   ResetRequired = FALSE;
    802   if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
    803     NewFlags = Flags;
    804     NewPPFlags = NewFlags.PPFlags;
    805     TcgPpData->PPResponse = Tcg2PpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);
    806     NewFlags.PPFlags = NewPPFlags;
    807   } else {
    808     if (!RequestConfirmed) {
    809       //
    810       // Print confirm text and wait for approval.
    811       //
    812       RequestConfirmed = Tcg2UserConfirm (TcgPpData->PPRequest, TcgPpData->PPRequestParameter);
    813     }
    814 
    815     //
    816     // Execute requested physical presence command
    817     //
    818     TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;
    819     NewFlags = Flags;
    820     if (RequestConfirmed) {
    821       TcgPpData->PPResponse = Tcg2ExecutePhysicalPresence (
    822                                 PlatformAuth,
    823                                 TcgPpData->PPRequest,
    824                                 TcgPpData->PPRequestParameter,
    825                                 &NewFlags
    826                                 );
    827     }
    828   }
    829 
    830   //
    831   // Save the flags if it is updated.
    832   //
    833   if (CompareMem (&Flags, &NewFlags, sizeof(EFI_TCG2_PHYSICAL_PRESENCE_FLAGS)) != 0) {
    834     Status   = gRT->SetVariable (
    835                       TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
    836                       &gEfiTcg2PhysicalPresenceGuid,
    837                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    838                       sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
    839                       &NewFlags
    840                       );
    841   }
    842 
    843   //
    844   // Clear request
    845   //
    846   if ((NewFlags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) == 0) {
    847     TcgPpData->LastPPRequest = TcgPpData->PPRequest;
    848     TcgPpData->PPRequest = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
    849     TcgPpData->PPRequestParameter = 0;
    850   }
    851 
    852   //
    853   // Save changes
    854   //
    855   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
    856   Status = gRT->SetVariable (
    857                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
    858                   &gEfiTcg2PhysicalPresenceGuid,
    859                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    860                   DataSize,
    861                   TcgPpData
    862                   );
    863   if (EFI_ERROR (Status)) {
    864     return;
    865   }
    866 
    867   if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {
    868     return;
    869   }
    870 
    871   //
    872   // Reset system to make new TPM settings in effect
    873   //
    874   switch (TcgPpData->LastPPRequest) {
    875     case TCG2_PHYSICAL_PRESENCE_CLEAR:
    876     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
    877     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
    878     case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
    879     case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
    880     case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
    881     case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
    882       break;
    883 
    884     default:
    885       if (TcgPpData->LastPPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
    886         if (ResetRequired) {
    887           break;
    888         } else {
    889           return ;
    890         }
    891       }
    892       if (TcgPpData->PPRequest != TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
    893         break;
    894       }
    895       return;
    896   }
    897 
    898   Print (L"Rebooting system to make TPM2 settings in effect\n");
    899   gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
    900   ASSERT (FALSE);
    901 }
    902 
    903 /**
    904   Check and execute the pending TPM request.
    905 
    906   The TPM request may come from OS or BIOS. This API will display request information and wait
    907   for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
    908   the TPM request is confirmed, and one or more reset may be required to make TPM request to
    909   take effect.
    910 
    911   This API should be invoked after console in and console out are all ready as they are required
    912   to display request information and get user input to confirm the request.
    913 
    914   @param[in]  PlatformAuth                   platform auth value. NULL means no platform auth change.
    915 **/
    916 VOID
    917 EFIAPI
    918 Tcg2PhysicalPresenceLibProcessRequest (
    919   IN      TPM2B_AUTH                     *PlatformAuth  OPTIONAL
    920   )
    921 {
    922   EFI_STATUS                        Status;
    923   UINTN                             DataSize;
    924   EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
    925   EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
    926   EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
    927   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
    928 
    929   Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
    930   if (EFI_ERROR (Status)) {
    931     return ;
    932   }
    933 
    934   //
    935   // Check S4 resume
    936   //
    937   if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
    938     DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
    939     return ;
    940   }
    941 
    942   mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, DxeTcg2PhysicalPresenceLibStrings, NULL);
    943   ASSERT (mTcg2PpStringPackHandle != NULL);
    944 
    945   //
    946   // Initialize physical presence flags.
    947   //
    948   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
    949   Status = gRT->GetVariable (
    950                   TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
    951                   &gEfiTcg2PhysicalPresenceGuid,
    952                   NULL,
    953                   &DataSize,
    954                   &PpiFlags
    955                   );
    956   if (EFI_ERROR (Status)) {
    957     PpiFlags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT;
    958     Status   = gRT->SetVariable (
    959                       TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
    960                       &gEfiTcg2PhysicalPresenceGuid,
    961                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    962                       sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
    963                       &PpiFlags
    964                       );
    965     if (EFI_ERROR (Status)) {
    966       DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));
    967       return ;
    968     }
    969   }
    970   DEBUG ((EFI_D_INFO, "[TPM2] PpiFlags = %x\n", PpiFlags.PPFlags));
    971 
    972   //
    973   // This flags variable controls whether physical presence is required for TPM command.
    974   // It should be protected from malicious software. We set it as read-only variable here.
    975   //
    976   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
    977   if (!EFI_ERROR (Status)) {
    978     Status = VariableLockProtocol->RequestToLock (
    979                                      VariableLockProtocol,
    980                                      TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
    981                                      &gEfiTcg2PhysicalPresenceGuid
    982                                      );
    983     if (EFI_ERROR (Status)) {
    984       DEBUG ((EFI_D_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
    985       ASSERT_EFI_ERROR (Status);
    986     }
    987   }
    988 
    989   //
    990   // Initialize physical presence variable.
    991   //
    992   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
    993   Status = gRT->GetVariable (
    994                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
    995                   &gEfiTcg2PhysicalPresenceGuid,
    996                   NULL,
    997                   &DataSize,
    998                   &TcgPpData
    999                   );
   1000   if (EFI_ERROR (Status)) {
   1001     ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));
   1002     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
   1003     Status   = gRT->SetVariable (
   1004                       TCG2_PHYSICAL_PRESENCE_VARIABLE,
   1005                       &gEfiTcg2PhysicalPresenceGuid,
   1006                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
   1007                       DataSize,
   1008                       &TcgPpData
   1009                       );
   1010     if (EFI_ERROR (Status)) {
   1011       DEBUG ((EFI_D_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));
   1012       return ;
   1013     }
   1014   }
   1015 
   1016   DEBUG ((EFI_D_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));
   1017 
   1018   //
   1019   // Execute pending TPM request.
   1020   //
   1021   Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, PpiFlags);
   1022   DEBUG ((EFI_D_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));
   1023 
   1024 }
   1025 
   1026 /**
   1027   Check if the pending TPM request needs user input to confirm.
   1028 
   1029   The TPM request may come from OS. This API will check if TPM request exists and need user
   1030   input to confirmation.
   1031 
   1032   @retval    TRUE        TPM needs input to confirm user physical presence.
   1033   @retval    FALSE       TPM doesn't need input to confirm user physical presence.
   1034 
   1035 **/
   1036 BOOLEAN
   1037 EFIAPI
   1038 Tcg2PhysicalPresenceLibNeedUserConfirm(
   1039   VOID
   1040   )
   1041 {
   1042   EFI_STATUS                        Status;
   1043   EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
   1044   UINTN                             DataSize;
   1045   BOOLEAN                           RequestConfirmed;
   1046   EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
   1047   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
   1048 
   1049   Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **) &Tcg2Protocol);
   1050   if (EFI_ERROR (Status)) {
   1051     return FALSE;
   1052   }
   1053 
   1054   //
   1055   // Check S4 resume
   1056   //
   1057   if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
   1058     DEBUG ((EFI_D_INFO, "S4 Resume, Skip TPM PP process!\n"));
   1059     return FALSE;
   1060   }
   1061 
   1062   //
   1063   // Check Tpm requests
   1064   //
   1065   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
   1066   Status = gRT->GetVariable (
   1067                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
   1068                   &gEfiTcg2PhysicalPresenceGuid,
   1069                   NULL,
   1070                   &DataSize,
   1071                   &TcgPpData
   1072                   );
   1073   if (EFI_ERROR (Status)) {
   1074     return FALSE;
   1075   }
   1076 
   1077   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
   1078   Status = gRT->GetVariable (
   1079                   TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
   1080                   &gEfiTcg2PhysicalPresenceGuid,
   1081                   NULL,
   1082                   &DataSize,
   1083                   &PpiFlags
   1084                   );
   1085   if (EFI_ERROR (Status)) {
   1086     return FALSE;
   1087   }
   1088 
   1089   if (TcgPpData.PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
   1090     //
   1091     // No operation request
   1092     //
   1093     return FALSE;
   1094   }
   1095 
   1096   if (!Tcg2HaveValidTpmRequest(&TcgPpData, PpiFlags, &RequestConfirmed)) {
   1097     //
   1098     // Invalid operation request.
   1099     //
   1100     return FALSE;
   1101   }
   1102 
   1103   if (!RequestConfirmed) {
   1104     //
   1105     // Need UI to confirm
   1106     //
   1107     return TRUE;
   1108   }
   1109 
   1110   return FALSE;
   1111 }
   1112 
   1113 
   1114 /**
   1115   The handler for TPM physical presence function:
   1116   Return TPM Operation Response to OS Environment.
   1117 
   1118   @param[out]     MostRecentRequest Most recent operation request.
   1119   @param[out]     Response          Response to the most recent operation request.
   1120 
   1121   @return Return Code for Return TPM Operation Response to OS Environment.
   1122 **/
   1123 UINT32
   1124 EFIAPI
   1125 Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
   1126   OUT UINT32                *MostRecentRequest,
   1127   OUT UINT32                *Response
   1128   )
   1129 {
   1130   EFI_STATUS                        Status;
   1131   UINTN                             DataSize;
   1132   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
   1133 
   1134   DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
   1135 
   1136   //
   1137   // Get the Physical Presence variable
   1138   //
   1139   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
   1140   Status = gRT->GetVariable (
   1141                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
   1142                   &gEfiTcg2PhysicalPresenceGuid,
   1143                   NULL,
   1144                   &DataSize,
   1145                   &PpData
   1146                   );
   1147   if (EFI_ERROR (Status)) {
   1148     *MostRecentRequest = 0;
   1149     *Response          = 0;
   1150     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
   1151     return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
   1152   }
   1153 
   1154   *MostRecentRequest = PpData.LastPPRequest;
   1155   *Response          = PpData.PPResponse;
   1156 
   1157   return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
   1158 }
   1159 
   1160 /**
   1161   The handler for TPM physical presence function:
   1162   Submit TPM Operation Request to Pre-OS Environment and
   1163   Submit TPM Operation Request to Pre-OS Environment 2.
   1164 
   1165   Caution: This function may receive untrusted input.
   1166 
   1167   @param[in]      OperationRequest TPM physical presence operation request.
   1168   @param[in]      RequestParameter TPM physical presence operation request parameter.
   1169 
   1170   @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
   1171           Submit TPM Operation Request to Pre-OS Environment 2.
   1172 **/
   1173 UINT32
   1174 EFIAPI
   1175 Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
   1176   IN UINT32                 OperationRequest,
   1177   IN UINT32                 RequestParameter
   1178   )
   1179 {
   1180   EFI_STATUS                        Status;
   1181   UINTN                             DataSize;
   1182   EFI_TCG2_PHYSICAL_PRESENCE        PpData;
   1183   EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
   1184 
   1185   DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));
   1186 
   1187   //
   1188   // Get the Physical Presence variable
   1189   //
   1190   DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
   1191   Status = gRT->GetVariable (
   1192                   TCG2_PHYSICAL_PRESENCE_VARIABLE,
   1193                   &gEfiTcg2PhysicalPresenceGuid,
   1194                   NULL,
   1195                   &DataSize,
   1196                   &PpData
   1197                   );
   1198   if (EFI_ERROR (Status)) {
   1199     DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
   1200     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
   1201   }
   1202 
   1203   if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
   1204       (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) ) {
   1205     //
   1206     // This command requires UI to prompt user for Auth data.
   1207     //
   1208     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
   1209   }
   1210 
   1211   if (PpData.PPRequest != OperationRequest) {
   1212     PpData.PPRequest = (UINT8)OperationRequest;
   1213     PpData.PPRequestParameter = RequestParameter;
   1214     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
   1215     Status = gRT->SetVariable (
   1216                     TCG2_PHYSICAL_PRESENCE_VARIABLE,
   1217                     &gEfiTcg2PhysicalPresenceGuid,
   1218                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
   1219                     DataSize,
   1220                     &PpData
   1221                     );
   1222   }
   1223 
   1224   if (EFI_ERROR (Status)) {
   1225     DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
   1226     return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
   1227   }
   1228 
   1229   if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
   1230     DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
   1231     Status = gRT->GetVariable (
   1232                     TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
   1233                     &gEfiTcg2PhysicalPresenceGuid,
   1234                     NULL,
   1235                     &DataSize,
   1236                     &Flags
   1237                     );
   1238     if (EFI_ERROR (Status)) {
   1239       Flags.PPFlags = TCG2_BIOS_TPM_MANAGEMENT_FLAG_DEFAULT;
   1240     }
   1241     return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter);
   1242   }
   1243 
   1244   return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
   1245 }
   1246