blob: aead18787125fb57092e8709b4dc2e5f5a3a3b5c [file] [log] [blame]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "hoth_state.hpp"
#include "google3/host_commands.h"
#include "ec_util_interface.hpp"
#include <stdplus/print.hpp>
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/State/error.hpp>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <exception>
#include <functional>
#include <future>
namespace google
{
namespace hoth
{
namespace
{
constexpr uint32_t kTimerIntervalSeconds = 20;
template <typename T>
bool statisticsReponseHasEnoughWords(const ec_response_statistics& stats,
const T& field)
{
uint64_t offset_required =
(uint64_t)&field - (uint64_t)&stats + sizeof(field);
return stats.valid_words * 4 >= offset_required;
}
} // namespace
HothState::HothState(sdbusplus::bus::bus& bus, boost::asio::io_context& io,
const char* objPath, internal::HostCommand* hostCmd,
internal::EcUtil* ecutil) :
HothStateObject(bus, objPath), bus(bus), io(io), hostCmd(hostCmd),
ecUtil(ecutil), timer(io)
{
// Update metrics immediately while kicking off the timer.
timerUpdateMetrics();
}
void HothState::updateMetrics()
{
statistics = ecUtil->getHothStatistics();
// Emit the signal that property has changed.
// Fall back to default values if response does not contain enought words.
HothStateObject::resetFlags(
statisticsReponseHasEnoughWords(statistics, statistics.hoth_reset_flags)
? (uint32_t)statistics.hoth_reset_flags
: 0);
HothStateObject::upTime(statisticsReponseHasEnoughWords(
statistics, statistics.time_since_hoth_boot_us)
? (uint64_t)statistics.time_since_hoth_boot_us
: 0);
HothStateObject::roInfoStrikes(
statisticsReponseHasEnoughWords(statistics, statistics.ro_info_strikes)
? (uint32_t)statistics.ro_info_strikes
: 0xffffffff);
HothStateObject::rwInfoStrikes(
statisticsReponseHasEnoughWords(statistics, statistics.rw_info_strikes)
? (uint32_t)statistics.rw_info_strikes
: 0xffffffff);
HothStateObject::payloadUpdateFailureCode(
statisticsReponseHasEnoughWords(
statistics, statistics.payload_update_failure_reason)
? (uint16_t)statistics.payload_update_failure_reason
: 0xffff);
HothStateObject::payloadConfirmFailureCode(
statisticsReponseHasEnoughWords(
statistics,
statistics.payload_update_confirmation_cookie_failure_reason)
? (uint32_t)
statistics.payload_update_confirmation_cookie_failure_reason
: 0xffffffff);
HothStateObject::firmwareUpdateFailureCode(
statisticsReponseHasEnoughWords(
statistics, statistics.firmware_update_failure_reason)
? (uint16_t)statistics.firmware_update_failure_reason
: 0xffff);
HothStateObject::firmwareUpdateFailedMinor(
statisticsReponseHasEnoughWords(
statistics, statistics.failed_firmware_minor_version)
? (uint32_t)statistics.failed_firmware_minor_version
: 0xffffffff);
HothStateObject::bootloaderUpdateFailureCode(
statisticsReponseHasEnoughWords(statistics,
statistics.bootloader_update_error)
? (uint32_t)statistics.bootloader_update_error
: 0xffffffff);
HothStateObject::hasPersistentPanicInfo(
ecUtil->checkHothPersistentPanicInfo());
}
void HothState::timerUpdateMetrics()
{
try
{
updateMetrics();
}
catch (const std::exception& e)
{
stdplus::print(stderr, "Fetching Hoth metrics had an exception: {}\n",
e.what());
}
timer.expires_after(std::chrono::seconds(kTimerIntervalSeconds));
// NOLINTNEXTLINE(modernize-avoid-bind)
timer.async_wait(std::bind(&HothState::timerUpdateMetrics, this));
}
} // namespace hoth
} // namespace google