blob: 9636bae2b5a98432f85b66bc25231577d21189af [file] [log] [blame]
// Copyright 2018 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 <utility>
#include <vector>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/hash/sha1.h>
#include <base/json/json_reader.h>
#include <base/strings/string_number_conversions.h>
#include <base/system/sys_info.h>
#include <chromeos-config/libcros_config/cros_config.h>
#include <vboot/crossystem.h>
#include "runtime_probe/utils/config_utils.h"
namespace {
constexpr char kCrosConfigModelNamePath[] = "/";
constexpr char kCrosConfigModelNameKey[] = "name";
constexpr char kUsrLocal[] = "usr/local";
constexpr char kRuntimeProbeConfigDir[] = "etc/runtime_probe";
constexpr char kRuntimeProbeConfigName[] = "probe_config.json";
void GetModelName(std::string* model_name) {
auto cros_config = std::make_unique<brillo::CrosConfig>();
if (cros_config->Init() &&
cros_config->GetString(kCrosConfigModelNamePath, kCrosConfigModelNameKey,
model_name))
return;
// Fallback to sys_info.
*model_name = base::SysInfo::GetLsbReleaseBoard();
}
bool GetProbeConfigPathByBase(const base::FilePath& root_path,
std::string* probe_config_path) {
probe_config_path->clear();
std::string model_name;
GetModelName(&model_name);
std::vector<base::FilePath> config_paths{
root_path.Append(kRuntimeProbeConfigDir)
.Append(model_name)
.Append(kRuntimeProbeConfigName),
root_path.Append(kRuntimeProbeConfigDir).Append(kRuntimeProbeConfigName)};
for (const auto& config_path : config_paths) {
if (base::PathExists(config_path)) {
*probe_config_path = config_path.value();
break;
}
}
return !probe_config_path->empty();
}
std::string GetProbeConfigSHA1Hash(const std::string& content) {
const auto& hash_val = base::SHA1HashString(content);
return base::HexEncode(hash_val.data(), hash_val.size());
}
bool IsCrosDebugOn() {
return VbGetSystemPropertyInt("cros_debug") == 1;
}
} // namespace
namespace runtime_probe {
base::Optional<ProbeConfigData> ParseProbeConfig(
const std::string& config_file_path) {
std::string config_json;
if (!base::ReadFileToString(base::FilePath(config_file_path), &config_json)) {
LOG(ERROR) << "Config file doesn't exist. "
<< "Input config file path is: " << config_file_path;
return base::nullopt;
}
const auto probe_config_sha1_hash = GetProbeConfigSHA1Hash(config_json);
LOG(INFO) << "SHA1 hash of probe config read from " << config_file_path
<< ": " << probe_config_sha1_hash;
auto json_val = base::JSONReader::Read(config_json, base::JSON_PARSE_RFC);
if (!json_val || !json_val->is_dict()) {
LOG(ERROR) << "Failed to parse ProbeConfig from : [" << config_file_path
<< "]\nInput JSON string is:\n"
<< config_json;
return base::nullopt;
}
return ProbeConfigData{.config = std::move(*json_val),
.sha1_hash = std::move(probe_config_sha1_hash)};
}
bool GetProbeConfigPath(const std::string& probe_config_path_from_cli,
std::string* probe_config_path) {
probe_config_path->clear();
if (!probe_config_path_from_cli.empty()) {
if (!IsCrosDebugOn()) {
LOG(ERROR) << "Arbitrary ProbeConfig is only allowed with cros_debug=1";
return false;
}
*probe_config_path = probe_config_path_from_cli;
} else {
VLOG(1) << "No config_file_path specified, picking default config.";
base::FilePath root{"/"};
if (IsCrosDebugOn())
GetProbeConfigPathByBase(root.Append(kUsrLocal), probe_config_path);
if (probe_config_path->empty())
GetProbeConfigPathByBase(root, probe_config_path);
}
VLOG(1) << "Selected config file: " << *probe_config_path;
return !probe_config_path->empty();
}
} // namespace runtime_probe