blob: 129d224d0243f876dd8ede84b79484c0fc379ce7 [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
4#include <phosphor-logging/log.hpp>
5
Lei YUaf5abc52017-03-07 17:49:17 +08006namespace phosphor
7{
8namespace time
9{
10using namespace sdbusplus::xyz::openbmc_project::Time;
11using namespace phosphor::logging;
Lei YU7b218792017-02-09 12:10:13 +080012using namespace std::chrono;
Lei YUaf5abc52017-03-07 17:49:17 +080013
14HostEpoch::HostEpoch(sdbusplus::bus::bus& bus,
15 const char* objPath)
16 : EpochBase(bus, objPath),
Lei YU7f4fca52017-02-23 15:15:51 +080017 offset(utils::readData<decltype(offset)::rep>(offsetFile))
Lei YUaf5abc52017-03-07 17:49:17 +080018{
Lei YU7b218792017-02-09 12:10:13 +080019 // Initialize the diffToSteadyClock
20 auto steadyTime = duration_cast<microseconds>(
21 steady_clock::now().time_since_epoch());
22 diffToSteadyClock = getTime() + offset - steadyTime;
Lei YUaf5abc52017-03-07 17:49:17 +080023}
24
25uint64_t HostEpoch::elapsed() const
26{
Lei YU7b218792017-02-09 12:10:13 +080027 auto ret = getTime();
28 if (timeOwner == Owner::SPLIT)
29 {
30 ret += offset;
31 }
32 return ret.count();
Lei YUaf5abc52017-03-07 17:49:17 +080033}
34
35uint64_t HostEpoch::elapsed(uint64_t value)
36{
Lei YU7b218792017-02-09 12:10:13 +080037 /*
38 Mode | Owner | Set Host Time
39 ----- | ----- | -------------
40 NTP | BMC | Not allowed
41 NTP | HOST | Not allowed
42 NTP | SPLIT | OK, and just save offset
43 NTP | BOTH | Not allowed
44 MANUAL| BMC | Not allowed
45 MANUAL| HOST | OK, and set time to BMC
46 MANUAL| SPLIT | OK, and just save offset
47 MANUAL| BOTH | OK, and set time to BMC
48 */
49 if (timeOwner == Owner::BMC ||
50 (timeMode == Mode::NTP
51 && (timeOwner == Owner::HOST || timeOwner == Owner::BOTH)))
Lei YUaf5abc52017-03-07 17:49:17 +080052 {
Lei YU7b218792017-02-09 12:10:13 +080053 log<level::ERR>("Setting HostTime is not allowed");
Lei YUaf5abc52017-03-07 17:49:17 +080054 // TODO: throw NotAllowed exception
55 return 0;
56 }
57
Lei YU7b218792017-02-09 12:10:13 +080058 auto time = microseconds(value);
59 if (timeOwner == Owner::SPLIT)
60 {
61 // Calculate the offset between host and bmc time
62 offset = time - getTime();
63 saveOffset();
Lei YUaf5abc52017-03-07 17:49:17 +080064
Lei YU7b218792017-02-09 12:10:13 +080065 // Calculate the diff between host and steady time
66 auto steadyTime = duration_cast<microseconds>(
67 steady_clock::now().time_since_epoch());
68 diffToSteadyClock = time - steadyTime;
69 }
70 else
71 {
72 // Set time to BMC
73 setTime(time);
74 }
Lei YUaf5abc52017-03-07 17:49:17 +080075
76 server::EpochTime::elapsed(value);
77 return value;
78}
79
Lei YU7b218792017-02-09 12:10:13 +080080void HostEpoch::onOwnerChanged(Owner owner)
81{
82 // If timeOwner is changed to SPLIT, the offset shall be preserved
83 // Otherwise it shall be cleared;
84 timeOwner = owner;
85 if (timeOwner != Owner::SPLIT)
86 {
87 offset = microseconds(0);
88 saveOffset();
89 }
90}
91
92void HostEpoch::saveOffset()
93{
94 // Store the offset to file
95 utils::writeData(offsetFile, offset.count());
96}
97
98void HostEpoch::onBmcTimeChanged(const microseconds& bmcTime)
99{
100 // If owner is split and BMC time is changed,
101 // the offset shall be adjusted
102 if (timeOwner == Owner::SPLIT)
103 {
104 auto steadyTime = duration_cast<microseconds>(
105 steady_clock::now().time_since_epoch());
106 auto hostTime = steadyTime + diffToSteadyClock;
107 offset = hostTime - bmcTime;
108
109 saveOffset();
110 }
111}
112
Lei YUaf5abc52017-03-07 17:49:17 +0800113} // namespace time
114} // namespace phosphor
115