blob: 3670b1dff20ceb626039f701d8cfd8f084528a62 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rmad/ssfc/ssfc_prober.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "rmad/system/runtime_probe_client_impl.h"
#include "rmad/utils/cbi_utils_impl.h"
#include "rmad/utils/cros_config_utils_impl.h"
#include "rmad/utils/dbus_utils.h"
namespace rmad {
SsfcProberImpl::SsfcProberImpl() {
runtime_probe_client_ =
std::make_unique<RuntimeProbeClientImpl>(GetSystemBus());
cbi_utils_ = std::make_unique<CbiUtilsImpl>();
cros_config_utils_ = std::make_unique<CrosConfigUtilsImpl>();
Initialize();
}
SsfcProberImpl::SsfcProberImpl(
std::unique_ptr<RuntimeProbeClient> runtime_probe_client,
std::unique_ptr<CbiUtils> cbi_utils,
std::unique_ptr<CrosConfigUtils> cros_config_utils)
: runtime_probe_client_(std::move(runtime_probe_client)),
cbi_utils_(std::move(cbi_utils)),
cros_config_utils_(std::move(cros_config_utils)) {
Initialize();
}
void SsfcProberImpl::Initialize() {
RmadConfig rmad_config;
if (cros_config_utils_->GetRmadConfig(&rmad_config) &&
!rmad_config.ssfc.component_type_configs.empty()) {
ssfc_required_ = true;
ssfc_config_ = rmad_config.ssfc;
} else {
ssfc_required_ = false;
}
}
bool SsfcProberImpl::ProbeSsfc(uint32_t* ssfc) const {
if (!IsSsfcRequired()) {
return false;
}
std::vector<std::pair<RmadComponent, std::string>> runtime_probed_components;
if (!runtime_probe_client_->ProbeSsfcComponents(
/*use_customized_identifier=*/false, &runtime_probed_components)) {
return false;
}
// Get existing SSFC, which might not exist.
uint32_t probed_ssfc = 0;
cbi_utils_->GetSsfc(&probed_ssfc);
probed_ssfc &= ssfc_config_.mask;
// Update SSFC by probed results.
for (const auto& component_type_config :
ssfc_config_.component_type_configs) {
const auto& probeable_components =
component_type_config.probeable_components;
// Iterator of probed component under the component type.
auto probed_it = probeable_components.cend();
for (const auto& [component, identifier] : runtime_probed_components) {
if (auto it = probeable_components.find(identifier);
it != probeable_components.cend()) {
// There could be multiple probed results that map to the same component
// depending on how the probe statement is written, but at most one
// component under the component type should be probed.
if (probed_it != it && probed_it != probeable_components.cend()) {
LOG(ERROR) << "Failed to probe component type "
<< component_type_config.component_type
<< ": multiple components under the same type: "
<< probed_it->first << " and " << it->first;
return false;
}
probed_it = it;
}
}
if (probed_it == probeable_components.cend()) {
probed_ssfc |= component_type_config.default_value;
} else {
probed_ssfc |= probed_it->second;
}
}
*ssfc = probed_ssfc;
return true;
}
} // namespace rmad