blob: c3e6400aa2d2030e3d8752cf005f306328051214 [file] [log] [blame]
Lei YUaf5abc52017-03-07 17:49:17 +08001#include "host_epoch.hpp"
Lei YU7f4fca52017-02-23 15:15:51 +08002#include "utils.hpp"
Lei YUaf5abc52017-03-07 17:49:17 +08003
Lei YU33752c72018-06-07 17:06:58 +08004#include <phosphor-logging/elog-errors.hpp>
Lei YUaf5abc52017-03-07 17:49:17 +08005#include <phosphor-logging/log.hpp>
Lei YUf6fad822018-07-13 16:35:45 +08006#include <xyz/openbmc_project/Time/error.hpp>
Lei YUaf5abc52017-03-07 17:49:17 +08007
Lei YUaf5abc52017-03-07 17:49:17 +08008namespace phosphor
9{
10namespace time
11{
12using namespace sdbusplus::xyz::openbmc_project::Time;
13using namespace phosphor::logging;
Lei YU7b218792017-02-09 12:10:13 +080014using namespace std::chrono;
Lei YUaf5abc52017-03-07 17:49:17 +080015
Lei YUf6fad822018-07-13 16:35:45 +080016using NotAllowedError =
17 sdbusplus::xyz::openbmc_project::Time::Error::NotAllowed;
18
Lei YUaf5abc52017-03-07 17:49:17 +080019HostEpoch::HostEpoch(sdbusplus::bus::bus& bus,
20 const char* objPath)
21 : EpochBase(bus, objPath),
Lei YU7f4fca52017-02-23 15:15:51 +080022 offset(utils::readData<decltype(offset)::rep>(offsetFile))
Lei YUaf5abc52017-03-07 17:49:17 +080023{
Lei YU7b218792017-02-09 12:10:13 +080024 // Initialize the diffToSteadyClock
25 auto steadyTime = duration_cast<microseconds>(
26 steady_clock::now().time_since_epoch());
27 diffToSteadyClock = getTime() + offset - steadyTime;
Lei YUaf5abc52017-03-07 17:49:17 +080028}
29
30uint64_t HostEpoch::elapsed() const
31{
Lei YU7b218792017-02-09 12:10:13 +080032 auto ret = getTime();
Lei YUad143542017-07-25 14:27:07 +080033 if (timeOwner == Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +080034 {
35 ret += offset;
36 }
37 return ret.count();
Lei YUaf5abc52017-03-07 17:49:17 +080038}
39
40uint64_t HostEpoch::elapsed(uint64_t value)
41{
Lei YU7b218792017-02-09 12:10:13 +080042 /*
43 Mode | Owner | Set Host Time
44 ----- | ----- | -------------
45 NTP | BMC | Not allowed
46 NTP | HOST | Not allowed
47 NTP | SPLIT | OK, and just save offset
48 NTP | BOTH | Not allowed
49 MANUAL| BMC | Not allowed
50 MANUAL| HOST | OK, and set time to BMC
51 MANUAL| SPLIT | OK, and just save offset
52 MANUAL| BOTH | OK, and set time to BMC
53 */
54 if (timeOwner == Owner::BMC ||
55 (timeMode == Mode::NTP
Lei YUad143542017-07-25 14:27:07 +080056 && (timeOwner == Owner::Host || timeOwner == Owner::Both)))
Lei YUaf5abc52017-03-07 17:49:17 +080057 {
Lei YUf6fad822018-07-13 16:35:45 +080058 using namespace xyz::openbmc_project::Time;
59 elog<NotAllowedError>(
60 NotAllowed::OWNER(utils::ownerToStr(timeOwner).c_str()),
61 NotAllowed::SYNC_METHOD(utils::modeToStr(timeMode).c_str()),
62 NotAllowed::REASON("Setting HostTime is not allowed"));
Lei YUaf5abc52017-03-07 17:49:17 +080063 }
64
Lei YU7b218792017-02-09 12:10:13 +080065 auto time = microseconds(value);
Lei YUad143542017-07-25 14:27:07 +080066 if (timeOwner == Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +080067 {
68 // Calculate the offset between host and bmc time
69 offset = time - getTime();
70 saveOffset();
Lei YUaf5abc52017-03-07 17:49:17 +080071
Lei YU7b218792017-02-09 12:10:13 +080072 // Calculate the diff between host and steady time
73 auto steadyTime = duration_cast<microseconds>(
74 steady_clock::now().time_since_epoch());
75 diffToSteadyClock = time - steadyTime;
76 }
77 else
78 {
79 // Set time to BMC
80 setTime(time);
81 }
Lei YUaf5abc52017-03-07 17:49:17 +080082
83 server::EpochTime::elapsed(value);
84 return value;
85}
86
Lei YU7b218792017-02-09 12:10:13 +080087void HostEpoch::onOwnerChanged(Owner owner)
88{
89 // If timeOwner is changed to SPLIT, the offset shall be preserved
90 // Otherwise it shall be cleared;
91 timeOwner = owner;
Lei YUad143542017-07-25 14:27:07 +080092 if (timeOwner != Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +080093 {
94 offset = microseconds(0);
95 saveOffset();
96 }
Lei YU47263802017-11-08 17:30:04 +080097 else
98 {
99 // In SPLIT, need to re-calculate the diff between
100 // host and steady time
101 auto steadyTime = duration_cast<microseconds>(
102 steady_clock::now().time_since_epoch());
103 diffToSteadyClock = getTime() - steadyTime;
104 }
Lei YU7b218792017-02-09 12:10:13 +0800105}
106
107void HostEpoch::saveOffset()
108{
109 // Store the offset to file
110 utils::writeData(offsetFile, offset.count());
111}
112
113void HostEpoch::onBmcTimeChanged(const microseconds& bmcTime)
114{
115 // If owner is split and BMC time is changed,
116 // the offset shall be adjusted
Lei YUad143542017-07-25 14:27:07 +0800117 if (timeOwner == Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +0800118 {
119 auto steadyTime = duration_cast<microseconds>(
120 steady_clock::now().time_since_epoch());
121 auto hostTime = steadyTime + diffToSteadyClock;
122 offset = hostTime - bmcTime;
123
124 saveOffset();
125 }
126}
127
Lei YUaf5abc52017-03-07 17:49:17 +0800128} // namespace time
129} // namespace phosphor
130