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
diff --git a/libpldmresponder/bios.hpp b/libpldmresponder/bios.hpp
index 41ac70c..4a42bf4 100644
--- a/libpldmresponder/bios.hpp
+++ b/libpldmresponder/bios.hpp
@@ -8,6 +8,7 @@
#include <stdint.h>
+#include <ctime>
#include <functional>
#include <map>
#include <vector>
@@ -56,7 +57,7 @@
/** @brief Handler for GetDateTime
*
* @param[in] request - Request message payload
- * @param[return] Response - PLDM Response message
+ * @return Response - PLDM Response message
*/
Response getDateTime(const pldm_msg* request, size_t payloadLength);
@@ -64,7 +65,7 @@
*
* @param[in] request - Request message
* @param[in] payload_length - Request message payload length
- * @param[return] Response - PLDM Response message
+ * @return Response - PLDM Response message
*/
Response getBIOSTable(const pldm_msg* request, size_t payloadLength);
@@ -76,6 +77,14 @@
*/
Response getBIOSAttributeCurrentValueByHandle(const pldm_msg* request,
size_t payloadLength);
+
+ /** @brief Handler for SetDateTime
+ *
+ * @param[in] request - Request message payload
+ * @param[in] payloadLength - Request message payload length
+ * @return Response - PLDM Response message
+ */
+ Response setDateTime(const pldm_msg* request, size_t payloadLength);
};
} // namespace bios
@@ -96,6 +105,19 @@
void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
uint8_t& hours, uint8_t& day, uint8_t& month,
uint16_t& year);
+
+/** @brief Convert dec time to epoch time
+ *
+ * @param[in] seconds - number of seconds in dec
+ * @param[in] minutes - number of minutes in dec
+ * @param[in] hours - number of hours in dec
+ * @param[in] day - day of the month in dec
+ * @param[in] month - month number in dec
+ * @param[in] year - year number in dec
+ * @return time - epoch time
+ */
+std::time_t timeToEpoch(uint8_t seconds, uint8_t minutes, uint8_t hours,
+ uint8_t day, uint8_t month, uint16_t year);
} // namespace utils
} // namespace responder
diff --git a/test/libpldmresponder_bios_test.cpp b/test/libpldmresponder_bios_test.cpp
index 1271dda..762a960 100644
--- a/test/libpldmresponder_bios_test.cpp
+++ b/test/libpldmresponder_bios_test.cpp
@@ -51,6 +51,23 @@
ASSERT_EQ(0x2019, year);
}
+TEST(timeToEpoch, testTime0)
+{
+ std::time_t ret = 1555132693;
+
+ uint8_t sec = 13;
+ uint8_t min = 18;
+ uint8_t hours = 5;
+ uint8_t day = 13;
+ uint8_t month = 4;
+ uint16_t year = 2019;
+
+ std::time_t timeSec = 0;
+ timeSec = timeToEpoch(sec, min, hours, day, month, year);
+
+ EXPECT_EQ(ret, timeSec);
+}
+
TEST(GetBIOSStrings, allScenarios)
{
using namespace bios_parser;