| // 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 |