blob: 4cf6832c0001b2254afde836c2f122fdda15458f [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 <string>
#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/logging.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/probe_config_loader_impl.h"
#include "runtime_probe/system_property_impl.h"
namespace runtime_probe {
namespace {
constexpr char kUsrLocal[] = "usr/local";
std::string GetProbeConfigSHA1Hash(const std::string& content) {
const auto& hash_val = base::SHA1HashString(content);
return base::HexEncode(hash_val.data(), hash_val.size());
}
base::Optional<ProbeConfigData> LoadProbeConfig(
const base::FilePath& file_path) {
DVLOG(2) << "LoadProbeConfig: " << file_path;
std::string config_json;
if (!base::ReadFileToString(file_path, &config_json)) {
DVLOG(2) << "Failed to read probe config";
return base::nullopt;
}
const auto probe_config_sha1_hash = GetProbeConfigSHA1Hash(config_json);
DVLOG(3) << "SHA1 hash of probe config: " << probe_config_sha1_hash;
auto json_val = base::JSONReader::Read(config_json, base::JSON_PARSE_RFC);
if (!json_val || !json_val->is_dict()) {
DVLOG(2) << "Failed to parse probe config as JSON.";
DVLOG(3) << "Input: " << config_json;
return base::nullopt;
}
const auto absolute_path = base::MakeAbsoluteFilePath(file_path);
return ProbeConfigData{.path = absolute_path,
.config = std::move(*json_val),
.sha1_hash = std::move(probe_config_sha1_hash)};
}
} // namespace
ProbeConfigLoaderImpl::ProbeConfigLoaderImpl() : root_("/") {
auto config = std::make_unique<brillo::CrosConfig>();
if (config->Init()) {
cros_config_ = std::move(config);
}
system_property_ = std::make_unique<SystemPropertyImpl>();
}
base::Optional<ProbeConfigData> ProbeConfigLoaderImpl::LoadDefault() const {
for (const auto& file_path : GetDefaultPaths()) {
auto ret = LoadProbeConfig(file_path);
if (ret) {
DVLOG(1) << "Load default config from: " << file_path;
return ret;
}
}
DVLOG(1) << "Cannot find any default probe configs";
return base::nullopt;
}
base::Optional<ProbeConfigData> ProbeConfigLoaderImpl::LoadFromFile(
const base::FilePath& file_path) const {
if (GetCrosDebug() != 1) {
LOG(ERROR) << "Arbitrary probe config is only allowed with cros_debug=1";
return base::nullopt;
}
auto ret = LoadProbeConfig(file_path);
DVLOG(1) << "Load config from: " << file_path;
return ret;
}
std::vector<base::FilePath> ProbeConfigLoaderImpl::GetDefaultPaths() const {
std::vector<base::FilePath> file_paths;
std::string model_name = GetModelName();
if (GetCrosDebug() == 1) {
auto probe_config_dir =
root_.Append(kUsrLocal).Append(kRuntimeProbeConfigDir);
file_paths.push_back(
probe_config_dir.Append(model_name).Append(kRuntimeProbeConfigName));
file_paths.push_back(probe_config_dir.Append(kRuntimeProbeConfigName));
}
auto probe_config_dir = root_.Append(kRuntimeProbeConfigDir);
file_paths.push_back(
probe_config_dir.Append(model_name).Append(kRuntimeProbeConfigName));
file_paths.push_back(probe_config_dir.Append(kRuntimeProbeConfigName));
return file_paths;
}
void ProbeConfigLoaderImpl::SetCrosConfigForTesting(
std::unique_ptr<brillo::CrosConfigInterface> cros_config) {
cros_config_ = std::move(cros_config);
}
void ProbeConfigLoaderImpl::SetSystemProertyForTesting(
std::unique_ptr<SystemProperty> system_property) {
system_property_ = std::move(system_property);
}
void ProbeConfigLoaderImpl::SetRootForTest(const base::FilePath& root) {
root_ = root;
}
int ProbeConfigLoaderImpl::GetCrosDebug() const {
int cros_config;
if (system_property_->GetInt("cros_debug", &cros_config))
return cros_config;
// Fallback to disabled cros_debug.
return 0;
}
std::string ProbeConfigLoaderImpl::GetModelName() const {
std::string model_name;
if (cros_config_->GetString(kCrosConfigModelNamePath, kCrosConfigModelNameKey,
&model_name))
return model_name;
// Fallback to sys_info.
return base::SysInfo::GetLsbReleaseBoard();
}
} // namespace runtime_probe