/** Check and execute the requested physical presence command. Caution: This function may receive untrusted input. TcgPpData variable is external input, so this function will validate its data structure to be valid value. @param[in] TcgProtocol EFI TCG Protocol instance. @param[in] TcgPpData Point to the physical presence NV variable. @param[in] Flags The physical presence interface flags. **/ VOID ExecutePendingTpmRequest ( IN EFI_TCG_PROTOCOL *TcgProtocol, IN EFI_PHYSICAL_PRESENCE *TcgPpData, IN UINT8 Flags ) { EFI_STATUS Status; UINTN DataSize; BOOLEAN RequestConfirmed; UINT8 NewFlags; if (!HaveValidTpmRequest(TcgPpData, Flags, &RequestConfirmed)) { // // Invalid operation request. // TcgPpData->PPResponse = TPM_PP_BIOS_FAILURE; TcgPpData->LastPPRequest = TcgPpData->PPRequest; TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION; DataSize = sizeof (EFI_PHYSICAL_PRESENCE); Status = gRT->SetVariable ( PHYSICAL_PRESENCE_VARIABLE, &gEfiPhysicalPresenceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, DataSize, TcgPpData ); return; } if (!RequestConfirmed) { // // Print confirm text and wait for approval. // RequestConfirmed = UserConfirm (TcgPpData->PPRequest); } // // Execute requested physical presence command // TcgPpData->PPResponse = TPM_PP_USER_ABORT; NewFlags = Flags; if (RequestConfirmed) { TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &NewFlags); } // // Save the flags if it is updated. // if (Flags != NewFlags) { Status = gRT->SetVariable ( PHYSICAL_PRESENCE_FLAGS_VARIABLE, &gEfiPhysicalPresenceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (UINT8), &NewFlags ); if (EFI_ERROR (Status)) { return; } } // // Clear request // if ((NewFlags & FLAG_RESET_TRACK) == 0) { TcgPpData->LastPPRequest = TcgPpData->PPRequest; TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION; } // // Save changes // DataSize = sizeof (EFI_PHYSICAL_PRESENCE); Status = gRT->SetVariable ( PHYSICAL_PRESENCE_VARIABLE, &gEfiPhysicalPresenceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, DataSize, TcgPpData ); if (EFI_ERROR (Status)) { return; } if (TcgPpData->PPResponse == TPM_PP_USER_ABORT) { return; } // // Reset system to make new TPM settings in effect // switch (TcgPpData->LastPPRequest) { case PHYSICAL_PRESENCE_ACTIVATE: case PHYSICAL_PRESENCE_DEACTIVATE: case PHYSICAL_PRESENCE_CLEAR: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: break; default: if (TcgPpData->PPRequest != PHYSICAL_PRESENCE_NO_ACTION) { break; } return; } Print (L"Rebooting system to make TPM settings in effect\n"); gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); ASSERT (FALSE); }
/** Execute physical presence operation requested by the OS. @param[in] TcgProtocol EFI TCG Protocol instance. @param[in] CommandCode Physical presence operation value. @param[in, out] PpiFlags The physical presence interface flags. @retval TPM_PP_BIOS_FAILURE Unknown physical presence operation. @retval TPM_PP_BIOS_FAILURE Error occurred during sending command to TPM or receiving response from TPM. @retval Others Return code from the TPM device after command execution. **/ TPM_RESULT ExecutePhysicalPresence ( IN EFI_TCG_PROTOCOL *TcgProtocol, IN UINT8 CommandCode, IN OUT UINT8 *PpiFlags ) { BOOLEAN BoolVal; TPM_RESULT TpmResponse; UINT32 InData[5]; switch (CommandCode) { case PHYSICAL_PRESENCE_ENABLE: return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_PhysicalEnable, 0, NULL ); case PHYSICAL_PRESENCE_DISABLE: return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_PhysicalDisable, 0, NULL ); case PHYSICAL_PRESENCE_ACTIVATE: BoolVal = FALSE; return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_PhysicalSetDeactivated, sizeof (BoolVal), &BoolVal ); case PHYSICAL_PRESENCE_DEACTIVATE: BoolVal = TRUE; return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_PhysicalSetDeactivated, sizeof (BoolVal), &BoolVal ); case PHYSICAL_PRESENCE_CLEAR: return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_ForceClear, 0, NULL ); case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE, PpiFlags); if (TpmResponse == 0) { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ACTIVATE, PpiFlags); } return TpmResponse; case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DEACTIVATE, PpiFlags); if (TpmResponse == 0) { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DISABLE, PpiFlags); } return TpmResponse; case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE: BoolVal = TRUE; return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_SetOwnerInstall, sizeof (BoolVal), &BoolVal ); case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE: BoolVal = FALSE; return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_SetOwnerInstall, sizeof (BoolVal), &BoolVal ); case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: // // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE // PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE will be executed after reboot // if ((*PpiFlags & FLAG_RESET_TRACK) == 0) { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); *PpiFlags |= FLAG_RESET_TRACK; } else { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE, PpiFlags); *PpiFlags &= ~FLAG_RESET_TRACK; } return TpmResponse; case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE, PpiFlags); if (TpmResponse == 0) { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_DEACTIVATE_DISABLE, PpiFlags); } return TpmResponse; case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: InData[0] = SwapBytes32 (TPM_SET_STCLEAR_DATA); // CapabilityArea InData[1] = SwapBytes32 (sizeof(UINT32)); // SubCapSize InData[2] = SwapBytes32 (TPM_SD_DEFERREDPHYSICALPRESENCE); // SubCap InData[3] = SwapBytes32 (sizeof(UINT32)); // SetValueSize InData[4] = SwapBytes32 (1); // UnownedFieldUpgrade; bit0 return TpmCommandNoReturnData ( TcgProtocol, TPM_ORD_SetCapability, sizeof (UINT32) * 5, InData ); case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH: // // TPM_SetOperatorAuth // This command requires UI to prompt user for Auth data // Here it is NOT implemented // return TPM_PP_BIOS_FAILURE; case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR, PpiFlags); if (TpmResponse == 0) { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); } return TpmResponse; case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE: *PpiFlags &= ~FLAG_NO_PPI_PROVISION; return 0; case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_TRUE: *PpiFlags |= FLAG_NO_PPI_PROVISION; return 0; case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE: *PpiFlags &= ~FLAG_NO_PPI_CLEAR; return 0; case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_TRUE: *PpiFlags |= FLAG_NO_PPI_CLEAR; return 0; case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE: *PpiFlags &= ~FLAG_NO_PPI_MAINTENANCE; return 0; case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_TRUE: *PpiFlags |= FLAG_NO_PPI_MAINTENANCE; return 0; case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: // // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_CLEAR // PHYSICAL_PRESENCE_CLEAR will be executed after reboot. // if ((*PpiFlags & FLAG_RESET_TRACK) == 0) { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); *PpiFlags |= FLAG_RESET_TRACK; } else { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR, PpiFlags); *PpiFlags &= ~FLAG_RESET_TRACK; } return TpmResponse; case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: // // PHYSICAL_PRESENCE_ENABLE_ACTIVATE + PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE // PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE will be executed after reboot. // if ((*PpiFlags & FLAG_RESET_TRACK) == 0) { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_ENABLE_ACTIVATE, PpiFlags); *PpiFlags |= FLAG_RESET_TRACK; } else { TpmResponse = ExecutePhysicalPresence (TcgProtocol, PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE, PpiFlags); *PpiFlags &= ~FLAG_RESET_TRACK; } return TpmResponse; default: ; } return TPM_PP_BIOS_FAILURE; }
/** Check and execute the requested physical presence command. Caution: This function may receive untrusted input. TcgPpData variable is external input, so this function will validate its data structure to be valid value. @param[in] TcgProtocol EFI TCG Protocol instance. @param[in] TcgPpData Point to the physical presence NV variable. **/ VOID ExecutePendingTpmRequest ( IN EFI_TCG_PROTOCOL *TcgProtocol, IN EFI_PHYSICAL_PRESENCE *TcgPpData ) { EFI_STATUS Status; UINTN DataSize; UINT8 Flags; BOOLEAN RequestConfirmed; Flags = TcgPpData->Flags; RequestConfirmed = FALSE; switch (TcgPpData->PPRequest) { case PHYSICAL_PRESENCE_NO_ACTION: return; case PHYSICAL_PRESENCE_ENABLE: case PHYSICAL_PRESENCE_DISABLE: case PHYSICAL_PRESENCE_ACTIVATE: case PHYSICAL_PRESENCE_DEACTIVATE: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_TRUE: case PHYSICAL_PRESENCE_SET_OWNER_INSTALL_FALSE: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: case PHYSICAL_PRESENCE_SET_OPERATOR_AUTH: if ((Flags & FLAG_NO_PPI_PROVISION) != 0) { RequestConfirmed = TRUE; } break; case PHYSICAL_PRESENCE_CLEAR: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: if ((Flags & FLAG_NO_PPI_CLEAR) != 0) { RequestConfirmed = TRUE; } break; case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: if ((Flags & FLAG_NO_PPI_MAINTENANCE) != 0) { RequestConfirmed = TRUE; } break; case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: if ((Flags & FLAG_NO_PPI_CLEAR) != 0 && (Flags & FLAG_NO_PPI_PROVISION) != 0) { RequestConfirmed = TRUE; } break; case PHYSICAL_PRESENCE_SET_NO_PPI_PROVISION_FALSE: case PHYSICAL_PRESENCE_SET_NO_PPI_CLEAR_FALSE: case PHYSICAL_PRESENCE_SET_NO_PPI_MAINTENANCE_FALSE: RequestConfirmed = TRUE; break; default: // // Invalid operation request. // TcgPpData->PPResponse = TPM_PP_BIOS_FAILURE; TcgPpData->LastPPRequest = TcgPpData->PPRequest; TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION; DataSize = sizeof (EFI_PHYSICAL_PRESENCE); Status = gRT->SetVariable ( PHYSICAL_PRESENCE_VARIABLE, &gEfiPhysicalPresenceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, DataSize, TcgPpData ); return; } if ((Flags & FLAG_RESET_TRACK) != 0) { // // It had been confirmed in last boot, it doesn't need confirm again. // RequestConfirmed = TRUE; } if (!RequestConfirmed) { // // Print confirm text and wait for approval. // RequestConfirmed = UserConfirm (TcgPpData->PPRequest); } // // Execute requested physical presence command // TcgPpData->PPResponse = TPM_PP_USER_ABORT; if (RequestConfirmed) { TcgPpData->PPResponse = ExecutePhysicalPresence (TcgProtocol, TcgPpData->PPRequest, &TcgPpData->Flags); } // // Clear request // if ((TcgPpData->Flags & FLAG_RESET_TRACK) == 0) { TcgPpData->LastPPRequest = TcgPpData->PPRequest; TcgPpData->PPRequest = PHYSICAL_PRESENCE_NO_ACTION; } // // Save changes // DataSize = sizeof (EFI_PHYSICAL_PRESENCE); Status = gRT->SetVariable ( PHYSICAL_PRESENCE_VARIABLE, &gEfiPhysicalPresenceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, DataSize, TcgPpData ); if (EFI_ERROR (Status)) { return; } if (TcgPpData->PPResponse == TPM_PP_USER_ABORT) { return; } // // Reset system to make new TPM settings in effect // switch (TcgPpData->LastPPRequest) { case PHYSICAL_PRESENCE_ACTIVATE: case PHYSICAL_PRESENCE_DEACTIVATE: case PHYSICAL_PRESENCE_CLEAR: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE: case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_OWNER_TRUE: case PHYSICAL_PRESENCE_DEACTIVATE_DISABLE_OWNER_FALSE: case PHYSICAL_PRESENCE_DEFERRED_PP_UNOWNERED_FIELD_UPGRADE: case PHYSICAL_PRESENCE_CLEAR_ENABLE_ACTIVATE: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR: case PHYSICAL_PRESENCE_ENABLE_ACTIVATE_CLEAR_ENABLE_ACTIVATE: break; default: if (TcgPpData->PPRequest != PHYSICAL_PRESENCE_NO_ACTION) { break; } return; } Print (L"Rebooting system to make TPM settings in effect\n"); gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); ASSERT (FALSE); }