1 #include "bios.hpp" 2 3 #include "libpldmresponder/utils.hpp" 4 #include "registration.hpp" 5 #include "xyz/openbmc_project/Common/error.hpp" 6 7 #include <array> 8 #include <chrono> 9 #include <ctime> 10 #include <iostream> 11 #include <phosphor-logging/log.hpp> 12 #include <stdexcept> 13 #include <string> 14 #include <variant> 15 #include <vector> 16 17 namespace pldm 18 { 19 20 using namespace phosphor::logging; 21 22 using EpochTimeUS = uint64_t; 23 24 constexpr auto dbusProperties = "org.freedesktop.DBus.Properties"; 25 26 namespace responder 27 { 28 29 namespace bios 30 { 31 32 void registerHandlers() 33 { 34 registerHandler(PLDM_BIOS, PLDM_GET_DATE_TIME, std::move(getDateTime)); 35 } 36 37 } // namespace bios 38 39 namespace utils 40 { 41 42 void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes, 43 uint8_t& hours, uint8_t& day, uint8_t& month, 44 uint16_t& year) 45 { 46 auto t = time_t(timeSec); 47 auto time = localtime(&t); 48 49 seconds = decimalToBcd(time->tm_sec); 50 minutes = decimalToBcd(time->tm_min); 51 hours = decimalToBcd(time->tm_hour); 52 day = decimalToBcd(time->tm_mday); 53 month = 54 decimalToBcd(time->tm_mon + 1); // The number of months in the range 55 // 0 to 11.PLDM expects range 1 to 12 56 year = decimalToBcd(time->tm_year + 1900); // The number of years since 1900 57 } 58 59 } // namespace utils 60 61 Response getDateTime(const pldm_msg* request, size_t payloadLength) 62 { 63 uint8_t seconds = 0; 64 uint8_t minutes = 0; 65 uint8_t hours = 0; 66 uint8_t day = 0; 67 uint8_t month = 0; 68 uint16_t year = 0; 69 70 constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime"; 71 constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc"; 72 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0); 73 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 74 std::variant<EpochTimeUS> value; 75 76 auto bus = sdbusplus::bus::new_default(); 77 try 78 { 79 auto service = getService(bus, bmcTimePath, timeInterface); 80 81 auto method = bus.new_method_call(service.c_str(), bmcTimePath, 82 dbusProperties, "Get"); 83 method.append(timeInterface, "Elapsed"); 84 85 auto reply = bus.call(method); 86 reply.read(value); 87 } 88 89 catch (std::exception& e) 90 { 91 log<level::ERR>("Error getting time", entry("PATH=%s", bmcTimePath), 92 entry("TIME INTERACE=%s", timeInterface)); 93 94 encode_get_date_time_resp(request->hdr.instance_id, PLDM_ERROR, seconds, 95 minutes, hours, day, month, year, 96 responsePtr); 97 return response; 98 } 99 100 uint64_t timeUsec = std::get<EpochTimeUS>(value); 101 102 uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>( 103 std::chrono::microseconds(timeUsec)) 104 .count(); 105 106 utils::epochToBCDTime(timeSec, seconds, minutes, hours, day, month, year); 107 108 encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS, seconds, 109 minutes, hours, day, month, year, responsePtr); 110 return response; 111 } 112 113 } // namespace responder 114 } // namespace pldm 115