If false, F10 is used as confirm key.\r
\r
@retval TRUE User confirmed the changes by input.\r
- @retval FALSE User discarded the changes.\r
+ @retval FALSE User discarded the changes or device error.\r
\r
**/\r
BOOLEAN\r
EFI_STATUS Status;\r
EFI_INPUT_KEY Key;\r
UINT16 InputKey;\r
- \r
+ UINTN Index;\r
+\r
InputKey = 0; \r
do {\r
- Status = gBS->CheckEvent (gST->ConIn->WaitForKey);\r
- if (!EFI_ERROR (Status)) {\r
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
- if (Key.ScanCode == SCAN_ESC) {\r
- InputKey = Key.ScanCode;\r
- }\r
- if ((Key.ScanCode == SCAN_F10) && !CautionKey) {\r
- InputKey = Key.ScanCode;\r
- }\r
- if ((Key.ScanCode == SCAN_F12) && CautionKey) {\r
- InputKey = Key.ScanCode;\r
- }\r
- } \r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (Status == EFI_NOT_READY) {\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
+ continue;\r
+ }\r
+\r
+ if (Status == EFI_DEVICE_ERROR) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (Key.ScanCode == SCAN_ESC) {\r
+ InputKey = Key.ScanCode;\r
+ }\r
+ if ((Key.ScanCode == SCAN_F10) && !CautionKey) {\r
+ InputKey = Key.ScanCode;\r
+ }\r
+ if ((Key.ScanCode == SCAN_F12) && CautionKey) {\r
+ InputKey = Key.ScanCode;\r
+ }\r
} while (InputKey == 0);\r
\r
if (InputKey != SCAN_ESC) {\r
}\r
\r
/**\r
- Check and execute the requested physical presence command.\r
-\r
- Caution: This function may receive untrusted input.\r
- TcgPpData variable is external input, so this function will validate\r
- its data structure to be valid value.\r
-\r
- @param[in] TcgProtocol EFI TCG Protocol instance. \r
- @param[in] TcgPpData Point to the physical presence NV variable.\r
+ Check if there is a valid physical presence command request. Also updates parameter value \r
+ to whether the requested physical presence command already confirmed by user\r
+ \r
+ @param[in] TcgProtocol EFI TCG Protocol instance. \r
+ @param[out] RequestConfirmed If the physical presence operation command required user confirm from UI.\r
+ True, it indicates the command doesn't require user confirm, or already confirmed \r
+ in last boot cycle by user.\r
+ False, it indicates the command need user confirm from UI.\r
+\r
+ @retval TRUE Physical Presence operation command is valid.\r
+ @retval FALSE Physical Presence operation command is invalid.\r
\r
**/\r
-VOID\r
-ExecutePendingTpmRequest (\r
- IN EFI_TCG_PROTOCOL *TcgProtocol,\r
- IN EFI_PHYSICAL_PRESENCE *TcgPpData\r
+BOOLEAN\r
+HaveValidTpmRequest (\r
+ IN EFI_PHYSICAL_PRESENCE *TcgPpData,\r
+ OUT BOOLEAN *RequestConfirmed\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN DataSize;\r
UINT8 Flags;\r
- BOOLEAN RequestConfirmed;\r
+ \r
+ Flags = TcgPpData->Flags;\r
+ *RequestConfirmed = FALSE;\r
\r
- Flags = TcgPpData->Flags;\r
- RequestConfirmed = FALSE; \r
switch (TcgPpData->PPRequest) {\r
case PHYSICAL_PRESENCE_NO_ACTION:\r
- return;\r
+ *RequestConfirmed = TRUE;\r
+ return TRUE;\r
case PHYSICAL_PRESENCE_ENABLE:\r
case PHYSICAL_PRESENCE_DISABLE:\r
case PHYSICAL_PRESENCE_ACTIVATE:\r
case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE:\r
case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH:\r
if ((Flags & FLAG_NO_PPI_PROVISION) != 0) {\r
- RequestConfirmed = TRUE;\r
+ *RequestConfirmed = TRUE;\r
}\r
break;\r
\r
case PHYSICAL_PRESENCE_CLEAR:\r
case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR:\r
if ((Flags & FLAG_NO_PPI_CLEAR) != 0) {\r
- RequestConfirmed = TRUE;\r
+ *RequestConfirmed = TRUE;\r
}\r
break;\r
\r
case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE:\r
if ((Flags & FLAG_NO_PPI_MAINTENANCE) != 0) {\r
- RequestConfirmed = TRUE;\r
+ *RequestConfirmed = TRUE;\r
}\r
break;\r
\r
case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE:\r
case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE:\r
if ((Flags & FLAG_NO_PPI_CLEAR) != 0 && (Flags & FLAG_NO_PPI_PROVISION) != 0) {\r
- RequestConfirmed = TRUE;\r
+ *RequestConfirmed = TRUE;\r
}\r
- break; \r
+ break;\r
\r
case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE:\r
case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE:\r
case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE:\r
- RequestConfirmed = TRUE;\r
+ *RequestConfirmed = TRUE;\r
break;\r
- \r
+\r
case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE:\r
case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE:\r
case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE:\r
break;\r
- \r
+\r
default:\r
//\r
- // Invalid operation request.\r
+ // Wrong Physical Presence command\r
//\r
- TcgPpData->PPResponse = TPM_PP_BIOS_FAILURE;\r
- TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
- TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION;\r
- DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
- Status = gRT->SetVariable (\r
- PHYSICAL_PRESENCE_VARIABLE,\r
- &gEfiPhysicalPresenceGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- DataSize,\r
- TcgPpData\r
- );\r
- return;\r
+ return FALSE;\r
}\r
\r
if ((Flags & FLAG_RESET_TRACK) != 0) {\r
//\r
// It had been confirmed in last boot, it doesn't need confirm again.\r
//\r
- RequestConfirmed = TRUE;\r
+ *RequestConfirmed = TRUE;\r
+ }\r
+\r
+ //\r
+ // Physical Presence command is correct\r
+ //\r
+ return TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Check and execute the requested physical presence command.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ TcgPpData variable is external input, so this function will validate\r
+ its data structure to be valid value.\r
+\r
+ @param[in] TcgProtocol EFI TCG Protocol instance. \r
+ @param[in] TcgPpData Point to the physical presence NV variable.\r
+\r
+**/\r
+VOID\r
+ExecutePendingTpmRequest (\r
+ IN EFI_TCG_PROTOCOL *TcgProtocol,\r
+ IN EFI_PHYSICAL_PRESENCE *TcgPpData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN DataSize;\r
+ BOOLEAN RequestConfirmed;\r
+\r
+ if (TcgPpData->PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {\r
+ //\r
+ // No operation request\r
+ //\r
+ return;\r
+ }\r
+\r
+ if (!HaveValidTpmRequest(TcgPpData, &RequestConfirmed)) {\r
+ //\r
+ // Invalid operation request.\r
+ //\r
+ TcgPpData->PPResponse = TPM_PP_BIOS_FAILURE;\r
+ TcgPpData->LastPPRequest = TcgPpData->PPRequest;\r
+ TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION;\r
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+ Status = gRT->SetVariable (\r
+ PHYSICAL_PRESENCE_VARIABLE,\r
+ &gEfiPhysicalPresenceGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ DataSize,\r
+ TcgPpData\r
+ );\r
+ return;\r
}\r
\r
if (!RequestConfirmed) {\r
TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK);\r
}\r
\r
+/**\r
+ Check if the pending TPM request needs user input to confirm.\r
+\r
+ The TPM request may come from OS. This API will check if TPM request exists and need user\r
+ input to confirmation.\r
+ \r
+ @retval TRUE TPM needs input to confirm user physical presence.\r
+ @retval FALSE TPM doesn't need input to confirm user physical presence.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TcgPhysicalPresenceLibNeedUserConfirm(\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_PRESENCE TcgPpData;\r
+ UINTN DataSize;\r
+ BOOLEAN RequestConfirmed;\r
+ BOOLEAN LifetimeLock;\r
+ BOOLEAN CmdEnable;\r
+ EFI_TCG_PROTOCOL *TcgProtocol;\r
+\r
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check Tpm requests\r
+ //\r
+ DataSize = sizeof (EFI_PHYSICAL_PRESENCE);\r
+ Status = gRT->GetVariable (\r
+ PHYSICAL_PRESENCE_VARIABLE,\r
+ &gEfiPhysicalPresenceGuid,\r
+ NULL,\r
+ &DataSize,\r
+ &TcgPpData\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {\r
+ //\r
+ // No operation request\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ if (!HaveValidTpmRequest(&TcgPpData, &RequestConfirmed)) {\r
+ //\r
+ // Invalid operation request.\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Check Tpm Capability\r
+ //\r
+ Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (!CmdEnable) {\r
+ if (LifetimeLock) {\r
+ //\r
+ // physicalPresenceCMDEnable is locked, can't execute physical presence command.\r
+ //\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ if (!RequestConfirmed) {\r
+ //\r
+ // Need UI to confirm\r
+ //\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r