blob: 51d541557dcd781583bc026230366cbd8a2fcc82 [file] [log] [blame]
#include "bios.hpp"
#include "libpldmresponder/utils.hpp"
#include "registration.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
#include <array>
#include <chrono>
#include <ctime>
#include <iostream>
#include <phosphor-logging/log.hpp>
#include <stdexcept>
#include <string>
#include <variant>
#include <vector>
namespace pldm
{
using namespace phosphor::logging;
using EpochTimeUS = uint64_t;
constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
namespace responder
{
namespace bios
{
void registerHandlers()
{
registerHandler(PLDM_BIOS, PLDM_GET_DATE_TIME, std::move(getDateTime));
}
} // namespace bios
namespace utils
{
void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
uint8_t& hours, uint8_t& day, uint8_t& month,
uint16_t& year)
{
auto t = time_t(timeSec);
auto time = localtime(&t);
seconds = decimalToBcd(time->tm_sec);
minutes = decimalToBcd(time->tm_min);
hours = decimalToBcd(time->tm_hour);
day = decimalToBcd(time->tm_mday);
month =
decimalToBcd(time->tm_mon + 1); // The number of months in the range
// 0 to 11.PLDM expects range 1 to 12
year = decimalToBcd(time->tm_year + 1900); // The number of years since 1900
}
} // namespace utils
Response getDateTime(const pldm_msg* request, size_t payloadLength)
{
uint8_t seconds = 0;
uint8_t minutes = 0;
uint8_t hours = 0;
uint8_t day = 0;
uint8_t month = 0;
uint16_t year = 0;
constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc";
Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
std::variant<EpochTimeUS> value;
auto bus = sdbusplus::bus::new_default();
try
{
auto service = getService(bus, bmcTimePath, timeInterface);
auto method = bus.new_method_call(service.c_str(), bmcTimePath,
dbusProperties, "Get");
method.append(timeInterface, "Elapsed");
auto reply = bus.call(method);
reply.read(value);
}
catch (std::exception& e)
{
log<level::ERR>("Error getting time", entry("PATH=%s", bmcTimePath),
entry("TIME INTERACE=%s", timeInterface));
encode_get_date_time_resp(0, PLDM_ERROR, seconds, minutes, hours, day,
month, year, responsePtr);
return response;
}
uint64_t timeUsec = std::get<EpochTimeUS>(value);
uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::microseconds(timeUsec))
.count();
utils::epochToBCDTime(timeSec, seconds, minutes, hours, day, month, year);
encode_get_date_time_resp(0, PLDM_SUCCESS, seconds, minutes, hours, day,
month, year, responsePtr);
return response;
}
} // namespace responder
} // namespace pldm