blob: f2664f508550931d08f51f0cd8da88b9cc4281aa [file] [log] [blame]
// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rmad/state_handler/wipe_selection_state_handler.h"
#include <memory>
#include <utility>
#include <base/files/file_path.h>
#include <base/logging.h>
#include "rmad/constants.h"
#include "rmad/utils/cr50_utils_impl.h"
#include "rmad/utils/crossystem_utils_impl.h"
#include "rmad/utils/fake_cr50_utils.h"
#include "rmad/utils/fake_crossystem_utils.h"
namespace rmad {
namespace fake {
FakeWipeSelectionStateHandler::FakeWipeSelectionStateHandler(
scoped_refptr<JsonStore> json_store, const base::FilePath& working_dir_path)
: WipeSelectionStateHandler(
json_store,
std::make_unique<FakeCr50Utils>(working_dir_path),
std::make_unique<FakeCrosSystemUtils>(working_dir_path)) {}
} // namespace fake
WipeSelectionStateHandler::WipeSelectionStateHandler(
scoped_refptr<JsonStore> json_store)
: BaseStateHandler(json_store) {
cr50_utils_ = std::make_unique<Cr50UtilsImpl>();
crossystem_utils_ = std::make_unique<CrosSystemUtilsImpl>();
}
WipeSelectionStateHandler::WipeSelectionStateHandler(
scoped_refptr<JsonStore> json_store,
std::unique_ptr<Cr50Utils> cr50_utils,
std::unique_ptr<CrosSystemUtils> crossystem_utils)
: BaseStateHandler(json_store),
cr50_utils_(std::move(cr50_utils)),
crossystem_utils_(std::move(crossystem_utils)) {}
RmadErrorCode WipeSelectionStateHandler::InitializeState() {
if (!state_.has_wipe_selection()) {
state_.set_allocated_wipe_selection(new WipeSelectionState);
}
if (!InitializeVarsFromStateFile()) {
return RMAD_ERROR_STATE_HANDLER_INITIALIZATION_FAILED;
}
return RMAD_ERROR_OK;
}
bool WipeSelectionStateHandler::InitializeVarsFromStateFile() {
// json_store should contain the following keys set by |DeviceDestination|:
// - kSameOwner
// - kWpDisableRequired
// - kCcdBlocked (only required when kWpDisableRequired is true)
bool same_owner;
if (!json_store_->GetValue(kSameOwner, &same_owner)) {
LOG(ERROR) << "Variable " << kSameOwner << " not found";
return false;
}
if (!json_store_->GetValue(kWpDisableRequired, &wp_disable_required_)) {
LOG(ERROR) << "Variable " << kWpDisableRequired << " not found";
return false;
}
if (wp_disable_required_ &&
!json_store_->GetValue(kCcdBlocked, &ccd_blocked_)) {
LOG(ERROR) << "Variable " << kCcdBlocked << " not found";
return false;
}
// We should not see "different owner" in this state, because we always wipe
// the device if it's going to a different owner.
if (!same_owner) {
LOG(ERROR) << "Device is going to a different owner. "
<< "We should always wipe the device";
return false;
}
return true;
}
BaseStateHandler::GetNextStateCaseReply
WipeSelectionStateHandler::GetNextStateCase(const RmadState& state) {
if (!state.has_wipe_selection()) {
LOG(ERROR) << "RmadState missing |wipe selection| state.";
return NextStateCaseWrapper(RMAD_ERROR_REQUEST_INVALID);
}
state_ = state;
// There are 5 paths:
// 1. Same owner + WP disabling required + CCD blocked + wipe device:
// Go to kWpDisableRsu state.
// 2. Same owner + Wp disabling required + CCD blocked + don't wipe device:
// Go to kWpDisablePhysical state.
// 3. Same owner + WP disabling required + CCD not blocked + wipe device:
// Go to kWpDisableMethod state.
// 4. Same owner + WP disabling required + CCD not blocked + don't wipe
// device:
// Go to kWpDisablePhysical state.
// 5. Same owner + WP disabling not required:
// Go to kFinalize state.
bool wipe_device = state_.wipe_selection().wipe_device();
json_store_->SetValue(kWipeDevice, wipe_device);
RmadState::StateCase next_state = RmadState::StateCase::STATE_NOT_SET;
if (wp_disable_required_) {
if (cr50_utils_->IsFactoryModeEnabled()) {
// Skip WP disabling steps if factory mode is already turned on.
json_store_->SetValue(kWpDisableSkipped, true);
json_store_->SetValue(
kWriteProtectDisableMethod,
static_cast<int>(WriteProtectDisableMethod::SKIPPED));
next_state = RmadState::StateCase::kWpDisableComplete;
} else if (ccd_blocked_) {
if (wipe_device) {
// Case 1.
next_state = RmadState::StateCase::kWpDisableRsu;
} else {
// Case 2.
next_state = RmadState::StateCase::kWpDisablePhysical;
}
} else {
if (wipe_device) {
// Case 3.
// If HWWP is already disabled, assume the user will select the physical
// method and go directly to WpDisablePhysical state. Otherwise, let the
// user choose between physical method or RSU.
if (int hwwp_status; crossystem_utils_->GetHwwpStatus(&hwwp_status) &&
hwwp_status == 0) {
next_state = RmadState::StateCase::kWpDisablePhysical;
} else {
next_state = RmadState::StateCase::kWpDisableMethod;
}
} else {
// Case 4.
next_state = RmadState::StateCase::kWpDisablePhysical;
}
}
} else {
// Case 5.
next_state = RmadState::StateCase::kFinalize;
}
return NextStateCaseWrapper(next_state);
}
} // namespace rmad