blob: 65bea78500204d7cc0a7bb94021fa37259e17327 [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;
Zhikui Renc96f37d2021-12-08 15:40:51 -080042std::unique_ptr<PfrPostcode> pfrPostcodeObject;
AppaRao Pulie4e95652019-07-19 16:52:01 +053043
AppaRao Pulie4e95652019-07-19 16:52:01 +053044// List holds <ObjPath> <ImageType> <VersionPurpose>
45static std::vector<std::tuple<std::string, ImageType, std::string>>
46 verComponentList = {
AppaRao Pulie4e95652019-07-19 16:52:01 +053047 std::make_tuple("bmc_recovery", ImageType::bmcRecovery,
48 versionPurposeBMC),
AppaRao Pulie4e95652019-07-19 16:52:01 +053049 std::make_tuple("bios_recovery", ImageType::biosRecovery,
50 versionPurposeHost),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053051 std::make_tuple("cpld_recovery", ImageType::cpldRecovery,
52 versionPurposeOther),
Vikram Bodireddy8292dc62021-05-26 13:31:47 +053053 std::make_tuple("afm_active", ImageType::afmActive,
54 versionPurposeOther),
55 std::make_tuple("afm_recovery", ImageType::afmRecovery,
56 versionPurposeOther),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053057};
AppaRao Pulie4e95652019-07-19 16:52:01 +053058
AppaRao Pulie90f1282019-11-05 01:07:05 +053059// Recovery reason map.
60// {<CPLD association>,{<Redfish MessageID>, <Recovery Reason>}}
61static const boost::container::flat_map<uint8_t,
62 std::pair<std::string, std::string>>
63 recoveryReasonMap = {
64 {0x01,
65 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000066 "BIOS active image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053067 {0x02,
68 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000069 "BIOS recovery image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053070 {0x03, {"MEFirmwareRecoveryReason", "ME launch failure"}},
71 {0x04, {"BIOSFirmwareRecoveryReason", "ACM launch failure"}},
72 {0x05, {"BIOSFirmwareRecoveryReason", "IBB launch failure"}},
73 {0x06, {"BIOSFirmwareRecoveryReason", "OBB launch failure"}},
74 {0x07,
75 {"BMCFirmwareRecoveryReason",
76 "BMC active image authentication failure"}},
77 {0x08,
78 {"BMCFirmwareRecoveryReason",
79 "BMC recovery image authentication failure"}},
80 {0x09, {"BMCFirmwareRecoveryReason", "BMC launch failure"}},
81 {0x0A, {"CPLDFirmwareRecoveryReason", "CPLD watchdog expired"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053082
AppaRao Pulie90f1282019-11-05 01:07:05 +053083// Panic Reason map.
84// {<CPLD association>, {<Redfish MessageID>, <Panic reason> })
85static const boost::container::flat_map<uint8_t,
86 std::pair<std::string, std::string>>
87 panicReasonMap = {
Chalapathi3fb544b2020-02-14 15:43:49 +000088 {0x01, {"BIOSFirmwarePanicReason", "BIOS update intent"}},
89 {0x02, {"BMCFirmwarePanicReason", "BMC update intent"}},
90 {0x03, {"BMCFirmwarePanicReason", "BMC reset detected"}},
91 {0x04, {"BMCFirmwarePanicReason", "BMC watchdog expired"}},
92 {0x05, {"MEFirmwarePanicReason", "ME watchdog expired"}},
93 {0x06, {"BIOSFirmwarePanicReason", "ACM watchdog expired"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053094 {0x09,
95 {"BIOSFirmwarePanicReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000096 "ACM or IBB or OBB authentication failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053097
AppaRao Puli24766942019-11-13 19:27:08 +053098// Firmware resiliency major map.
99// {<CPLD association>, {<Redfish MessageID>, <Error reason> })
100static const boost::container::flat_map<uint8_t,
101 std::pair<std::string, std::string>>
102 majorErrorCodeMap = {
103 {0x01,
104 {"BMCFirmwareResiliencyError", "BMC image authentication failed"}},
105 {0x02,
106 {"BIOSFirmwareResiliencyError", "BIOS image authentication failed"}},
Chalapathi3fb544b2020-02-14 15:43:49 +0000107 {0x03, {"BIOSFirmwareResiliencyError", "Update from BIOS failed"}},
108 {0x04, {"BMCFirmwareResiliencyError", "Update from BMC failed"}}};
AppaRao Puli24766942019-11-13 19:27:08 +0530109
AppaRao Pulie4e95652019-07-19 16:52:01 +0530110static void updateDbusPropertiesCache()
111{
112 for (const auto& pfrVerObj : pfrVersionObjects)
113 {
114 pfrVerObj->updateVersion();
115 }
116
117 // Update provisoningStatus properties
118 pfrConfigObject->updateProvisioningStatus();
119
120 phosphor::logging::log<phosphor::logging::level::INFO>(
121 "PFR Manager service cache data updated.");
122}
123
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530124static void logLastRecoveryEvent()
125{
126 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530127 if (0 != readCpldReg(ActionType::recoveryReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530128 {
129 return;
130 }
131
AppaRao Pulie90f1282019-11-05 01:07:05 +0530132 auto it = recoveryReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530133 if (it == recoveryReasonMap.end())
134 {
135 // No matching found. So just return without logging event.
136 return;
137 }
AppaRao Pulie90f1282019-11-05 01:07:05 +0530138 std::string msgId = "OpenBMC.0.1." + it->second.first;
139 sd_journal_send("MESSAGE=%s", "Platform firmware recovery occurred.",
140 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
141 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
142 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530143}
144
145static void logLastPanicEvent()
146{
147 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530148 if (0 != readCpldReg(ActionType::panicReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530149 {
150 return;
151 }
152
AppaRao Pulie90f1282019-11-05 01:07:05 +0530153 auto it = panicReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530154 if (it == panicReasonMap.end())
155 {
156 // No matching found. So just return without logging event.
157 return;
158 }
159
AppaRao Pulie90f1282019-11-05 01:07:05 +0530160 std::string msgId = "OpenBMC.0.1." + it->second.first;
161 sd_journal_send("MESSAGE=%s", "Platform firmware panic occurred.",
162 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
163 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
164 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530165}
166
AppaRao Puli24766942019-11-13 19:27:08 +0530167static void logResiliencyErrorEvent(const uint8_t majorErrorCode,
168 const uint8_t minorErrorCode)
169{
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000170 uint8_t cpldRoTRev = 0;
171 if (0 != readCpldReg(ActionType::readRoTRev, cpldRoTRev))
172 {
173 return;
174 }
175
AppaRao Puli24766942019-11-13 19:27:08 +0530176 auto it = majorErrorCodeMap.find(majorErrorCode);
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000177 if (cpldRoTRev == 0x02)
178 {
179 auto itRev2 = majorErrorCodeMapRev2.find(majorErrorCode);
180 if (itRev2 != majorErrorCodeMapRev2.end())
181 {
182 it = itRev2;
183 }
184 else if (it == majorErrorCodeMap.end())
185 {
186 // No matching found. So just return without logging event.
187 return;
188 }
189 }
190 else if (it == majorErrorCodeMap.end())
AppaRao Puli24766942019-11-13 19:27:08 +0530191 {
192 // No matching found. So just return without logging event.
193 return;
194 }
195
196 std::string errorStr =
197 it->second.second + "(MinorCode:0x" + toHexString(minorErrorCode) + ")";
198 std::string msgId = "OpenBMC.0.1." + it->second.first;
199 sd_journal_send(
200 "MESSAGE=%s", "Platform firmware resiliency error occurred.",
201 "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s", msgId.c_str(),
202 "REDFISH_MESSAGE_ARGS=%s", errorStr.c_str(), NULL);
203}
204
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000205static void
206 handleLastCountChange(std::shared_ptr<sdbusplus::asio::connection> conn,
207 std::string eventName, uint8_t currentCount)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530208{
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000209 sdbusplus::asio::setProperty(
210 *conn, "xyz.openbmc_project.Settings",
211 "/xyz/openbmc_project/pfr/last_events",
212 "xyz.openbmc_project.PFR.LastEvents", eventName, currentCount,
213 [](boost::system::error_code ec) {
214 if (ec)
215 {
216 phosphor::logging::log<phosphor::logging::level::ERR>(
217 "PFR: Unable to update currentCount",
218 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
219 return;
220 }
221 });
222 return;
223}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530224
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000225static void
226 checkAndLogEvents(std::shared_ptr<sdbusplus::asio::connection>& conn)
227{
228 sdbusplus::asio::getAllProperties(
229 *conn, "xyz.openbmc_project.Settings",
230 "/xyz/openbmc_project/pfr/last_events",
231 "xyz.openbmc_project.PFR.LastEvents",
232 [conn](
233 boost::system::error_code ec,
234 std::vector<
235 std::pair<std::string, std::variant<std::monostate, uint8_t>>>&
236 properties) {
237 if (ec)
238 {
239 phosphor::logging::log<phosphor::logging::level::ERR>(
240 "PFR: Unable get PFR last events",
241 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
242 return;
243 }
244 uint8_t lastRecoveryCount = 0;
245 uint8_t lastPanicCount = 0;
246 uint8_t lastMajorErr = 0;
247 uint8_t lastMinorErr = 0;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530248
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000249 try
250 {
251 sdbusplus::unpackProperties(
252 properties, "lastRecoveryCount", lastRecoveryCount,
253 "lastPanicCount", lastPanicCount, "lastMajorErr",
254 lastMajorErr, "lastMinorErr", lastMinorErr);
255 }
256 catch (const sdbusplus::exception::UnpackPropertyError& error)
257 {
258 phosphor::logging::log<phosphor::logging::level::ERR>(
259 "PFR: Unpack error",
260 phosphor::logging::entry("MSG=%s", error.what()));
261 return;
262 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530263
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000264 uint8_t currPanicCount = 0;
265 if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
266 {
267 if (lastPanicCount != currPanicCount)
268 {
269 // Update cached data to dbus and log redfish
270 // event by reading reason.
271 handleLastCountChange(conn, "lastPanicCount",
272 currPanicCount);
273 if (currPanicCount)
274 {
275 logLastPanicEvent();
276 }
277 }
278 }
279
280 uint8_t currRecoveryCount = 0;
281 if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
282 {
283 if (lastRecoveryCount != currRecoveryCount)
284 {
285 // Update cached data to dbus and log redfish
286 // event by reading reason.
287 handleLastCountChange(conn, "lastRecoveryCount",
288 currRecoveryCount);
289 if (currRecoveryCount)
290 {
291 logLastRecoveryEvent();
292 }
293 }
294 }
295
296 uint8_t majorErr = 0;
297 uint8_t minorErr = 0;
298 if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
299 (0 == readCpldReg(ActionType::minorError, minorErr)))
300 {
301 if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
302 {
303 // Update cached data to dbus and log redfish event by
304 // reading reason.
305 handleLastCountChange(conn, "lastMajorErr", majorErr);
306 handleLastCountChange(conn, "lastMinorErr", minorErr);
307 if (majorErr && minorErr)
308 {
309 logResiliencyErrorEvent(majorErr, minorErr);
310 }
311 }
312 }
313 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530314}
315
316static void monitorPlatformStateChange(
317 sdbusplus::asio::object_server& server,
318 std::shared_ptr<sdbusplus::asio::connection>& conn)
319{
320 constexpr size_t pollTimeout = 10; // seconds
321 stateTimer->expires_after(std::chrono::seconds(pollTimeout));
322 stateTimer->async_wait(
323 [&server, &conn](const boost::system::error_code& ec) {
324 if (ec == boost::asio::error::operation_aborted)
325 {
326 // Timer reset.
327 return;
328 }
329 if (ec)
330 {
331 // Platform State Monitor - Timer cancelled.
332 return;
333 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000334 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530335 monitorPlatformStateChange(server, conn);
336 });
337}
338
AppaRao Puli46cead92019-07-22 16:50:09 +0530339void checkAndSetCheckpoint(sdbusplus::asio::object_server& server,
340 std::shared_ptr<sdbusplus::asio::connection>& conn)
341{
342 // Check whether systemd completed all the loading.
343 conn->async_method_call(
344 [&server, &conn](boost::system::error_code ec,
345 const std::variant<uint64_t>& value) {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530346 if (!ec)
AppaRao Puli46cead92019-07-22 16:50:09 +0530347 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530348 if (std::get<uint64_t>(value))
AppaRao Puli46cead92019-07-22 16:50:09 +0530349 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530350 phosphor::logging::log<phosphor::logging::level::INFO>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000351 "BMC boot completed. Setting checkpoint 9.");
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530352 if (!finishedSettingChkPoint)
353 {
354 finishedSettingChkPoint = true;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530355 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530356 }
357 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530358 }
359 }
360 else
361 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530362 // Failed to get data from systemd. System might not
363 // be ready yet. Attempt again for data.
364 phosphor::logging::log<phosphor::logging::level::ERR>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000365 "aync call failed to get FinishTimestamp.",
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530366 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
AppaRao Puli46cead92019-07-22 16:50:09 +0530367 }
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530368 // FIX-ME: Latest up-stream sync caused issue in receiving
369 // StartupFinished signal. Unable to get StartupFinished signal
370 // from systemd1 hence using poll method too, to trigger it
371 // properly.
372 constexpr size_t pollTimeout = 10; // seconds
373 initTimer->expires_after(std::chrono::seconds(pollTimeout));
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000374 initTimer->async_wait(
375 [&server, &conn](const boost::system::error_code& ec) {
376 if (ec == boost::asio::error::operation_aborted)
377 {
378 // Timer reset.
379 phosphor::logging::log<phosphor::logging::level::INFO>(
380 "Set boot Checkpoint - Timer aborted or stopped.");
381 return;
382 }
383 if (ec)
384 {
385 phosphor::logging::log<phosphor::logging::level::ERR>(
386 "Set boot Checkpoint - async wait error.");
387 return;
388 }
389 checkAndSetCheckpoint(server, conn);
390 });
AppaRao Puli46cead92019-07-22 16:50:09 +0530391 },
392 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
393 "org.freedesktop.DBus.Properties", "Get",
394 "org.freedesktop.systemd1.Manager", "FinishTimestamp");
395}
396
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530397void monitorSignals(sdbusplus::asio::object_server& server,
398 std::shared_ptr<sdbusplus::asio::connection>& conn)
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530399{
AppaRao Puli46cead92019-07-22 16:50:09 +0530400 // Monitor Boot finished signal and set the checkpoint 9 to
401 // notify CPLD about BMC boot finish.
402 auto bootFinishedSignal = std::make_unique<sdbusplus::bus::match::match>(
403 static_cast<sdbusplus::bus::bus&>(*conn),
404 "type='signal',"
405 "member='StartupFinished',path='/org/freedesktop/systemd1',"
406 "interface='org.freedesktop.systemd1.Manager'",
407 [&server, &conn](sdbusplus::message::message& msg) {
408 if (!finishedSettingChkPoint)
409 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530410 phosphor::logging::log<phosphor::logging::level::INFO>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000411 "BMC boot completed(StartupFinished). Setting "
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530412 "checkpoint 9.");
AppaRao Puli46cead92019-07-22 16:50:09 +0530413 finishedSettingChkPoint = true;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530414 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Puli46cead92019-07-22 16:50:09 +0530415 }
416 });
417 checkAndSetCheckpoint(server, conn);
418
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530419 // Capture the Chassis state and Start the monitor timer
420 // if state changed to 'On'. Run timer until OS boot.
421 // Stop timer if state changed to 'Off'.
422 static auto matchChassisState = sdbusplus::bus::match::match(
423 static_cast<sdbusplus::bus::bus&>(*conn),
424 "type='signal',member='PropertiesChanged', "
425 "interface='org.freedesktop.DBus.Properties', "
426 "sender='xyz.openbmc_project.State.Chassis', "
427 "arg0namespace='xyz.openbmc_project.State.Chassis'",
428 [&server, &conn](sdbusplus::message::message& message) {
429 std::string intfName;
430 std::map<std::string, std::variant<std::string>> properties;
431 message.read(intfName, properties);
432
433 const auto it = properties.find("CurrentPowerState");
434 if (it != properties.end())
435 {
436 const std::string* state =
437 std::get_if<std::string>(&it->second);
438 if (state != nullptr)
439 {
440 if ((*state ==
441 "xyz.openbmc_project.State.Chassis.PowerState.On") &&
442 (!stateTimerRunning))
443 {
444 stateTimerRunning = true;
445 monitorPlatformStateChange(server, conn);
446 }
447 else if ((*state == "xyz.openbmc_project.State.Chassis."
448 "PowerState.Off") &&
449 (stateTimerRunning))
450 {
451 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000452 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530453 stateTimerRunning = false;
454 }
455 }
AppaRao Pulie4e95652019-07-19 16:52:01 +0530456
457 // Update the D-Bus properties when chassis state changes.
458 updateDbusPropertiesCache();
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530459 }
460 });
461
462 // Capture the Host state and Start the monitor timer
463 // if state changed to 'Running'. Run timer until OS boot.
464 // Stop timer if state changed to 'Off'.
465 static auto matchHostState = sdbusplus::bus::match::match(
466 static_cast<sdbusplus::bus::bus&>(*conn),
467 "type='signal',member='PropertiesChanged', "
468 "interface='org.freedesktop.DBus.Properties', "
469 "sender='xyz.openbmc_project.State.Chassis', "
470 "arg0namespace='xyz.openbmc_project.State.Host'",
471 [&server, &conn](sdbusplus::message::message& message) {
472 std::string intfName;
473 std::map<std::string, std::variant<std::string>> properties;
474 message.read(intfName, properties);
475
476 const auto it = properties.find("CurrentHostState");
477 if (it != properties.end())
478 {
479 const std::string* state =
480 std::get_if<std::string>(&it->second);
481 if (state != nullptr)
482 {
483 if ((*state ==
484 "xyz.openbmc_project.State.Host.HostState.Running") &&
485 (!stateTimerRunning))
486 {
487 stateTimerRunning = true;
488 monitorPlatformStateChange(server, conn);
489 }
490 else if (((*state == "xyz.openbmc_project.State.Host."
491 "HostState.Off") ||
492 (*state == "xyz.openbmc_project.State.Host."
493 "HostState.Quiesced")) &&
494 (stateTimerRunning))
495 {
496 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000497 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530498 stateTimerRunning = false;
499 }
500 }
AppaRao Pulie4e95652019-07-19 16:52:01 +0530501
502 // Update the D-Bus properties when host state changes.
503 updateDbusPropertiesCache();
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530504 }
505 });
506
507 // Capture the OS state change and stop monitor timer
508 // if OS boots completly or becomes Inactive.
509 // start timer in other cases to mnitor states.
510 static auto matchOsState = sdbusplus::bus::match::match(
511 static_cast<sdbusplus::bus::bus&>(*conn),
512 "type='signal',member='PropertiesChanged', "
513 "interface='org.freedesktop.DBus.Properties', "
514 "sender='xyz.openbmc_project.State.Chassis', "
515 "arg0namespace='xyz.openbmc_project.State.OperatingSystem.Status'",
516 [&server, &conn](sdbusplus::message::message& message) {
517 std::string intfName;
518 std::map<std::string, std::variant<std::string>> properties;
519 message.read(intfName, properties);
520
521 const auto it = properties.find("OperatingSystemState");
522 if (it != properties.end())
523 {
524 const std::string* state =
525 std::get_if<std::string>(&it->second);
526 if (state != nullptr)
527 {
Jason M. Billsf89de472022-01-19 16:14:19 -0800528 // The short strings "BootComplete" and "Standby" are
529 // deprecated in favor of the full enum strings
530 // Support for the short strings will be removed in the
531 // future.
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530532 if (((*state == "BootComplete") ||
Jason M. Billsf89de472022-01-19 16:14:19 -0800533 (*state == "xyz.openbmc_project.State.OperatingSystem."
534 "Status.OSStatus.BootComplete") ||
535 (*state == "Inactive") ||
536 (*state == "xyz.openbmc_project.State.OperatingSystem."
537 "Status.OSStatus.Inactive")) &&
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530538 (stateTimerRunning))
539 {
540 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000541 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530542 stateTimerRunning = false;
543 }
544 else if (!stateTimerRunning)
545 {
546 stateTimerRunning = true;
547 monitorPlatformStateChange(server, conn);
548 }
549 }
550 }
551 });
552
553 // First time, check and log events if any.
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000554 checkAndLogEvents(conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530555}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530556
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000557static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)
558{
559 std::string cpldVersion = pfr::readCPLDVersion();
Alex Schendel5cf320c2021-12-09 12:11:04 -0800560 lg2::info("VERSION INFO - cpld_active - {VER}", "VER", cpldVersion);
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000561 conn->async_method_call(
562 [](const boost::system::error_code ec) {
563 if (ec)
564 {
565 phosphor::logging::log<phosphor::logging::level::ERR>(
566 "Unable to update cpld_active version",
567 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
568 return;
569 }
570 },
571 "xyz.openbmc_project.Settings",
572 "/xyz/openbmc_project/software/cpld_active",
573 "org.freedesktop.DBus.Properties", "Set",
574 "xyz.openbmc_project.Software.Version", "Version",
575 std::variant<std::string>(cpldVersion));
576 return;
577}
578
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000579void checkPfrInterface(std::shared_ptr<sdbusplus::asio::connection> conn)
580{
581 if (!i2cConfigLoaded)
582 {
583 init(conn, i2cConfigLoaded);
584 if (retrCount > 0)
585 {
586 // pfr object not loaded yet. query again.
587 return;
588 }
589 else
590 {
591 // Platform does not contain pfr object. Stop the service.
592 phosphor::logging::log<phosphor::logging::level::INFO>(
593 "Platform does not support PFR, hence stop the "
594 "service.");
595 std::exit(EXIT_SUCCESS);
596 return;
597 }
598 }
599 else
600 {
601 retrCount = 0;
602
603 bool locked = false;
604 bool prov = false;
605 bool support = false;
606 pfr::getProvisioningStatus(locked, prov, support);
607 if (support && prov)
608 {
609 // pfr provisioned.
610 phosphor::logging::log<phosphor::logging::level::INFO>(
611 "PFR Supported.");
612 return;
613 }
614 else
615 {
616 // pfr not supported, stop the service
617 phosphor::logging::log<phosphor::logging::level::INFO>(
618 "PFR not Supported. Hence stop the service");
619 std::exit(EXIT_SUCCESS);
620 }
621 }
622}
623void checkPFRandAddObjects(sdbusplus::asio::object_server& server,
624 std::shared_ptr<sdbusplus::asio::connection>& conn)
625{
626 checkPfrInterface(conn);
627
628 constexpr size_t timeout = 10; // seconds
629 pfrObjTimer->expires_after(std::chrono::seconds(timeout));
630 pfrObjTimer->async_wait([&conn,
631 &server](const boost::system::error_code& ec) {
632 if (ec)
633 {
634 if (ec == boost::asio::error::operation_aborted)
635 {
636 // Timer reset.
637 phosphor::logging::log<phosphor::logging::level::INFO>(
638 "pfr object found. Hence Object Timer aborted or stopped.");
639 }
640 else
641 {
642 phosphor::logging::log<phosphor::logging::level::ERR>(
643 "pfr object timer error.");
644 }
645 }
646 if (retrCount > 0)
647 {
648 checkPFRandAddObjects(server, conn);
649 }
650 else
651 {
652 pfr::monitorSignals(server, conn);
653
654 // Update the D-Bus properties.
655 updateDbusPropertiesCache();
656 // Update CPLD Version to cpld_active object in settings.
657 updateCPLDversion(conn);
658 }
659 retrCount--;
660 });
661}
AppaRao Pulidcf13122020-05-28 01:21:39 +0530662} // namespace pfr
663
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530664int main()
665{
666 // setup connection to dbus
667 boost::asio::io_service io;
668 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
AppaRao Pulidcf13122020-05-28 01:21:39 +0530669 pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
670 pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000671 pfr::pfrObjTimer = std::make_unique<boost::asio::steady_timer>(io);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530672 auto server = sdbusplus::asio::object_server(conn, true);
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000673 pfr::init(conn, pfr::i2cConfigLoaded);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000674
675 pfr::checkPFRandAddObjects(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530676
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000677 // Update CPLD Version to cpld_active object in settings.
678 pfr::updateCPLDversion(conn);
679
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530680 server.add_manager("/xyz/openbmc_project/pfr");
681
682 // Create PFR attributes object and interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530683 pfr::pfrConfigObject = std::make_unique<pfr::PfrConfig>(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530684
685 // Create Software objects using Versions interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530686 for (const auto& entry : pfr::verComponentList)
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530687 {
AppaRao Pulidcf13122020-05-28 01:21:39 +0530688 pfr::pfrVersionObjects.emplace_back(std::make_unique<pfr::PfrVersion>(
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530689 server, conn, std::get<0>(entry), std::get<1>(entry),
690 std::get<2>(entry)));
691 }
692
Zhikui Renc96f37d2021-12-08 15:40:51 -0800693 if (pfr::pfrConfigObject)
694 {
695 pfr::pfrConfigObject->updateProvisioningStatus();
696 if (pfr::pfrConfigObject->getPfrProvisioned())
697 {
698 pfr::pfrPostcodeObject =
699 std::make_unique<pfr::PfrPostcode>(server, conn);
700 }
701 }
702
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530703 conn->request_name("xyz.openbmc_project.PFR.Manager");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530704 phosphor::logging::log<phosphor::logging::level::INFO>(
705 "Intel PFR service started successfully");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530706 io.run();
707
708 return 0;
709}