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