blob: bf6cbef5791b2ab6a822b02ea26b1f07ba663562 [file] [log] [blame]
AppaRao Pulie63eeda2019-07-05 16:25:38 +05301/*
2// Copyright (c) 2019 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
AppaRao Puli67d184c2020-05-29 00:48:33 +053017#include "pfr.hpp"
18#include "pfr_mgr.hpp"
19
AppaRao Puli88aa33b2019-07-18 23:49:55 +053020#include <systemd/sd-journal.h>
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +000021#include <unistd.h>
AppaRao Puli88aa33b2019-07-18 23:49:55 +053022
AppaRao Puli46cead92019-07-22 16:50:09 +053023#include <boost/asio.hpp>
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +000024#include <sdbusplus/asio/property.hpp>
25#include <sdbusplus/unpack_properties.hpp>
AppaRao Pulie63eeda2019-07-05 16:25:38 +053026
AppaRao Pulidcf13122020-05-28 01:21:39 +053027namespace pfr
28{
AppaRao Puli88aa33b2019-07-18 23:49:55 +053029
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +000030static bool i2cConfigLoaded = false;
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +000031static int retrCount = 10;
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +000032
AppaRao Puli88aa33b2019-07-18 23:49:55 +053033static bool stateTimerRunning = false;
AppaRao Puli46cead92019-07-22 16:50:09 +053034bool finishedSettingChkPoint = false;
35static constexpr uint8_t bmcBootFinishedChkPoint = 0x09;
36
AppaRao Puli88aa33b2019-07-18 23:49:55 +053037std::unique_ptr<boost::asio::steady_timer> stateTimer = nullptr;
AppaRao Puli46cead92019-07-22 16:50:09 +053038std::unique_ptr<boost::asio::steady_timer> initTimer = nullptr;
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +000039std::unique_ptr<boost::asio::steady_timer> pfrObjTimer = nullptr;
AppaRao Pulidcf13122020-05-28 01:21:39 +053040std::vector<std::unique_ptr<PfrVersion>> pfrVersionObjects;
41std::unique_ptr<PfrConfig> pfrConfigObject;
AppaRao Pulie4e95652019-07-19 16:52:01 +053042
AppaRao Pulie4e95652019-07-19 16:52:01 +053043// List holds <ObjPath> <ImageType> <VersionPurpose>
44static std::vector<std::tuple<std::string, ImageType, std::string>>
45 verComponentList = {
AppaRao Pulie4e95652019-07-19 16:52:01 +053046 std::make_tuple("bmc_recovery", ImageType::bmcRecovery,
47 versionPurposeBMC),
AppaRao Pulie4e95652019-07-19 16:52:01 +053048 std::make_tuple("bios_recovery", ImageType::biosRecovery,
49 versionPurposeHost),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053050 std::make_tuple("cpld_recovery", ImageType::cpldRecovery,
51 versionPurposeOther),
Vikram Bodireddy8292dc62021-05-26 13:31:47 +053052 std::make_tuple("afm_active", ImageType::afmActive,
53 versionPurposeOther),
54 std::make_tuple("afm_recovery", ImageType::afmRecovery,
55 versionPurposeOther),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053056};
AppaRao Pulie4e95652019-07-19 16:52:01 +053057
AppaRao Pulie90f1282019-11-05 01:07:05 +053058// Recovery reason map.
59// {<CPLD association>,{<Redfish MessageID>, <Recovery Reason>}}
60static const boost::container::flat_map<uint8_t,
61 std::pair<std::string, std::string>>
62 recoveryReasonMap = {
63 {0x01,
64 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000065 "BIOS active image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053066 {0x02,
67 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000068 "BIOS recovery image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053069 {0x03, {"MEFirmwareRecoveryReason", "ME launch failure"}},
70 {0x04, {"BIOSFirmwareRecoveryReason", "ACM launch failure"}},
71 {0x05, {"BIOSFirmwareRecoveryReason", "IBB launch failure"}},
72 {0x06, {"BIOSFirmwareRecoveryReason", "OBB launch failure"}},
73 {0x07,
74 {"BMCFirmwareRecoveryReason",
75 "BMC active image authentication failure"}},
76 {0x08,
77 {"BMCFirmwareRecoveryReason",
78 "BMC recovery image authentication failure"}},
79 {0x09, {"BMCFirmwareRecoveryReason", "BMC launch failure"}},
80 {0x0A, {"CPLDFirmwareRecoveryReason", "CPLD watchdog expired"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053081
AppaRao Pulie90f1282019-11-05 01:07:05 +053082// Panic Reason map.
83// {<CPLD association>, {<Redfish MessageID>, <Panic reason> })
84static const boost::container::flat_map<uint8_t,
85 std::pair<std::string, std::string>>
86 panicReasonMap = {
Chalapathi3fb544b2020-02-14 15:43:49 +000087 {0x01, {"BIOSFirmwarePanicReason", "BIOS update intent"}},
88 {0x02, {"BMCFirmwarePanicReason", "BMC update intent"}},
89 {0x03, {"BMCFirmwarePanicReason", "BMC reset detected"}},
90 {0x04, {"BMCFirmwarePanicReason", "BMC watchdog expired"}},
91 {0x05, {"MEFirmwarePanicReason", "ME watchdog expired"}},
92 {0x06, {"BIOSFirmwarePanicReason", "ACM watchdog expired"}},
93 {0x07, {"BIOSFirmwarePanicReason", "IBB watchdog expired"}},
94 {0x08, {"BIOSFirmwarePanicReason", "OBB watchdog expired"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053095 {0x09,
96 {"BIOSFirmwarePanicReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000097 "ACM or IBB or OBB authentication failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053098
AppaRao Puli24766942019-11-13 19:27:08 +053099// Firmware resiliency major map.
100// {<CPLD association>, {<Redfish MessageID>, <Error reason> })
101static const boost::container::flat_map<uint8_t,
102 std::pair<std::string, std::string>>
103 majorErrorCodeMap = {
104 {0x01,
105 {"BMCFirmwareResiliencyError", "BMC image authentication failed"}},
106 {0x02,
107 {"BIOSFirmwareResiliencyError", "BIOS image authentication failed"}},
Chalapathi3fb544b2020-02-14 15:43:49 +0000108 {0x03, {"BIOSFirmwareResiliencyError", "Update from BIOS failed"}},
109 {0x04, {"BMCFirmwareResiliencyError", "Update from BMC failed"}}};
AppaRao Puli24766942019-11-13 19:27:08 +0530110
AppaRao Pulie4e95652019-07-19 16:52:01 +0530111static void updateDbusPropertiesCache()
112{
113 for (const auto& pfrVerObj : pfrVersionObjects)
114 {
115 pfrVerObj->updateVersion();
116 }
117
118 // Update provisoningStatus properties
119 pfrConfigObject->updateProvisioningStatus();
120
121 phosphor::logging::log<phosphor::logging::level::INFO>(
122 "PFR Manager service cache data updated.");
123}
124
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530125static void logLastRecoveryEvent()
126{
127 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530128 if (0 != readCpldReg(ActionType::recoveryReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530129 {
130 return;
131 }
132
AppaRao Pulie90f1282019-11-05 01:07:05 +0530133 auto it = recoveryReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530134 if (it == recoveryReasonMap.end())
135 {
136 // No matching found. So just return without logging event.
137 return;
138 }
AppaRao Pulie90f1282019-11-05 01:07:05 +0530139 std::string msgId = "OpenBMC.0.1." + it->second.first;
140 sd_journal_send("MESSAGE=%s", "Platform firmware recovery occurred.",
141 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
142 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
143 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530144}
145
146static void logLastPanicEvent()
147{
148 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530149 if (0 != readCpldReg(ActionType::panicReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530150 {
151 return;
152 }
153
AppaRao Pulie90f1282019-11-05 01:07:05 +0530154 auto it = panicReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530155 if (it == panicReasonMap.end())
156 {
157 // No matching found. So just return without logging event.
158 return;
159 }
160
AppaRao Pulie90f1282019-11-05 01:07:05 +0530161 std::string msgId = "OpenBMC.0.1." + it->second.first;
162 sd_journal_send("MESSAGE=%s", "Platform firmware panic occurred.",
163 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
164 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
165 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530166}
167
AppaRao Puli24766942019-11-13 19:27:08 +0530168static void logResiliencyErrorEvent(const uint8_t majorErrorCode,
169 const uint8_t minorErrorCode)
170{
171 auto it = majorErrorCodeMap.find(majorErrorCode);
172 if (it == majorErrorCodeMap.end())
173 {
174 // No matching found. So just return without logging event.
175 return;
176 }
177
178 std::string errorStr =
179 it->second.second + "(MinorCode:0x" + toHexString(minorErrorCode) + ")";
180 std::string msgId = "OpenBMC.0.1." + it->second.first;
181 sd_journal_send(
182 "MESSAGE=%s", "Platform firmware resiliency error occurred.",
183 "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s", msgId.c_str(),
184 "REDFISH_MESSAGE_ARGS=%s", errorStr.c_str(), NULL);
185}
186
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000187static void
188 handleLastCountChange(std::shared_ptr<sdbusplus::asio::connection> conn,
189 std::string eventName, uint8_t currentCount)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530190{
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000191 sdbusplus::asio::setProperty(
192 *conn, "xyz.openbmc_project.Settings",
193 "/xyz/openbmc_project/pfr/last_events",
194 "xyz.openbmc_project.PFR.LastEvents", eventName, currentCount,
195 [](boost::system::error_code ec) {
196 if (ec)
197 {
198 phosphor::logging::log<phosphor::logging::level::ERR>(
199 "PFR: Unable to update currentCount",
200 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
201 return;
202 }
203 });
204 return;
205}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530206
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000207static void
208 checkAndLogEvents(std::shared_ptr<sdbusplus::asio::connection>& conn)
209{
210 sdbusplus::asio::getAllProperties(
211 *conn, "xyz.openbmc_project.Settings",
212 "/xyz/openbmc_project/pfr/last_events",
213 "xyz.openbmc_project.PFR.LastEvents",
214 [conn](
215 boost::system::error_code ec,
216 std::vector<
217 std::pair<std::string, std::variant<std::monostate, uint8_t>>>&
218 properties) {
219 if (ec)
220 {
221 phosphor::logging::log<phosphor::logging::level::ERR>(
222 "PFR: Unable get PFR last events",
223 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
224 return;
225 }
226 uint8_t lastRecoveryCount = 0;
227 uint8_t lastPanicCount = 0;
228 uint8_t lastMajorErr = 0;
229 uint8_t lastMinorErr = 0;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530230
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000231 try
232 {
233 sdbusplus::unpackProperties(
234 properties, "lastRecoveryCount", lastRecoveryCount,
235 "lastPanicCount", lastPanicCount, "lastMajorErr",
236 lastMajorErr, "lastMinorErr", lastMinorErr);
237 }
238 catch (const sdbusplus::exception::UnpackPropertyError& error)
239 {
240 phosphor::logging::log<phosphor::logging::level::ERR>(
241 "PFR: Unpack error",
242 phosphor::logging::entry("MSG=%s", error.what()));
243 return;
244 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530245
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000246 uint8_t currPanicCount = 0;
247 if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
248 {
249 if (lastPanicCount != currPanicCount)
250 {
251 // Update cached data to dbus and log redfish
252 // event by reading reason.
253 handleLastCountChange(conn, "lastPanicCount",
254 currPanicCount);
255 if (currPanicCount)
256 {
257 logLastPanicEvent();
258 }
259 }
260 }
261
262 uint8_t currRecoveryCount = 0;
263 if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
264 {
265 if (lastRecoveryCount != currRecoveryCount)
266 {
267 // Update cached data to dbus and log redfish
268 // event by reading reason.
269 handleLastCountChange(conn, "lastRecoveryCount",
270 currRecoveryCount);
271 if (currRecoveryCount)
272 {
273 logLastRecoveryEvent();
274 }
275 }
276 }
277
278 uint8_t majorErr = 0;
279 uint8_t minorErr = 0;
280 if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
281 (0 == readCpldReg(ActionType::minorError, minorErr)))
282 {
283 if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
284 {
285 // Update cached data to dbus and log redfish event by
286 // reading reason.
287 handleLastCountChange(conn, "lastMajorErr", majorErr);
288 handleLastCountChange(conn, "lastMinorErr", minorErr);
289 if (majorErr && minorErr)
290 {
291 logResiliencyErrorEvent(majorErr, minorErr);
292 }
293 }
294 }
295 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530296}
297
298static void monitorPlatformStateChange(
299 sdbusplus::asio::object_server& server,
300 std::shared_ptr<sdbusplus::asio::connection>& conn)
301{
302 constexpr size_t pollTimeout = 10; // seconds
303 stateTimer->expires_after(std::chrono::seconds(pollTimeout));
304 stateTimer->async_wait(
305 [&server, &conn](const boost::system::error_code& ec) {
306 if (ec == boost::asio::error::operation_aborted)
307 {
308 // Timer reset.
309 return;
310 }
311 if (ec)
312 {
313 // Platform State Monitor - Timer cancelled.
314 return;
315 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000316 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530317 monitorPlatformStateChange(server, conn);
318 });
319}
320
AppaRao Puli46cead92019-07-22 16:50:09 +0530321void checkAndSetCheckpoint(sdbusplus::asio::object_server& server,
322 std::shared_ptr<sdbusplus::asio::connection>& conn)
323{
324 // Check whether systemd completed all the loading.
325 conn->async_method_call(
326 [&server, &conn](boost::system::error_code ec,
327 const std::variant<uint64_t>& value) {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530328 if (!ec)
AppaRao Puli46cead92019-07-22 16:50:09 +0530329 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530330 if (std::get<uint64_t>(value))
AppaRao Puli46cead92019-07-22 16:50:09 +0530331 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530332 phosphor::logging::log<phosphor::logging::level::INFO>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000333 "BMC boot completed. Setting checkpoint 9.");
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530334 if (!finishedSettingChkPoint)
335 {
336 finishedSettingChkPoint = true;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530337 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530338 }
339 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530340 }
341 }
342 else
343 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530344 // Failed to get data from systemd. System might not
345 // be ready yet. Attempt again for data.
346 phosphor::logging::log<phosphor::logging::level::ERR>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000347 "aync call failed to get FinishTimestamp.",
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530348 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
AppaRao Puli46cead92019-07-22 16:50:09 +0530349 }
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530350 // FIX-ME: Latest up-stream sync caused issue in receiving
351 // StartupFinished signal. Unable to get StartupFinished signal
352 // from systemd1 hence using poll method too, to trigger it
353 // properly.
354 constexpr size_t pollTimeout = 10; // seconds
355 initTimer->expires_after(std::chrono::seconds(pollTimeout));
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000356 initTimer->async_wait(
357 [&server, &conn](const boost::system::error_code& ec) {
358 if (ec == boost::asio::error::operation_aborted)
359 {
360 // Timer reset.
361 phosphor::logging::log<phosphor::logging::level::INFO>(
362 "Set boot Checkpoint - Timer aborted or stopped.");
363 return;
364 }
365 if (ec)
366 {
367 phosphor::logging::log<phosphor::logging::level::ERR>(
368 "Set boot Checkpoint - async wait error.");
369 return;
370 }
371 checkAndSetCheckpoint(server, conn);
372 });
AppaRao Puli46cead92019-07-22 16:50:09 +0530373 },
374 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
375 "org.freedesktop.DBus.Properties", "Get",
376 "org.freedesktop.systemd1.Manager", "FinishTimestamp");
377}
378
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530379void monitorSignals(sdbusplus::asio::object_server& server,
380 std::shared_ptr<sdbusplus::asio::connection>& conn)
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530381{
AppaRao Puli46cead92019-07-22 16:50:09 +0530382 // Monitor Boot finished signal and set the checkpoint 9 to
383 // notify CPLD about BMC boot finish.
384 auto bootFinishedSignal = std::make_unique<sdbusplus::bus::match::match>(
385 static_cast<sdbusplus::bus::bus&>(*conn),
386 "type='signal',"
387 "member='StartupFinished',path='/org/freedesktop/systemd1',"
388 "interface='org.freedesktop.systemd1.Manager'",
389 [&server, &conn](sdbusplus::message::message& msg) {
390 if (!finishedSettingChkPoint)
391 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530392 phosphor::logging::log<phosphor::logging::level::INFO>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000393 "BMC boot completed(StartupFinished). Setting "
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530394 "checkpoint 9.");
AppaRao Puli46cead92019-07-22 16:50:09 +0530395 finishedSettingChkPoint = true;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530396 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Puli46cead92019-07-22 16:50:09 +0530397 }
398 });
399 checkAndSetCheckpoint(server, conn);
400
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530401 // Capture the Chassis state and Start the monitor timer
402 // if state changed to 'On'. Run timer until OS boot.
403 // Stop timer if state changed to 'Off'.
404 static auto matchChassisState = sdbusplus::bus::match::match(
405 static_cast<sdbusplus::bus::bus&>(*conn),
406 "type='signal',member='PropertiesChanged', "
407 "interface='org.freedesktop.DBus.Properties', "
408 "sender='xyz.openbmc_project.State.Chassis', "
409 "arg0namespace='xyz.openbmc_project.State.Chassis'",
410 [&server, &conn](sdbusplus::message::message& message) {
411 std::string intfName;
412 std::map<std::string, std::variant<std::string>> properties;
413 message.read(intfName, properties);
414
415 const auto it = properties.find("CurrentPowerState");
416 if (it != properties.end())
417 {
418 const std::string* state =
419 std::get_if<std::string>(&it->second);
420 if (state != nullptr)
421 {
422 if ((*state ==
423 "xyz.openbmc_project.State.Chassis.PowerState.On") &&
424 (!stateTimerRunning))
425 {
426 stateTimerRunning = true;
427 monitorPlatformStateChange(server, conn);
428 }
429 else if ((*state == "xyz.openbmc_project.State.Chassis."
430 "PowerState.Off") &&
431 (stateTimerRunning))
432 {
433 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000434 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530435 stateTimerRunning = false;
436 }
437 }
AppaRao Pulie4e95652019-07-19 16:52:01 +0530438
439 // Update the D-Bus properties when chassis state changes.
440 updateDbusPropertiesCache();
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530441 }
442 });
443
444 // Capture the Host state and Start the monitor timer
445 // if state changed to 'Running'. Run timer until OS boot.
446 // Stop timer if state changed to 'Off'.
447 static auto matchHostState = sdbusplus::bus::match::match(
448 static_cast<sdbusplus::bus::bus&>(*conn),
449 "type='signal',member='PropertiesChanged', "
450 "interface='org.freedesktop.DBus.Properties', "
451 "sender='xyz.openbmc_project.State.Chassis', "
452 "arg0namespace='xyz.openbmc_project.State.Host'",
453 [&server, &conn](sdbusplus::message::message& message) {
454 std::string intfName;
455 std::map<std::string, std::variant<std::string>> properties;
456 message.read(intfName, properties);
457
458 const auto it = properties.find("CurrentHostState");
459 if (it != properties.end())
460 {
461 const std::string* state =
462 std::get_if<std::string>(&it->second);
463 if (state != nullptr)
464 {
465 if ((*state ==
466 "xyz.openbmc_project.State.Host.HostState.Running") &&
467 (!stateTimerRunning))
468 {
469 stateTimerRunning = true;
470 monitorPlatformStateChange(server, conn);
471 }
472 else if (((*state == "xyz.openbmc_project.State.Host."
473 "HostState.Off") ||
474 (*state == "xyz.openbmc_project.State.Host."
475 "HostState.Quiesced")) &&
476 (stateTimerRunning))
477 {
478 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000479 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530480 stateTimerRunning = false;
481 }
482 }
AppaRao Pulie4e95652019-07-19 16:52:01 +0530483
484 // Update the D-Bus properties when host state changes.
485 updateDbusPropertiesCache();
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530486 }
487 });
488
489 // Capture the OS state change and stop monitor timer
490 // if OS boots completly or becomes Inactive.
491 // start timer in other cases to mnitor states.
492 static auto matchOsState = sdbusplus::bus::match::match(
493 static_cast<sdbusplus::bus::bus&>(*conn),
494 "type='signal',member='PropertiesChanged', "
495 "interface='org.freedesktop.DBus.Properties', "
496 "sender='xyz.openbmc_project.State.Chassis', "
497 "arg0namespace='xyz.openbmc_project.State.OperatingSystem.Status'",
498 [&server, &conn](sdbusplus::message::message& message) {
499 std::string intfName;
500 std::map<std::string, std::variant<std::string>> properties;
501 message.read(intfName, properties);
502
503 const auto it = properties.find("OperatingSystemState");
504 if (it != properties.end())
505 {
506 const std::string* state =
507 std::get_if<std::string>(&it->second);
508 if (state != nullptr)
509 {
510 if (((*state == "BootComplete") ||
511 (*state == "Inactive")) &&
512 (stateTimerRunning))
513 {
514 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000515 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530516 stateTimerRunning = false;
517 }
518 else if (!stateTimerRunning)
519 {
520 stateTimerRunning = true;
521 monitorPlatformStateChange(server, conn);
522 }
523 }
524 }
525 });
526
527 // First time, check and log events if any.
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000528 checkAndLogEvents(conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530529}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530530
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000531static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)
532{
533 std::string cpldVersion = pfr::readCPLDVersion();
534 conn->async_method_call(
535 [](const boost::system::error_code ec) {
536 if (ec)
537 {
538 phosphor::logging::log<phosphor::logging::level::ERR>(
539 "Unable to update cpld_active version",
540 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
541 return;
542 }
543 },
544 "xyz.openbmc_project.Settings",
545 "/xyz/openbmc_project/software/cpld_active",
546 "org.freedesktop.DBus.Properties", "Set",
547 "xyz.openbmc_project.Software.Version", "Version",
548 std::variant<std::string>(cpldVersion));
549 return;
550}
551
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000552void checkPfrInterface(std::shared_ptr<sdbusplus::asio::connection> conn)
553{
554 if (!i2cConfigLoaded)
555 {
556 init(conn, i2cConfigLoaded);
557 if (retrCount > 0)
558 {
559 // pfr object not loaded yet. query again.
560 return;
561 }
562 else
563 {
564 // Platform does not contain pfr object. Stop the service.
565 phosphor::logging::log<phosphor::logging::level::INFO>(
566 "Platform does not support PFR, hence stop the "
567 "service.");
568 std::exit(EXIT_SUCCESS);
569 return;
570 }
571 }
572 else
573 {
574 retrCount = 0;
575
576 bool locked = false;
577 bool prov = false;
578 bool support = false;
579 pfr::getProvisioningStatus(locked, prov, support);
580 if (support && prov)
581 {
582 // pfr provisioned.
583 phosphor::logging::log<phosphor::logging::level::INFO>(
584 "PFR Supported.");
585 return;
586 }
587 else
588 {
589 // pfr not supported, stop the service
590 phosphor::logging::log<phosphor::logging::level::INFO>(
591 "PFR not Supported. Hence stop the service");
592 std::exit(EXIT_SUCCESS);
593 }
594 }
595}
596void checkPFRandAddObjects(sdbusplus::asio::object_server& server,
597 std::shared_ptr<sdbusplus::asio::connection>& conn)
598{
599 checkPfrInterface(conn);
600
601 constexpr size_t timeout = 10; // seconds
602 pfrObjTimer->expires_after(std::chrono::seconds(timeout));
603 pfrObjTimer->async_wait([&conn,
604 &server](const boost::system::error_code& ec) {
605 if (ec)
606 {
607 if (ec == boost::asio::error::operation_aborted)
608 {
609 // Timer reset.
610 phosphor::logging::log<phosphor::logging::level::INFO>(
611 "pfr object found. Hence Object Timer aborted or stopped.");
612 }
613 else
614 {
615 phosphor::logging::log<phosphor::logging::level::ERR>(
616 "pfr object timer error.");
617 }
618 }
619 if (retrCount > 0)
620 {
621 checkPFRandAddObjects(server, conn);
622 }
623 else
624 {
625 pfr::monitorSignals(server, conn);
626
627 // Update the D-Bus properties.
628 updateDbusPropertiesCache();
629 // Update CPLD Version to cpld_active object in settings.
630 updateCPLDversion(conn);
631 }
632 retrCount--;
633 });
634}
AppaRao Pulidcf13122020-05-28 01:21:39 +0530635} // namespace pfr
636
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530637int main()
638{
639 // setup connection to dbus
640 boost::asio::io_service io;
641 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
AppaRao Pulidcf13122020-05-28 01:21:39 +0530642 pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
643 pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000644 pfr::pfrObjTimer = std::make_unique<boost::asio::steady_timer>(io);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530645 auto server = sdbusplus::asio::object_server(conn, true);
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000646 pfr::init(conn, pfr::i2cConfigLoaded);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000647
648 pfr::checkPFRandAddObjects(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530649
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000650 // Update CPLD Version to cpld_active object in settings.
651 pfr::updateCPLDversion(conn);
652
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530653 server.add_manager("/xyz/openbmc_project/pfr");
654
655 // Create PFR attributes object and interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530656 pfr::pfrConfigObject = std::make_unique<pfr::PfrConfig>(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530657
658 // Create Software objects using Versions interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530659 for (const auto& entry : pfr::verComponentList)
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530660 {
AppaRao Pulidcf13122020-05-28 01:21:39 +0530661 pfr::pfrVersionObjects.emplace_back(std::make_unique<pfr::PfrVersion>(
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530662 server, conn, std::get<0>(entry), std::get<1>(entry),
663 std::get<2>(entry)));
664 }
665
666 conn->request_name("xyz.openbmc_project.PFR.Manager");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530667 phosphor::logging::log<phosphor::logging::level::INFO>(
668 "Intel PFR service started successfully");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530669 io.run();
670
671 return 0;
672}