libpldmresponder: bios: Add SetDataTime
Implement the time setting function based on decode requests,
set values and return responses.
It contains the error response.
Unit tests only include tests for numerical conversion.
Tested:
~# pldmtool bios SetDateTime -d 20200101080000
Encode request successfully
Request Message:
08 01 80 03 0d 00 00 08 01 01 20 20
On first recv(),response == request : RC = 0
Total length: 6
Shutdown Socket successful : RC = 0
Response Message:
08 01 00 03 0d 00
Set date time successfully.
~# busctl get-property xyz.openbmc_project.Time.Manager\
/xyz/openbmc_project/time/host\
xyz.openbmc_project.Time.EpochTime Elapsed
t 1577865726549597
The value of epochtime matches the time entered.
Signed-off-by: Xiaochao Ma <maxiaochao@inspur.com>
Change-Id: I8d123b993d515bcadba1468974907eb56d7e98b9
diff --git a/libpldmresponder/bios.cpp b/libpldmresponder/bios.cpp
index 8b18333..13b36ab 100644
--- a/libpldmresponder/bios.cpp
+++ b/libpldmresponder/bios.cpp
@@ -3,6 +3,8 @@
#include "utils.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
+#include <time.h>
+
#include <array>
#include <boost/crc.hpp>
#include <chrono>
@@ -59,6 +61,24 @@
1900); // The number of years since 1900
}
+std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
+ uint8_t day, uint8_t month, uint16_t year)
+{
+ struct std::tm stm;
+
+ stm.tm_year = year - 1900;
+ stm.tm_mon = month - 1;
+ stm.tm_mday = day;
+ stm.tm_hour = hours;
+ stm.tm_min = minutes;
+ stm.tm_sec = seconds;
+ stm.tm_isdst = -1;
+
+ // It will get the time in seconds since
+ // Epoch, 1970.1.1 00:00:00 +0000,UTC.
+ return timegm(&stm);
+}
+
size_t getTableTotalsize(size_t sizeWithoutPad)
{
return sizeWithoutPad + pldm_bios_table_pad_checksum_size(sizeWithoutPad);
@@ -93,7 +113,10 @@
catch (const std::exception& e)
{
}
-
+ handlers.emplace(PLDM_SET_DATE_TIME,
+ [this](const pldm_msg* request, size_t payloadLength) {
+ return this->setDateTime(request, payloadLength);
+ });
handlers.emplace(PLDM_GET_DATE_TIME,
[this](const pldm_msg* request, size_t payloadLength) {
return this->getDateTime(request, payloadLength);
@@ -155,6 +178,50 @@
return response;
}
+Response Handler::setDateTime(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;
+ std::time_t timeSec;
+
+ constexpr auto setTimeInterface = "xyz.openbmc_project.Time.EpochTime";
+ constexpr auto setTimePath = "/xyz/openbmc_project/time/host";
+ constexpr auto timeSetPro = "Elapsed";
+
+ auto rc = decode_set_date_time_req(request, payloadLength, &seconds,
+ &minutes, &hours, &day, &month, &year);
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+ timeSec = pldm::responder::utils::timeToEpoch(seconds, minutes, hours, day,
+ month, year);
+ uint64_t timeUsec = std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::seconds(timeSec))
+ .count();
+ std::variant<uint64_t> value{timeUsec};
+ try
+ {
+ pldm::utils::DBusHandler().setDbusProperty(setTimePath, timeSetPro,
+ setTimeInterface, value);
+ }
+ catch (std::exception& e)
+ {
+
+ std::cerr << "Error Setting time,PATH=" << setTimePath
+ << "TIME INTERFACE=" << setTimeInterface
+ << "ERROR=" << e.what() << "\n";
+
+ return ccOnlyResponse(request, PLDM_ERROR);
+ }
+
+ return ccOnlyResponse(request, PLDM_SUCCESS);
+}
+
/** @brief Construct the BIOS string table
*
* @param[in] BIOSStringTable - the string table