blob: 487df72e16e0265b51b796578cf233ff73ebb2fe [file] [log] [blame]
Lei YU96232822017-01-20 14:05:46 +08001#include "bmc_epoch.hpp"
2
Gunnar Millsab4cc6a2018-09-14 14:42:39 -05003#include "utils.hpp"
Lei YU7b218792017-02-09 12:10:13 +08004
5#include <sys/timerfd.h>
6#include <unistd.h>
7
Gunnar Millsab4cc6a2018-09-14 14:42:39 -05008#include <phosphor-logging/elog-errors.hpp>
9#include <phosphor-logging/elog.hpp>
George Liu947b5342022-07-01 16:12:18 +080010#include <phosphor-logging/lg2.hpp>
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050011#include <xyz/openbmc_project/Common/error.hpp>
George Liuf1d54ae2022-09-01 16:54:57 +080012#include <xyz/openbmc_project/Time/error.hpp>
Lei YU7b218792017-02-09 12:10:13 +080013
Andrew Geissler714a20b2023-07-24 16:58:27 -040014#include <chrono>
15
Gunnar Mills75710b62018-04-08 14:50:11 -050016// Need to do this since its not exported outside of the kernel.
Lei YU7b218792017-02-09 12:10:13 +080017// Refer : https://gist.github.com/lethean/446cea944b7441228298
18#ifndef TFD_TIMER_CANCEL_ON_SET
19#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
20#endif
21
Lei YU96232822017-01-20 14:05:46 +080022namespace phosphor
23{
24namespace time
25{
George Liuf1d54ae2022-09-01 16:54:57 +080026namespace // anonymous
27{
Pavithra Barithaya864e1732023-04-11 04:30:23 -050028constexpr auto systemdTimeService = "org.freedesktop.timedate1";
29constexpr auto systemdTimePath = "/org/freedesktop/timedate1";
30constexpr auto systemdTimeInterface = "org.freedesktop.timedate1";
31constexpr auto methodSetTime = "SetTime";
George Liuf1d54ae2022-09-01 16:54:57 +080032} // namespace
33
Pavithra Barithayadd42c7f2022-08-11 05:09:02 -050034PHOSPHOR_LOG2_USING;
35
Lei YU96232822017-01-20 14:05:46 +080036namespace server = sdbusplus::xyz::openbmc_project::Time::server;
37using namespace phosphor::logging;
George Liuf1d54ae2022-09-01 16:54:57 +080038using FailedError = sdbusplus::xyz::openbmc_project::Time::Error::Failed;
Andrew Geissler714a20b2023-07-24 16:58:27 -040039using namespace std::chrono;
Lei YU7b218792017-02-09 12:10:13 +080040
41void BmcEpoch::initialize()
42{
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050043 using InternalFailure =
44 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Lei YU7b218792017-02-09 12:10:13 +080045
46 // Subscribe time change event
47 // Choose the MAX time that is possible to avoid mis fires.
48 constexpr itimerspec maxTime = {
Andrew Geissler714a20b2023-07-24 16:58:27 -040049 {0, 0}, // it_interval
50 {system_clock::duration::max().count(), 0}, // it_value
Lei YU7b218792017-02-09 12:10:13 +080051 };
52
53 timeFd = timerfd_create(CLOCK_REALTIME, 0);
54 if (timeFd == -1)
55 {
Pavithra Barithayadd42c7f2022-08-11 05:09:02 -050056 error("Failed to create timerfd: {ERRNO}", "ERRNO", errno);
Lei YU7b218792017-02-09 12:10:13 +080057 elog<InternalFailure>();
58 }
59
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050060 auto r = timerfd_settime(
61 timeFd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &maxTime, nullptr);
Lei YU7b218792017-02-09 12:10:13 +080062 if (r != 0)
63 {
Pavithra Barithayadd42c7f2022-08-11 05:09:02 -050064 error("Failed to set timerfd: {ERRNO}", "ERRNO", errno);
Lei YU7b218792017-02-09 12:10:13 +080065 elog<InternalFailure>();
66 }
67
Pavithra Barithaya8af2a1e2023-04-27 00:46:35 -050068 sd_event_source* es = nullptr;
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050069 r = sd_event_add_io(bus.get_event(), &es, timeFd, EPOLLIN, onTimeChange,
70 this);
Lei YU7b218792017-02-09 12:10:13 +080071 if (r < 0)
72 {
Pavithra Barithayadd42c7f2022-08-11 05:09:02 -050073 error("Failed to add event: {ERRNO}", "ERRNO", errno);
Lei YU7b218792017-02-09 12:10:13 +080074 elog<InternalFailure>();
75 }
76 timeChangeEventSource.reset(es);
77}
78
79BmcEpoch::~BmcEpoch()
80{
81 close(timeFd);
Lei YU96232822017-01-20 14:05:46 +080082}
83
84uint64_t BmcEpoch::elapsed() const
85{
Lei YU96232822017-01-20 14:05:46 +080086 return getTime().count();
87}
88
89uint64_t BmcEpoch::elapsed(uint64_t value)
90{
Lei YU7b218792017-02-09 12:10:13 +080091 /*
George Liu3c2f4492020-04-12 11:35:57 +080092 Mode | Set BMC Time
93 ----- | -------------
94 NTP | Fail to set
95 MANUAL| OK
Lei YU7b218792017-02-09 12:10:13 +080096 */
Lei YU7b218792017-02-09 12:10:13 +080097 auto time = microseconds(value);
George Liu3c2f4492020-04-12 11:35:57 +080098 setTime(time);
Lei YU7b218792017-02-09 12:10:13 +080099
Lei YU96232822017-01-20 14:05:46 +0800100 server::EpochTime::elapsed(value);
101 return value;
102}
103
Ratan Gupta1e1dc442021-02-02 05:51:08 -0600104int BmcEpoch::onTimeChange(sd_event_source* /* es */, int fd,
105 uint32_t /* revents */, void* /* userdata */)
Lei YU7b218792017-02-09 12:10:13 +0800106{
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500107 std::array<char, 64> time{};
Lei YU7b218792017-02-09 12:10:13 +0800108
109 // We are not interested in the data here.
110 // So read until there is no new data here in the FD
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500111 while (read(fd, time.data(), time.max_size()) > 0)
Pavithra Barithaya864e1732023-04-11 04:30:23 -0500112 {
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500113 ;
Pavithra Barithaya864e1732023-04-11 04:30:23 -0500114 }
Lei YU7b218792017-02-09 12:10:13 +0800115
Lei YU7b218792017-02-09 12:10:13 +0800116 return 0;
117}
118
George Liuf1d54ae2022-09-01 16:54:57 +0800119void BmcEpoch::onModeChanged(Mode mode)
120{
121 manager.setTimeMode(mode);
122}
123
124bool BmcEpoch::setTime(const microseconds& usec)
125{
Pavithra Barithaya864e1732023-04-11 04:30:23 -0500126 auto method = bus.new_method_call(systemdTimeService, systemdTimePath,
127 systemdTimeInterface, methodSetTime);
George Liuf1d54ae2022-09-01 16:54:57 +0800128 method.append(static_cast<int64_t>(usec.count()),
129 false, // relative
130 false); // user_interaction
131
132 try
133 {
134 bus.call_noreply(method);
135 }
136 catch (const sdbusplus::exception_t& ex)
137 {
Pavithra Barithayadd42c7f2022-08-11 05:09:02 -0500138 error("Error in setting system time: {ERROR}", "ERROR", ex);
George Liuf1d54ae2022-09-01 16:54:57 +0800139 using namespace xyz::openbmc_project::Time;
140 elog<FailedError>(Failed::REASON(ex.what()));
141 }
142 return true;
143}
144
Pavithra Barithaya864e1732023-04-11 04:30:23 -0500145microseconds BmcEpoch::getTime()
George Liuf1d54ae2022-09-01 16:54:57 +0800146{
147 auto now = system_clock::now();
148 return duration_cast<microseconds>(now.time_since_epoch());
149}
150
Lei YUaf5abc52017-03-07 17:49:17 +0800151} // namespace time
152} // namespace phosphor