blob: 0ef0cd589add1e26974a0698ff9b1167845f3265 [file] [log] [blame]
// Copyright 2021 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/utils/flashrom_utils_impl.h>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <base/files/file_path.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <re2/re2.h>
#include "rmad/utils/cmd_utils_impl.h"
namespace {
constexpr char kFlashromCmd[] = "/usr/sbin/flashrom";
constexpr char kFmapDecodeCmd[] = "/usr/sbin/fmap_decode";
constexpr char kTempFirmwareFilePath[] = "fw.bin";
constexpr char kWriteProtectEnabledStr[] = "write protect is enabled.";
constexpr char kWriteProtectRangeRegexp[] =
R"a(area_offset="(0x[[:xdigit:]]+)"\s*area_size="(0x[[:xdigit:]]+)"\s*)a"
R"(area_name="WP_RO")";
} // namespace
namespace rmad {
FlashromUtilsImpl::FlashromUtilsImpl() : FlashromUtils() {
cmd_utils_ = std::make_unique<CmdUtilsImpl>();
}
FlashromUtilsImpl::FlashromUtilsImpl(std::unique_ptr<CmdUtils> cmd_utils)
: FlashromUtils(), cmd_utils_(std::move(cmd_utils)) {}
bool FlashromUtilsImpl::GetSoftwareWriteProtectionStatus(bool* enabled) {
std::string flashrom_output;
if (!cmd_utils_->GetOutput({kFlashromCmd, "-p", "host", "--wp-status"},
&flashrom_output)) {
return false;
}
if (flashrom_output.find(kWriteProtectEnabledStr) != std::string::npos) {
*enabled = true;
} else {
*enabled = false;
}
return true;
}
bool FlashromUtilsImpl::EnableSoftwareWriteProtection() {
int wp_start, wp_len;
if (!GetWriteProtectionRange(&wp_start, &wp_len)) {
LOG(ERROR) << "Failed to get write protection range";
return false;
}
std::stringstream wp_range_arg;
wp_range_arg << wp_start << "," << wp_len;
std::string unused_output;
return cmd_utils_->GetOutput({kFlashromCmd, "-p", "host", "--wp-enable",
"--wp-range", wp_range_arg.str()},
&unused_output);
}
bool FlashromUtilsImpl::DisableSoftwareWriteProtection() {
std::string unused_output;
return cmd_utils_->GetOutput({kFlashromCmd, "-p", "host", "--wp-disable"},
&unused_output);
}
bool FlashromUtilsImpl::GetWriteProtectionRange(int* wp_start, int* wp_len) {
base::ScopedTempDir temp_dir_;
CHECK(temp_dir_.CreateUniqueTempDir());
const base::FilePath firmware_file_path =
temp_dir_.GetPath().AppendASCII(kTempFirmwareFilePath);
std::string unused_output;
if (!cmd_utils_->GetOutput(
{kFlashromCmd, "-p", "host", "-r", firmware_file_path.MaybeAsASCII()},
&unused_output)) {
LOG(ERROR) << "Failed to read AP firmware";
return false;
}
std::string fmap_output;
if (!cmd_utils_->GetOutput(
{kFmapDecodeCmd, firmware_file_path.MaybeAsASCII()}, &fmap_output)) {
LOG(ERROR) << "Failed to decode fmap";
return false;
}
re2::StringPiece string_piece(fmap_output);
re2::RE2 regexp(kWriteProtectRangeRegexp);
std::string wp_start_str, wp_len_str;
if (!RE2::PartialMatch(string_piece, regexp, &wp_start_str, &wp_len_str)) {
LOG(ERROR) << "Failed to parse fmap";
return false;
}
return base::HexStringToInt(wp_start_str, wp_start) &&
base::HexStringToInt(wp_len_str, wp_len);
}
} // namespace rmad