Commit 3b52d699 authored by Mattias Nissler's avatar Mattias Nissler Committed by Commit Bot

Support device state preserving TPM firmware updates.

Extend the TPM firmware update code to be able to deal with different
TPM firmware update flows, represented by a newly introduced Mode
enum. In addition to the previously-existing powerwash update flow,
add a mode constant for the state preserving update flow. Change the
chrome://chrome UI to request state-preserving TPM updates if allowed.

BUG=chromium:788719
TEST=New unit tests, manual integration testing against platform functionality.

Change-Id: I7b2340b0a470d9f4bb393cde0ca01d91db3d442e
Reviewed-on: https://chromium-review.googlesource.com/1016918
Commit-Queue: Mattias Nissler <mnissler@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#561443}
parent 570ffc11
...@@ -48,10 +48,44 @@ constexpr const char kContextKeyIsTPMFirmwareUpdateChecked[] = ...@@ -48,10 +48,44 @@ constexpr const char kContextKeyIsTPMFirmwareUpdateChecked[] =
"tpm-firmware-update-checked"; "tpm-firmware-update-checked";
constexpr const char kContextKeyIsTPMFirmwareUpdateEditable[] = constexpr const char kContextKeyIsTPMFirmwareUpdateEditable[] =
"tpm-firmware-update-editable"; "tpm-firmware-update-editable";
constexpr const char kContextKeyTPMFirmwareUpdateMode[] =
"tpm-firmware-update-mode";
constexpr const char kContextKeyIsConfirmational[] = "is-confirmational-view"; constexpr const char kContextKeyIsConfirmational[] = "is-confirmational-view";
constexpr const char kContextKeyIsOfficialBuild[] = "is-official-build"; constexpr const char kContextKeyIsOfficialBuild[] = "is-official-build";
constexpr const char kContextKeyScreenState[] = "screen-state"; constexpr const char kContextKeyScreenState[] = "screen-state";
void StartTPMFirmwareUpdate(
tpm_firmware_update::Mode requested_mode,
const std::set<tpm_firmware_update::Mode>& available_modes) {
if (available_modes.count(requested_mode) == 0) {
// This should not happen, except for edge cases such as hijacked
// UI, device policy changing while the dialog was up, etc.
LOG(ERROR) << "Firmware update no longer available?";
return;
}
std::string mode_string;
switch (requested_mode) {
case tpm_firmware_update::Mode::kNone:
// Error handled below.
break;
case tpm_firmware_update::Mode::kPowerwash:
mode_string = "first_boot";
break;
case tpm_firmware_update::Mode::kPreserveDeviceState:
mode_string = "preserve_stateful";
break;
}
if (mode_string.empty()) {
LOG(ERROR) << "Invalid mode " << static_cast<int>(requested_mode);
return;
}
DBusThreadManager::Get()->GetSessionManagerClient()->StartTPMFirmwareUpdate(
mode_string);
}
} // namespace } // namespace
ResetScreen::ResetScreen(BaseScreenDelegate* base_screen_delegate, ResetScreen::ResetScreen(BaseScreenDelegate* base_screen_delegate,
...@@ -68,6 +102,8 @@ ResetScreen::ResetScreen(BaseScreenDelegate* base_screen_delegate, ...@@ -68,6 +102,8 @@ ResetScreen::ResetScreen(BaseScreenDelegate* base_screen_delegate,
context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, false); context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, false);
context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateChecked, false); context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateChecked, false);
context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateEditable, true); context_.SetBoolean(kContextKeyIsTPMFirmwareUpdateEditable, true);
context_.SetInteger(kContextKeyTPMFirmwareUpdateMode,
static_cast<int>(tpm_firmware_update::Mode::kPowerwash));
context_.SetBoolean(kContextKeyIsConfirmational, false); context_.SetBoolean(kContextKeyIsConfirmational, false);
context_.SetBoolean(kContextKeyIsOfficialBuild, false); context_.SetBoolean(kContextKeyIsOfficialBuild, false);
#if defined(OFFICIAL_BUILD) #if defined(OFFICIAL_BUILD)
...@@ -84,8 +120,9 @@ ResetScreen::~ResetScreen() { ...@@ -84,8 +120,9 @@ ResetScreen::~ResetScreen() {
// static // static
void ResetScreen::RegisterPrefs(PrefRegistrySimple* registry) { void ResetScreen::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false); registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
registry->RegisterBooleanPref(prefs::kFactoryResetTPMFirmwareUpdateRequested, registry->RegisterIntegerPref(
false); prefs::kFactoryResetTPMFirmwareUpdateMode,
static_cast<int>(tpm_firmware_update::Mode::kNone));
} }
void ResetScreen::Show() { void ResetScreen::Show() {
...@@ -126,19 +163,22 @@ void ResetScreen::Show() { ...@@ -126,19 +163,22 @@ void ResetScreen::Show() {
// Set availability of TPM firmware update. // Set availability of TPM firmware update.
PrefService* prefs = g_browser_process->local_state(); PrefService* prefs = g_browser_process->local_state();
bool tpm_firmware_update_requested = bool tpm_firmware_update_requested =
prefs->GetBoolean(prefs::kFactoryResetTPMFirmwareUpdateRequested); prefs->HasPrefPath(prefs::kFactoryResetTPMFirmwareUpdateMode);
if (tpm_firmware_update_requested) { if (tpm_firmware_update_requested) {
// If an update has been requested previously, rely on the earlier update // If an update has been requested previously, rely on the earlier update
// availability test to initialize the dialog. This avoids a race condition // availability test to initialize the dialog. This avoids a race condition
// where the powerwash dialog gets shown immediately after reboot before the // where the powerwash dialog gets shown immediately after reboot before the
// init job to determine update availability has completed. // init job to determine update availability has completed.
context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, true); context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, true);
context_editor.SetInteger(
kContextKeyTPMFirmwareUpdateMode,
prefs->GetInteger(prefs::kFactoryResetTPMFirmwareUpdateMode));
} else { } else {
// If a TPM firmware update hasn't previously been requested, check the // If a TPM firmware update hasn't previously been requested, check the
// system to see whether to offer the checkbox to update TPM firmware. Note // system to see whether to offer the checkbox to update TPM firmware. Note
// that due to the asynchronous availability check, the decision might not // that due to the asynchronous availability check, the decision might not
// be available immediately, so set a timeout of a couple seconds. // be available immediately, so set a timeout of a couple seconds.
tpm_firmware_update::ShouldOfferUpdateViaPowerwash( tpm_firmware_update::GetAvailableUpdateModes(
base::BindOnce(&ResetScreen::OnTPMFirmwareUpdateAvailableCheck, base::BindOnce(&ResetScreen::OnTPMFirmwareUpdateAvailableCheck,
weak_ptr_factory_.GetWeakPtr()), weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(10)); base::TimeDelta::FromSeconds(10));
...@@ -152,7 +192,7 @@ void ResetScreen::Show() { ...@@ -152,7 +192,7 @@ void ResetScreen::Show() {
// Clear prefs so the reset screen isn't triggered again the next time the // Clear prefs so the reset screen isn't triggered again the next time the
// device is about to show the login screen. // device is about to show the login screen.
prefs->ClearPref(prefs::kFactoryResetRequested); prefs->ClearPref(prefs::kFactoryResetRequested);
prefs->ClearPref(prefs::kFactoryResetTPMFirmwareUpdateRequested); prefs->ClearPref(prefs::kFactoryResetTPMFirmwareUpdateMode);
prefs->CommitPendingWrite(); prefs->CommitPendingWrite();
} }
...@@ -224,19 +264,11 @@ void ResetScreen::OnPowerwash() { ...@@ -224,19 +264,11 @@ void ResetScreen::OnPowerwash() {
// Re-check availability with a couple seconds timeout. This addresses the // Re-check availability with a couple seconds timeout. This addresses the
// case where the powerwash dialog gets shown immediately after reboot and // case where the powerwash dialog gets shown immediately after reboot and
// the decision on whether the update is available is not known immediately. // the decision on whether the update is available is not known immediately.
tpm_firmware_update::ShouldOfferUpdateViaPowerwash( tpm_firmware_update::GetAvailableUpdateModes(
base::BindOnce([](bool available) { base::BindOnce(
if (!available) { &StartTPMFirmwareUpdate,
// This should not happen, except for edge cases such as hijacked static_cast<tpm_firmware_update::Mode>(
// UI, device policy changing while the dialog was up, etc. context_.GetInteger(kContextKeyTPMFirmwareUpdateMode))),
LOG(ERROR) << "Firmware update no longer available?";
return;
}
DBusThreadManager::Get()
->GetSessionManagerClient()
->StartTPMFirmwareUpdate("first_boot");
}),
base::TimeDelta::FromSeconds(10)); base::TimeDelta::FromSeconds(10));
} else { } else {
VLOG(1) << "Starting Powerwash"; VLOG(1) << "Starting Powerwash";
...@@ -248,9 +280,10 @@ void ResetScreen::OnRestart() { ...@@ -248,9 +280,10 @@ void ResetScreen::OnRestart() {
PrefService* prefs = g_browser_process->local_state(); PrefService* prefs = g_browser_process->local_state();
prefs->SetBoolean(prefs::kFactoryResetRequested, true); prefs->SetBoolean(prefs::kFactoryResetRequested, true);
if (context_.GetBoolean(kContextKeyIsTPMFirmwareUpdateChecked)) { if (context_.GetBoolean(kContextKeyIsTPMFirmwareUpdateChecked)) {
prefs->SetBoolean(prefs::kFactoryResetTPMFirmwareUpdateRequested, true); prefs->SetInteger(prefs::kFactoryResetTPMFirmwareUpdateMode,
static_cast<int>(tpm_firmware_update::Mode::kPowerwash));
} else { } else {
prefs->ClearPref(prefs::kFactoryResetTPMFirmwareUpdateRequested); prefs->ClearPref(prefs::kFactoryResetTPMFirmwareUpdateMode);
} }
prefs->CommitPendingWrite(); prefs->CommitPendingWrite();
...@@ -335,9 +368,16 @@ void ResetScreen::OnRollbackCheck(bool can_rollback) { ...@@ -335,9 +368,16 @@ void ResetScreen::OnRollbackCheck(bool can_rollback) {
GetContextEditor().SetBoolean(kContextKeyIsRollbackAvailable, can_rollback); GetContextEditor().SetBoolean(kContextKeyIsRollbackAvailable, can_rollback);
} }
void ResetScreen::OnTPMFirmwareUpdateAvailableCheck(bool update_available) { void ResetScreen::OnTPMFirmwareUpdateAvailableCheck(
GetContextEditor().SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, const std::set<tpm_firmware_update::Mode>& modes) {
update_available); bool available = modes.count(tpm_firmware_update::Mode::kPowerwash) > 0;
ContextEditor context_editor = GetContextEditor();
context_editor.SetBoolean(kContextKeyIsTPMFirmwareUpdateAvailable, available);
if (available) {
context_editor.SetInteger(
kContextKeyTPMFirmwareUpdateMode,
static_cast<int>(tpm_firmware_update::Mode::kPowerwash));
}
} }
ErrorScreen* ResetScreen::GetErrorScreen() { ErrorScreen* ResetScreen::GetErrorScreen() {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_RESET_SCREEN_H_ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_RESET_SCREEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_RESET_SCREEN_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_RESET_SCREEN_H_
#include <set>
#include <string> #include <string>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
...@@ -13,6 +14,7 @@ ...@@ -13,6 +14,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/login/help_app_launcher.h" #include "chrome/browser/chromeos/login/help_app_launcher.h"
#include "chrome/browser/chromeos/login/screens/base_screen.h" #include "chrome/browser/chromeos/login/screens/base_screen.h"
#include "chrome/browser/chromeos/tpm_firmware_update.h"
#include "chromeos/dbus/update_engine_client.h" #include "chromeos/dbus/update_engine_client.h"
class PrefRegistrySimple; class PrefRegistrySimple;
...@@ -44,7 +46,8 @@ class ResetScreen : public BaseScreen, public UpdateEngineClient::Observer { ...@@ -44,7 +46,8 @@ class ResetScreen : public BaseScreen, public UpdateEngineClient::Observer {
void UpdateStatusChanged(const UpdateEngineClient::Status& status) override; void UpdateStatusChanged(const UpdateEngineClient::Status& status) override;
void OnRollbackCheck(bool can_rollback); void OnRollbackCheck(bool can_rollback);
void OnTPMFirmwareUpdateAvailableCheck(bool update_available); void OnTPMFirmwareUpdateAvailableCheck(
const std::set<tpm_firmware_update::Mode>& modes);
enum State { enum State {
STATE_RESTART_REQUIRED = 0, STATE_RESTART_REQUIRED = 0,
......
...@@ -32,18 +32,31 @@ namespace tpm_firmware_update { ...@@ -32,18 +32,31 @@ namespace tpm_firmware_update {
namespace { namespace {
// Checks whether |kSettingsKeyAllowPowerwash| is set to true in |settings|. // Checks whether |kSettingsKeyAllowPowerwash| is set to true in |settings|.
bool SettingsAllowUpdateViaPowerwash(const base::Value* settings) { std::set<Mode> GetModesFromSetting(const base::Value* settings) {
std::set<Mode> modes;
if (!settings) if (!settings)
return false; return modes;
const base::Value* const allow_powerwash = settings->FindKeyOfType( const base::Value* const allow_powerwash = settings->FindKeyOfType(
kSettingsKeyAllowPowerwash, base::Value::Type::BOOLEAN); kSettingsKeyAllowPowerwash, base::Value::Type::BOOLEAN);
return allow_powerwash && allow_powerwash->GetBool(); if (allow_powerwash && allow_powerwash->GetBool()) {
modes.insert(Mode::kPowerwash);
}
const base::Value* const allow_preserve_device_state =
settings->FindKeyOfType(kSettingsKeyAllowPreserveDeviceState,
base::Value::Type::BOOLEAN);
if (allow_preserve_device_state && allow_preserve_device_state->GetBool()) {
modes.insert(Mode::kPreserveDeviceState);
}
return modes;
} }
} // namespace } // namespace
const char kSettingsKeyAllowPowerwash[] = "allow-user-initiated-powerwash"; const char kSettingsKeyAllowPowerwash[] = "allow-user-initiated-powerwash";
const char kSettingsKeyAllowPreserveDeviceState[] =
"allow-user-initiated-preserve-device-state";
std::unique_ptr<base::DictionaryValue> DecodeSettingsProto( std::unique_ptr<base::DictionaryValue> DecodeSettingsProto(
const enterprise_management::TPMFirmwareUpdateSettingsProto& settings) { const enterprise_management::TPMFirmwareUpdateSettingsProto& settings) {
...@@ -54,6 +67,11 @@ std::unique_ptr<base::DictionaryValue> DecodeSettingsProto( ...@@ -54,6 +67,11 @@ std::unique_ptr<base::DictionaryValue> DecodeSettingsProto(
result->SetKey(kSettingsKeyAllowPowerwash, result->SetKey(kSettingsKeyAllowPowerwash,
base::Value(settings.allow_user_initiated_powerwash())); base::Value(settings.allow_user_initiated_powerwash()));
} }
if (settings.has_allow_user_initiated_preserve_device_state()) {
result->SetKey(
kSettingsKeyAllowPreserveDeviceState,
base::Value(settings.allow_user_initiated_preserve_device_state()));
}
return result; return result;
} }
...@@ -170,61 +188,77 @@ class AvailabilityChecker { ...@@ -170,61 +188,77 @@ class AvailabilityChecker {
DISALLOW_COPY_AND_ASSIGN(AvailabilityChecker); DISALLOW_COPY_AND_ASSIGN(AvailabilityChecker);
}; };
void ShouldOfferUpdateViaPowerwash( void GetAvailableUpdateModes(
base::OnceCallback<void(bool)> completion, base::OnceCallback<void(const std::set<Mode>&)> completion,
base::TimeDelta timeout) { base::TimeDelta timeout) {
// Wrap |completion| in a RepeatingCallback. This is necessary to cater to the // Wrap |completion| in a RepeatingCallback. This is necessary to cater to the
// somewhat awkward PrepareTrustedValues interface, which for some return // somewhat awkward PrepareTrustedValues interface, which for some return
// values invokes the callback passed to it, and for others requires the code // values invokes the callback passed to it, and for others requires the code
// here to do so. // here to do so.
base::RepeatingCallback<void(bool)> callback( base::RepeatingCallback<void(const std::set<Mode>&)> callback(
base::AdaptCallbackForRepeating(std::move(completion))); base::AdaptCallbackForRepeating(std::move(completion)));
if (!base::FeatureList::IsEnabled(features::kTPMFirmwareUpdate)) { if (!base::FeatureList::IsEnabled(features::kTPMFirmwareUpdate)) {
callback.Run(false); callback.Run(std::set<Mode>());
return; return;
} }
std::set<Mode> modes;
if (g_browser_process->platform_part() if (g_browser_process->platform_part()
->browser_policy_connector_chromeos() ->browser_policy_connector_chromeos()
->IsEnterpriseManaged()) { ->IsEnterpriseManaged()) {
// For enterprise-managed devices, always honor the device setting. // For enterprise-managed devices, always honor the device setting.
CrosSettings* const cros_settings = CrosSettings::Get(); CrosSettings* const cros_settings = CrosSettings::Get();
switch (cros_settings->PrepareTrustedValues( switch (cros_settings->PrepareTrustedValues(
base::Bind(&ShouldOfferUpdateViaPowerwash, callback, timeout))) { base::BindRepeating(&GetAvailableUpdateModes, callback, timeout))) {
case CrosSettingsProvider::TEMPORARILY_UNTRUSTED: case CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
// Retry happens via the callback registered above. // Retry happens via the callback registered above.
return; return;
case CrosSettingsProvider::PERMANENTLY_UNTRUSTED: case CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
// No device settings? Default to disallow. // No device settings? Default to disallow.
callback.Run(false); callback.Run(std::set<Mode>());
return; return;
case CrosSettingsProvider::TRUSTED: case CrosSettingsProvider::TRUSTED:
// Setting is present and trusted so respect its value. // Setting is present and trusted so respect its value.
if (!SettingsAllowUpdateViaPowerwash( modes = GetModesFromSetting(
cros_settings->GetPref(kTPMFirmwareUpdateSettings))) { cros_settings->GetPref(kTPMFirmwareUpdateSettings));
callback.Run(false);
return;
}
break; break;
} }
} else { } else {
// Consumer device or still in OOBE. If FRE is required, enterprise // Consumer device or still in OOBE. If FRE is required, enterprise
// enrollment might still be pending, in which case powerwash is disallowed // enrollment might still be pending, in which case TPM firmware updates are
// until FRE determines that the device is not remotely managed or it does // disallowed until FRE determines that the device is not remotely managed
// get enrolled and the admin allows TPM firmware update via powerwash. // or it does get enrolled and the admin allows TPM firmware updates.
const AutoEnrollmentController::FRERequirement requirement = const AutoEnrollmentController::FRERequirement requirement =
AutoEnrollmentController::GetFRERequirement(); AutoEnrollmentController::GetFRERequirement();
if (requirement == if (requirement ==
AutoEnrollmentController::FRERequirement::kExplicitlyRequired) { AutoEnrollmentController::FRERequirement::kExplicitlyRequired) {
callback.Run(false); callback.Run(std::set<Mode>());
return; return;
} }
// All modes are available for consumer devices.
modes.insert(Mode::kPowerwash);
modes.insert(Mode::kPreserveDeviceState);
}
// No need to check for availability if no update modes are allowed.
if (modes.empty()) {
callback.Run(std::set<Mode>());
return;
} }
// OK to offer TPM firmware update via powerwash to the user. Last thing to // Some TPM firmware update modes are allowed. Last thing to check is whether
// check is whether there actually is a pending update. // there actually is a pending update.
AvailabilityChecker::Start(callback, timeout); AvailabilityChecker::Start(
base::BindOnce(
[](std::set<Mode> modes,
base::OnceCallback<void(const std::set<Mode>&)> callback,
bool available) {
std::move(callback).Run(available ? modes : std::set<Mode>());
},
std::move(modes), callback),
timeout);
} }
} // namespace tpm_firmware_update } // namespace tpm_firmware_update
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define CHROME_BROWSER_CHROMEOS_TPM_FIRMWARE_UPDATE_H_ #define CHROME_BROWSER_CHROMEOS_TPM_FIRMWARE_UPDATE_H_
#include <memory> #include <memory>
#include <set>
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -21,18 +22,32 @@ class TPMFirmwareUpdateSettingsProto; ...@@ -21,18 +22,32 @@ class TPMFirmwareUpdateSettingsProto;
namespace chromeos { namespace chromeos {
namespace tpm_firmware_update { namespace tpm_firmware_update {
// Constants to identify the TPM firmware update modes that are supported. Do
// not re-assign constants, the numbers appear in local_state pref values.
enum class Mode : int {
// No update should take place. Used as a default in contexts where there is
// no proper value.
kNone = 0,
// Update TPM firmware via powerwash.
kPowerwash = 1,
// Device-state preserving update flow. Destroys all user data.
kPreserveDeviceState = 2,
};
// Settings dictionary key constants. // Settings dictionary key constants.
extern const char kSettingsKeyAllowPowerwash[]; extern const char kSettingsKeyAllowPowerwash[];
extern const char kSettingsKeyAllowPreserveDeviceState[];
// Decodes the TPM firmware update settings into base::Value representation. // Decodes the TPM firmware update settings into base::Value representation.
std::unique_ptr<base::DictionaryValue> DecodeSettingsProto( std::unique_ptr<base::DictionaryValue> DecodeSettingsProto(
const enterprise_management::TPMFirmwareUpdateSettingsProto& settings); const enterprise_management::TPMFirmwareUpdateSettingsProto& settings);
// Check whether the update should be offered as part of the powerwash flow. The // Check what update modes are allowed. The |timeout| parameter determines how
// |timeout| parameter determines how long to wait in case the decision whether // long to wait in case the decision whether an update is available is still
// an update is available is still pending. // pending.
void ShouldOfferUpdateViaPowerwash(base::OnceCallback<void(bool)> completion, void GetAvailableUpdateModes(
base::TimeDelta timeout); base::OnceCallback<void(const std::set<Mode>&)> completion,
base::TimeDelta timeout);
} // namespace tpm_firmware_update } // namespace tpm_firmware_update
} // namespace chromeos } // namespace chromeos
......
...@@ -388,12 +388,13 @@ void CoreOobeHandler::HandleToggleResetScreen() { ...@@ -388,12 +388,13 @@ void CoreOobeHandler::HandleToggleResetScreen() {
->IsEnterpriseManaged()) { ->IsEnterpriseManaged()) {
// Powerwash is only available if allowed by the admin specifically for the // Powerwash is only available if allowed by the admin specifically for the
// purpose of installing a TPM firmware update. // purpose of installing a TPM firmware update.
tpm_firmware_update::ShouldOfferUpdateViaPowerwash( tpm_firmware_update::GetAvailableUpdateModes(
base::BindOnce([](bool offer_update) { base::BindOnce([](const std::set<tpm_firmware_update::Mode>& modes) {
if (offer_update) { if (modes.count(tpm_firmware_update::Mode::kPowerwash) > 0) {
// Force the TPM firmware update option to be enabled. // Force the TPM firmware update option to be enabled.
g_browser_process->local_state()->SetBoolean( g_browser_process->local_state()->SetInteger(
prefs::kFactoryResetTPMFirmwareUpdateRequested, true); prefs::kFactoryResetTPMFirmwareUpdateMode,
static_cast<int>(tpm_firmware_update::Mode::kPowerwash));
LaunchResetScreen(); LaunchResetScreen();
} }
}), }),
......
...@@ -601,15 +601,16 @@ void AboutHandler::RequestUpdateOverCellular(const std::string& update_version, ...@@ -601,15 +601,16 @@ void AboutHandler::RequestUpdateOverCellular(const std::string& update_version,
void AboutHandler::HandleRefreshTPMFirmwareUpdateStatus( void AboutHandler::HandleRefreshTPMFirmwareUpdateStatus(
const base::ListValue* args) { const base::ListValue* args) {
chromeos::tpm_firmware_update::ShouldOfferUpdateViaPowerwash( chromeos::tpm_firmware_update::GetAvailableUpdateModes(
base::Bind(&AboutHandler::RefreshTPMFirmwareUpdateStatus, base::Bind(&AboutHandler::RefreshTPMFirmwareUpdateStatus,
weak_factory_.GetWeakPtr()), weak_factory_.GetWeakPtr()),
base::TimeDelta()); base::TimeDelta());
} }
void AboutHandler::RefreshTPMFirmwareUpdateStatus(bool update_available) { void AboutHandler::RefreshTPMFirmwareUpdateStatus(
const std::set<chromeos::tpm_firmware_update::Mode>& modes) {
std::unique_ptr<base::DictionaryValue> event(new base::DictionaryValue); std::unique_ptr<base::DictionaryValue> event(new base::DictionaryValue);
event->SetBoolean("updateAvailable", update_available); event->SetBoolean("updateAvailable", !modes.empty());
FireWebUIListener("tpm-firmware-update-status-changed", *event); FireWebUIListener("tpm-firmware-update-status-changed", *event);
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "base/task/cancelable_task_tracker.h" #include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/chromeos/tpm_firmware_update.h"
#include "chromeos/system/version_loader.h" #include "chromeos/system/version_loader.h"
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
...@@ -117,7 +118,8 @@ class AboutHandler : public settings::SettingsPageUIHandler, ...@@ -117,7 +118,8 @@ class AboutHandler : public settings::SettingsPageUIHandler,
// Called once when the page has loaded to retrieve the TPM firmware update // Called once when the page has loaded to retrieve the TPM firmware update
// status. // status.
void HandleRefreshTPMFirmwareUpdateStatus(const base::ListValue* args); void HandleRefreshTPMFirmwareUpdateStatus(const base::ListValue* args);
void RefreshTPMFirmwareUpdateStatus(bool update_available); void RefreshTPMFirmwareUpdateStatus(
const std::set<chromeos::tpm_firmware_update::Mode>& modes);
#endif #endif
// Checks for and applies update. // Checks for and applies update.
......
...@@ -20,6 +20,36 @@ ...@@ -20,6 +20,36 @@
namespace settings { namespace settings {
namespace {
#if defined(OS_CHROMEOS)
// Triggers a TPM firmware update using the least destructive mode from
// |available_modes|.
void TriggerTPMFirmwareUpdate(
const std::set<chromeos::tpm_firmware_update::Mode>& available_modes) {
using chromeos::tpm_firmware_update::Mode;
// Decide which update mode to use.
for (Mode mode : {Mode::kPreserveDeviceState, Mode::kPowerwash}) {
if (available_modes.count(mode) == 0) {
continue;
}
// Save a TPM firmware update request in local state, which
// will trigger the reset screen to appear on reboot.
PrefService* prefs = g_browser_process->local_state();
prefs->SetBoolean(prefs::kFactoryResetRequested, true);
prefs->SetInteger(prefs::kFactoryResetTPMFirmwareUpdateMode,
static_cast<int>(mode));
prefs->CommitPendingWrite();
chrome::AttemptRelaunch();
return;
}
}
#endif // defined(OS_CHROMEOS)
} // namespace
BrowserLifetimeHandler::BrowserLifetimeHandler() {} BrowserLifetimeHandler::BrowserLifetimeHandler() {}
BrowserLifetimeHandler::~BrowserLifetimeHandler() {} BrowserLifetimeHandler::~BrowserLifetimeHandler() {}
...@@ -66,18 +96,8 @@ void BrowserLifetimeHandler::HandleFactoryReset( ...@@ -66,18 +96,8 @@ void BrowserLifetimeHandler::HandleFactoryReset(
bool tpm_firmware_update_requested = args_list[0].GetBool(); bool tpm_firmware_update_requested = args_list[0].GetBool();
if (tpm_firmware_update_requested) { if (tpm_firmware_update_requested) {
chromeos::tpm_firmware_update::ShouldOfferUpdateViaPowerwash( chromeos::tpm_firmware_update::GetAvailableUpdateModes(
base::BindOnce([](bool offer_update) { base::BindOnce(&TriggerTPMFirmwareUpdate), base::TimeDelta());
if (!offer_update)
return;
PrefService* prefs = g_browser_process->local_state();
prefs->SetBoolean(prefs::kFactoryResetRequested, true);
prefs->SetBoolean(prefs::kFactoryResetTPMFirmwareUpdateRequested,
true);
prefs->CommitPendingWrite();
chrome::AttemptRelaunch();
}), base::TimeDelta());
return; return;
} }
......
...@@ -1910,10 +1910,10 @@ const char kTabStripStackedLayout[] = "tab-strip-stacked-layout"; ...@@ -1910,10 +1910,10 @@ const char kTabStripStackedLayout[] = "tab-strip-stacked-layout";
// Indicates that factory reset was requested from options page or reset screen. // Indicates that factory reset was requested from options page or reset screen.
const char kFactoryResetRequested[] = "FactoryResetRequested"; const char kFactoryResetRequested[] = "FactoryResetRequested";
// Indicates that a TPM firmware update should be requested when triggering a // Presence of this value indicates that a TPM firmware update has been
// factory reset. // requested. The value indicates the requested update mode.
const char kFactoryResetTPMFirmwareUpdateRequested[] = const char kFactoryResetTPMFirmwareUpdateMode[] =
"FactoryResetTPMFirmwareUpdateRequested"; "FactoryResetTPMFirmwareUpdateMode";
// Indicates that debugging features were requested from oobe screen. // Indicates that debugging features were requested from oobe screen.
const char kDebuggingFeaturesRequested[] = "DebuggingFeaturesRequested"; const char kDebuggingFeaturesRequested[] = "DebuggingFeaturesRequested";
......
...@@ -700,7 +700,7 @@ extern const char kHardwareAccelerationModePrevious[]; ...@@ -700,7 +700,7 @@ extern const char kHardwareAccelerationModePrevious[];
extern const char kDevicePolicyRefreshRate[]; extern const char kDevicePolicyRefreshRate[];
extern const char kFactoryResetRequested[]; extern const char kFactoryResetRequested[];
extern const char kFactoryResetTPMFirmwareUpdateRequested[]; extern const char kFactoryResetTPMFirmwareUpdateMode[];
extern const char kDebuggingFeaturesRequested[]; extern const char kDebuggingFeaturesRequested[];
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment