blob: ea3026c523fd44a11aae4e47f83576d73f682d5f [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 YU33752c72018-06-07 17:06:58 +08006#include <xyz/openbmc_project/Common/error.hpp>
Lei YUaf5abc52017-03-07 17:49:17 +08007
Lei YUaf5abc52017-03-07 17:49:17 +08008namespace phosphor
9{
10namespace time
11{
Lei YU33752c72018-06-07 17:06:58 +080012using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Lei YUaf5abc52017-03-07 17:49:17 +080013using namespace sdbusplus::xyz::openbmc_project::Time;
14using namespace phosphor::logging;
Lei YU7b218792017-02-09 12:10:13 +080015using namespace std::chrono;
Lei YUaf5abc52017-03-07 17:49:17 +080016
17HostEpoch::HostEpoch(sdbusplus::bus::bus& bus,
18 const char* objPath)
19 : EpochBase(bus, objPath),
Lei YU7f4fca52017-02-23 15:15:51 +080020 offset(utils::readData<decltype(offset)::rep>(offsetFile))
Lei YUaf5abc52017-03-07 17:49:17 +080021{
Lei YU7b218792017-02-09 12:10:13 +080022 // Initialize the diffToSteadyClock
23 auto steadyTime = duration_cast<microseconds>(
24 steady_clock::now().time_since_epoch());
25 diffToSteadyClock = getTime() + offset - steadyTime;
Lei YUaf5abc52017-03-07 17:49:17 +080026}
27
28uint64_t HostEpoch::elapsed() const
29{
Lei YU7b218792017-02-09 12:10:13 +080030 auto ret = getTime();
Lei YUad143542017-07-25 14:27:07 +080031 if (timeOwner == Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +080032 {
33 ret += offset;
34 }
35 return ret.count();
Lei YUaf5abc52017-03-07 17:49:17 +080036}
37
38uint64_t HostEpoch::elapsed(uint64_t value)
39{
Lei YU7b218792017-02-09 12:10:13 +080040 /*
41 Mode | Owner | Set Host Time
42 ----- | ----- | -------------
43 NTP | BMC | Not allowed
44 NTP | HOST | Not allowed
45 NTP | SPLIT | OK, and just save offset
46 NTP | BOTH | Not allowed
47 MANUAL| BMC | Not allowed
48 MANUAL| HOST | OK, and set time to BMC
49 MANUAL| SPLIT | OK, and just save offset
50 MANUAL| BOTH | OK, and set time to BMC
51 */
52 if (timeOwner == Owner::BMC ||
53 (timeMode == Mode::NTP
Lei YUad143542017-07-25 14:27:07 +080054 && (timeOwner == Owner::Host || timeOwner == Owner::Both)))
Lei YUaf5abc52017-03-07 17:49:17 +080055 {
Lei YU7b218792017-02-09 12:10:13 +080056 log<level::ERR>("Setting HostTime is not allowed");
Lei YU33752c72018-06-07 17:06:58 +080057 elog<InsufficientPermission>();
Lei YUaf5abc52017-03-07 17:49:17 +080058 }
59
Lei YU7b218792017-02-09 12:10:13 +080060 auto time = microseconds(value);
Lei YUad143542017-07-25 14:27:07 +080061 if (timeOwner == Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +080062 {
63 // Calculate the offset between host and bmc time
64 offset = time - getTime();
65 saveOffset();
Lei YUaf5abc52017-03-07 17:49:17 +080066
Lei YU7b218792017-02-09 12:10:13 +080067 // Calculate the diff between host and steady time
68 auto steadyTime = duration_cast<microseconds>(
69 steady_clock::now().time_since_epoch());
70 diffToSteadyClock = time - steadyTime;
71 }
72 else
73 {
74 // Set time to BMC
75 setTime(time);
76 }
Lei YUaf5abc52017-03-07 17:49:17 +080077
78 server::EpochTime::elapsed(value);
79 return value;
80}
81
Lei YU7b218792017-02-09 12:10:13 +080082void HostEpoch::onOwnerChanged(Owner owner)
83{
84 // If timeOwner is changed to SPLIT, the offset shall be preserved
85 // Otherwise it shall be cleared;
86 timeOwner = owner;
Lei YUad143542017-07-25 14:27:07 +080087 if (timeOwner != Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +080088 {
89 offset = microseconds(0);
90 saveOffset();
91 }
Lei YU47263802017-11-08 17:30:04 +080092 else
93 {
94 // In SPLIT, need to re-calculate the diff between
95 // host and steady time
96 auto steadyTime = duration_cast<microseconds>(
97 steady_clock::now().time_since_epoch());
98 diffToSteadyClock = getTime() - steadyTime;
99 }
Lei YU7b218792017-02-09 12:10:13 +0800100}
101
102void HostEpoch::saveOffset()
103{
104 // Store the offset to file
105 utils::writeData(offsetFile, offset.count());
106}
107
108void HostEpoch::onBmcTimeChanged(const microseconds& bmcTime)
109{
110 // If owner is split and BMC time is changed,
111 // the offset shall be adjusted
Lei YUad143542017-07-25 14:27:07 +0800112 if (timeOwner == Owner::Split)
Lei YU7b218792017-02-09 12:10:13 +0800113 {
114 auto steadyTime = duration_cast<microseconds>(
115 steady_clock::now().time_since_epoch());
116 auto hostTime = steadyTime + diffToSteadyClock;
117 offset = hostTime - bmcTime;
118
119 saveOffset();
120 }
121}
122
Lei YUaf5abc52017-03-07 17:49:17 +0800123} // namespace time
124} // namespace phosphor
125