blob: 428b0f7a738ab9ca9acdc916f83e89afca80fc80 [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"}},
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +000081 {0x0A, {"CPLDFirmwareRecoveryReason", "CPLD watchdog expired"}},
82 {0x0B, {"BMCFirmwareRecoveryReason", "BMC attestation failure"}},
83 {0x0C, {"FirmwareResiliencyError", "CPU0 attestation failure"}},
84 {0x0D, {"FirmwareResiliencyError", "CPU1 attestation failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053085
AppaRao Pulie90f1282019-11-05 01:07:05 +053086// Panic Reason map.
87// {<CPLD association>, {<Redfish MessageID>, <Panic reason> })
88static const boost::container::flat_map<uint8_t,
89 std::pair<std::string, std::string>>
90 panicReasonMap = {
Chalapathi3fb544b2020-02-14 15:43:49 +000091 {0x01, {"BIOSFirmwarePanicReason", "BIOS update intent"}},
92 {0x02, {"BMCFirmwarePanicReason", "BMC update intent"}},
93 {0x03, {"BMCFirmwarePanicReason", "BMC reset detected"}},
94 {0x04, {"BMCFirmwarePanicReason", "BMC watchdog expired"}},
95 {0x05, {"MEFirmwarePanicReason", "ME watchdog expired"}},
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +000096 {0x06, {"BIOSFirmwarePanicReason", "ACM/IBB/OBB WDT expired"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053097 {0x09,
98 {"BIOSFirmwarePanicReason",
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +000099 "ACM or IBB or OBB authentication failure"}},
100 {0x0A, {"FirmwareResiliencyError", "Attestation failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530101
AppaRao Puli24766942019-11-13 19:27:08 +0530102// Firmware resiliency major map.
103// {<CPLD association>, {<Redfish MessageID>, <Error reason> })
104static const boost::container::flat_map<uint8_t,
105 std::pair<std::string, std::string>>
106 majorErrorCodeMap = {
107 {0x01,
108 {"BMCFirmwareResiliencyError", "BMC image authentication failed"}},
109 {0x02,
110 {"BIOSFirmwareResiliencyError", "BIOS image authentication failed"}},
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +0000111 {0x03,
112 {"BIOSFirmwareResiliencyError", "in-band and oob update failure"}},
113 {0x04, {"BMCFirmwareResiliencyError", "Communication setup failed"}},
114 {0x05,
115 {"FirmwareResiliencyError",
116 "Attestation measurement mismatch-Attestation failure"}},
117 {0x06, {"FirmwareResiliencyError", "Attestation challenge timeout"}},
118 {0x07, {"FirmwareResiliencyError", "SPDM protocol timeout"}},
119 {0x08, {"FirmwareResiliencyError", "I2c Communication failure"}},
120 {0x09,
121 {"CPLDFirmwareResiliencyError",
122 "Combined CPLD authentication failure"}},
123 {0x0A, {"CPLDFirmwareResiliencyError", "Combined CPLD update failure"}},
124 {0x0B,
125 {"CPLDFirmwareResiliencyError", "Combined CPLD recovery failure"}},
126 {0x10, {"FirmwareResiliencyError", "Image copy Failed"}}};
AppaRao Puli24766942019-11-13 19:27:08 +0530127
AppaRao Pulie4e95652019-07-19 16:52:01 +0530128static void updateDbusPropertiesCache()
129{
130 for (const auto& pfrVerObj : pfrVersionObjects)
131 {
132 pfrVerObj->updateVersion();
133 }
134
135 // Update provisoningStatus properties
136 pfrConfigObject->updateProvisioningStatus();
137
138 phosphor::logging::log<phosphor::logging::level::INFO>(
139 "PFR Manager service cache data updated.");
140}
141
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530142static void logLastRecoveryEvent()
143{
144 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530145 if (0 != readCpldReg(ActionType::recoveryReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530146 {
147 return;
148 }
149
AppaRao Pulie90f1282019-11-05 01:07:05 +0530150 auto it = recoveryReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530151 if (it == recoveryReasonMap.end())
152 {
153 // No matching found. So just return without logging event.
154 return;
155 }
AppaRao Pulie90f1282019-11-05 01:07:05 +0530156 std::string msgId = "OpenBMC.0.1." + it->second.first;
157 sd_journal_send("MESSAGE=%s", "Platform firmware recovery occurred.",
158 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
159 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
160 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530161}
162
163static void logLastPanicEvent()
164{
165 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530166 if (0 != readCpldReg(ActionType::panicReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530167 {
168 return;
169 }
170
AppaRao Pulie90f1282019-11-05 01:07:05 +0530171 auto it = panicReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530172 if (it == panicReasonMap.end())
173 {
174 // No matching found. So just return without logging event.
175 return;
176 }
177
AppaRao Pulie90f1282019-11-05 01:07:05 +0530178 std::string msgId = "OpenBMC.0.1." + it->second.first;
179 sd_journal_send("MESSAGE=%s", "Platform firmware panic occurred.",
180 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
181 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
182 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530183}
184
AppaRao Puli24766942019-11-13 19:27:08 +0530185static void logResiliencyErrorEvent(const uint8_t majorErrorCode,
186 const uint8_t minorErrorCode)
187{
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000188 uint8_t cpldRoTRev = 0;
189 if (0 != readCpldReg(ActionType::readRoTRev, cpldRoTRev))
190 {
191 return;
192 }
193
AppaRao Puli24766942019-11-13 19:27:08 +0530194 auto it = majorErrorCodeMap.find(majorErrorCode);
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000195 if (cpldRoTRev == 0x02)
196 {
197 auto itRev2 = majorErrorCodeMapRev2.find(majorErrorCode);
198 if (itRev2 != majorErrorCodeMapRev2.end())
199 {
200 it = itRev2;
201 }
202 else if (it == majorErrorCodeMap.end())
203 {
204 // No matching found. So just return without logging event.
205 return;
206 }
207 }
208 else if (it == majorErrorCodeMap.end())
AppaRao Puli24766942019-11-13 19:27:08 +0530209 {
210 // No matching found. So just return without logging event.
211 return;
212 }
213
Patrick Williams304e82e2023-05-10 07:51:13 -0500214 std::string errorStr = it->second.second + "(MinorCode:0x" +
215 toHexString(minorErrorCode) + ")";
AppaRao Puli24766942019-11-13 19:27:08 +0530216 std::string msgId = "OpenBMC.0.1." + it->second.first;
217 sd_journal_send(
218 "MESSAGE=%s", "Platform firmware resiliency error occurred.",
219 "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s", msgId.c_str(),
220 "REDFISH_MESSAGE_ARGS=%s", errorStr.c_str(), NULL);
221}
222
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000223static void
224 handleLastCountChange(std::shared_ptr<sdbusplus::asio::connection> conn,
225 std::string eventName, uint8_t currentCount)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530226{
Patrick Williams304e82e2023-05-10 07:51:13 -0500227 sdbusplus::asio::setProperty(*conn, "xyz.openbmc_project.Settings",
228 "/xyz/openbmc_project/pfr/last_events",
229 "xyz.openbmc_project.PFR.LastEvents",
230 eventName, currentCount,
231 [](boost::system::error_code ec) {
232 if (ec)
233 {
234 phosphor::logging::log<phosphor::logging::level::ERR>(
235 "PFR: Unable to update currentCount",
236 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
237 return;
238 }
239 });
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000240 return;
241}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530242
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000243static void
244 checkAndLogEvents(std::shared_ptr<sdbusplus::asio::connection>& conn)
245{
246 sdbusplus::asio::getAllProperties(
247 *conn, "xyz.openbmc_project.Settings",
248 "/xyz/openbmc_project/pfr/last_events",
249 "xyz.openbmc_project.PFR.LastEvents",
250 [conn](
251 boost::system::error_code ec,
Jonathan Doman9b7b9f72022-06-03 15:31:35 -0700252 const std::vector<
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000253 std::pair<std::string, std::variant<std::monostate, uint8_t>>>&
254 properties) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500255 if (ec)
256 {
257 phosphor::logging::log<phosphor::logging::level::ERR>(
258 "PFR: Unable get PFR last events",
259 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
260 return;
261 }
262 uint8_t lastRecoveryCount = 0;
263 uint8_t lastPanicCount = 0;
264 uint8_t lastMajorErr = 0;
265 uint8_t lastMinorErr = 0;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530266
Patrick Williams304e82e2023-05-10 07:51:13 -0500267 try
268 {
269 sdbusplus::unpackProperties(
270 properties, "lastRecoveryCount", lastRecoveryCount,
271 "lastPanicCount", lastPanicCount, "lastMajorErr", lastMajorErr,
272 "lastMinorErr", lastMinorErr);
273 }
274 catch (const sdbusplus::exception::UnpackPropertyError& error)
275 {
276 phosphor::logging::log<phosphor::logging::level::ERR>(
277 "PFR: Unpack error",
278 phosphor::logging::entry("MSG=%s", error.what()));
279 return;
280 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530281
Patrick Williams304e82e2023-05-10 07:51:13 -0500282 uint8_t currPanicCount = 0;
283 if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
284 {
285 if (lastPanicCount != currPanicCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000286 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500287 // Update cached data to dbus and log redfish
288 // event by reading reason.
289 handleLastCountChange(conn, "lastPanicCount", currPanicCount);
290 if (currPanicCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000291 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500292 logLastPanicEvent();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000293 }
294 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500295 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000296
Patrick Williams304e82e2023-05-10 07:51:13 -0500297 uint8_t currRecoveryCount = 0;
298 if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
299 {
300 if (lastRecoveryCount != currRecoveryCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000301 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500302 // Update cached data to dbus and log redfish
303 // event by reading reason.
304 handleLastCountChange(conn, "lastRecoveryCount",
305 currRecoveryCount);
306 if (currRecoveryCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000307 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500308 logLastRecoveryEvent();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000309 }
310 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500311 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000312
Patrick Williams304e82e2023-05-10 07:51:13 -0500313 uint8_t majorErr = 0;
314 uint8_t minorErr = 0;
315 if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
316 (0 == readCpldReg(ActionType::minorError, minorErr)))
317 {
318 if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000319 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500320 // Update cached data to dbus and log redfish event by
321 // reading reason.
322 handleLastCountChange(conn, "lastMajorErr", majorErr);
323 handleLastCountChange(conn, "lastMinorErr", minorErr);
324 if (majorErr && minorErr)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000325 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500326 logResiliencyErrorEvent(majorErr, minorErr);
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000327 }
328 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500329 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000330 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530331}
332
333static void monitorPlatformStateChange(
334 sdbusplus::asio::object_server& server,
335 std::shared_ptr<sdbusplus::asio::connection>& conn)
336{
337 constexpr size_t pollTimeout = 10; // seconds
338 stateTimer->expires_after(std::chrono::seconds(pollTimeout));
339 stateTimer->async_wait(
340 [&server, &conn](const boost::system::error_code& ec) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500341 if (ec == boost::asio::error::operation_aborted)
342 {
343 // Timer reset.
344 return;
345 }
346 if (ec)
347 {
348 // Platform State Monitor - Timer cancelled.
349 return;
350 }
351 checkAndLogEvents(conn);
352 monitorPlatformStateChange(server, conn);
353 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530354}
355
AppaRao Puli46cead92019-07-22 16:50:09 +0530356void checkAndSetCheckpoint(sdbusplus::asio::object_server& server,
357 std::shared_ptr<sdbusplus::asio::connection>& conn)
358{
359 // Check whether systemd completed all the loading.
360 conn->async_method_call(
361 [&server, &conn](boost::system::error_code ec,
362 const std::variant<uint64_t>& value) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500363 if (!ec)
364 {
365 if (std::get<uint64_t>(value))
AppaRao Puli46cead92019-07-22 16:50:09 +0530366 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500367 phosphor::logging::log<phosphor::logging::level::INFO>(
368 "BMC boot completed. Setting checkpoint 9.");
369 if (!finishedSettingChkPoint)
AppaRao Puli46cead92019-07-22 16:50:09 +0530370 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500371 finishedSettingChkPoint = true;
372 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Puli46cead92019-07-22 16:50:09 +0530373 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500374 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530375 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500376 }
377 else
378 {
379 // Failed to get data from systemd. System might not
380 // be ready yet. Attempt again for data.
381 phosphor::logging::log<phosphor::logging::level::ERR>(
382 "aync call failed to get FinishTimestamp.",
383 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
384 }
385 // FIX-ME: Latest up-stream sync caused issue in receiving
386 // StartupFinished signal. Unable to get StartupFinished signal
387 // from systemd1 hence using poll method too, to trigger it
388 // properly.
389 constexpr size_t pollTimeout = 10; // seconds
390 initTimer->expires_after(std::chrono::seconds(pollTimeout));
391 initTimer->async_wait(
392 [&server, &conn](const boost::system::error_code& ec) {
393 if (ec == boost::asio::error::operation_aborted)
AppaRao Puli46cead92019-07-22 16:50:09 +0530394 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500395 // Timer reset.
396 phosphor::logging::log<phosphor::logging::level::INFO>(
397 "Set boot Checkpoint - Timer aborted or stopped.");
398 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530399 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500400 if (ec)
401 {
402 phosphor::logging::log<phosphor::logging::level::ERR>(
403 "Set boot Checkpoint - async wait error.");
404 return;
405 }
406 checkAndSetCheckpoint(server, conn);
407 });
AppaRao Puli46cead92019-07-22 16:50:09 +0530408 },
409 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
410 "org.freedesktop.DBus.Properties", "Get",
411 "org.freedesktop.systemd1.Manager", "FinishTimestamp");
412}
413
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530414void monitorSignals(sdbusplus::asio::object_server& server,
415 std::shared_ptr<sdbusplus::asio::connection>& conn)
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530416{
AppaRao Puli46cead92019-07-22 16:50:09 +0530417 // Monitor Boot finished signal and set the checkpoint 9 to
418 // notify CPLD about BMC boot finish.
Patrick Williamsf01de222022-07-22 19:26:57 -0500419 auto bootFinishedSignal = std::make_unique<sdbusplus::bus::match_t>(
420 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli46cead92019-07-22 16:50:09 +0530421 "type='signal',"
422 "member='StartupFinished',path='/org/freedesktop/systemd1',"
423 "interface='org.freedesktop.systemd1.Manager'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500424 [&server, &conn](sdbusplus::message_t& msg) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500425 if (!finishedSettingChkPoint)
426 {
427 phosphor::logging::log<phosphor::logging::level::INFO>(
428 "BMC boot completed(StartupFinished). Setting "
429 "checkpoint 9.");
430 finishedSettingChkPoint = true;
431 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
432 }
AppaRao Puli46cead92019-07-22 16:50:09 +0530433 });
434 checkAndSetCheckpoint(server, conn);
435
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530436 // Capture the Chassis state and Start the monitor timer
437 // if state changed to 'On'. Run timer until OS boot.
438 // Stop timer if state changed to 'Off'.
Patrick Williamsf01de222022-07-22 19:26:57 -0500439 static auto matchChassisState = sdbusplus::bus::match_t(
440 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530441 "type='signal',member='PropertiesChanged', "
442 "interface='org.freedesktop.DBus.Properties', "
443 "sender='xyz.openbmc_project.State.Chassis', "
444 "arg0namespace='xyz.openbmc_project.State.Chassis'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500445 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500446 std::string intfName;
447 std::map<std::string, std::variant<std::string>> properties;
448 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530449
Patrick Williams304e82e2023-05-10 07:51:13 -0500450 const auto it = properties.find("CurrentPowerState");
451 if (it != properties.end())
452 {
453 const std::string* state = std::get_if<std::string>(&it->second);
454 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530455 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500456 if ((*state ==
457 "xyz.openbmc_project.State.Chassis.PowerState.On") &&
458 (!stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530459 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500460 stateTimerRunning = true;
461 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530462 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500463 else if ((*state == "xyz.openbmc_project.State.Chassis."
464 "PowerState.Off") &&
465 (stateTimerRunning))
466 {
467 stateTimer->cancel();
468 checkAndLogEvents(conn);
469 stateTimerRunning = false;
470 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530471 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500472
473 // Update the D-Bus properties when chassis state changes.
474 updateDbusPropertiesCache();
475 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530476 });
477
478 // Capture the Host state and Start the monitor timer
479 // if state changed to 'Running'. Run timer until OS boot.
480 // Stop timer if state changed to 'Off'.
Patrick Williamsf01de222022-07-22 19:26:57 -0500481 static auto matchHostState = sdbusplus::bus::match_t(
482 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530483 "type='signal',member='PropertiesChanged', "
484 "interface='org.freedesktop.DBus.Properties', "
485 "sender='xyz.openbmc_project.State.Chassis', "
486 "arg0namespace='xyz.openbmc_project.State.Host'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500487 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500488 std::string intfName;
489 std::map<std::string, std::variant<std::string>> properties;
490 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530491
Patrick Williams304e82e2023-05-10 07:51:13 -0500492 const auto it = properties.find("CurrentHostState");
493 if (it != properties.end())
494 {
495 const std::string* state = std::get_if<std::string>(&it->second);
496 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530497 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500498 if ((*state ==
499 "xyz.openbmc_project.State.Host.HostState.Running") &&
500 (!stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530501 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500502 stateTimerRunning = true;
503 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530504 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500505 else if (((*state == "xyz.openbmc_project.State.Host."
506 "HostState.Off") ||
507 (*state == "xyz.openbmc_project.State.Host."
508 "HostState.Quiesced")) &&
509 (stateTimerRunning))
510 {
511 stateTimer->cancel();
512 checkAndLogEvents(conn);
513 stateTimerRunning = false;
514 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530515 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500516
517 // Update the D-Bus properties when host state changes.
518 updateDbusPropertiesCache();
519 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530520 });
521
522 // Capture the OS state change and stop monitor timer
523 // if OS boots completly or becomes Inactive.
524 // start timer in other cases to mnitor states.
Patrick Williamsf01de222022-07-22 19:26:57 -0500525 static auto matchOsState = sdbusplus::bus::match_t(
526 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530527 "type='signal',member='PropertiesChanged', "
528 "interface='org.freedesktop.DBus.Properties', "
529 "sender='xyz.openbmc_project.State.Chassis', "
530 "arg0namespace='xyz.openbmc_project.State.OperatingSystem.Status'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500531 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500532 std::string intfName;
533 std::map<std::string, std::variant<std::string>> properties;
534 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530535
Patrick Williams304e82e2023-05-10 07:51:13 -0500536 const auto it = properties.find("OperatingSystemState");
537 if (it != properties.end())
538 {
539 const std::string* state = std::get_if<std::string>(&it->second);
540 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530541 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500542 // The short strings "BootComplete" and "Standby" are
543 // deprecated in favor of the full enum strings
544 // Support for the short strings will be removed in the
545 // future.
546 if (((*state == "BootComplete") ||
547 (*state == "xyz.openbmc_project.State.OperatingSystem."
548 "Status.OSStatus.BootComplete") ||
549 (*state == "Inactive") ||
550 (*state == "xyz.openbmc_project.State.OperatingSystem."
551 "Status.OSStatus.Inactive")) &&
552 (stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530553 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500554 stateTimer->cancel();
555 checkAndLogEvents(conn);
556 stateTimerRunning = false;
557 }
558 else if (!stateTimerRunning)
559 {
560 stateTimerRunning = true;
561 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530562 }
563 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500564 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530565 });
566
567 // First time, check and log events if any.
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000568 checkAndLogEvents(conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530569}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530570
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000571static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)
572{
573 std::string cpldVersion = pfr::readCPLDVersion();
Alex Schendel5cf320c2021-12-09 12:11:04 -0800574 lg2::info("VERSION INFO - cpld_active - {VER}", "VER", cpldVersion);
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000575 conn->async_method_call(
576 [](const boost::system::error_code ec) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500577 if (ec)
578 {
579 phosphor::logging::log<phosphor::logging::level::ERR>(
580 "Unable to update cpld_active version",
581 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
582 return;
583 }
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000584 },
585 "xyz.openbmc_project.Settings",
586 "/xyz/openbmc_project/software/cpld_active",
587 "org.freedesktop.DBus.Properties", "Set",
588 "xyz.openbmc_project.Software.Version", "Version",
589 std::variant<std::string>(cpldVersion));
590 return;
591}
592
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000593void checkPfrInterface(std::shared_ptr<sdbusplus::asio::connection> conn)
594{
595 if (!i2cConfigLoaded)
596 {
597 init(conn, i2cConfigLoaded);
598 if (retrCount > 0)
599 {
600 // pfr object not loaded yet. query again.
601 return;
602 }
603 else
604 {
605 // Platform does not contain pfr object. Stop the service.
606 phosphor::logging::log<phosphor::logging::level::INFO>(
607 "Platform does not support PFR, hence stop the "
608 "service.");
609 std::exit(EXIT_SUCCESS);
610 return;
611 }
612 }
613 else
614 {
615 retrCount = 0;
616
617 bool locked = false;
618 bool prov = false;
619 bool support = false;
620 pfr::getProvisioningStatus(locked, prov, support);
621 if (support && prov)
622 {
623 // pfr provisioned.
624 phosphor::logging::log<phosphor::logging::level::INFO>(
625 "PFR Supported.");
626 return;
627 }
628 else
629 {
630 // pfr not supported, stop the service
631 phosphor::logging::log<phosphor::logging::level::INFO>(
632 "PFR not Supported. Hence stop the service");
633 std::exit(EXIT_SUCCESS);
634 }
635 }
636}
637void checkPFRandAddObjects(sdbusplus::asio::object_server& server,
638 std::shared_ptr<sdbusplus::asio::connection>& conn)
639{
640 checkPfrInterface(conn);
641
642 constexpr size_t timeout = 10; // seconds
643 pfrObjTimer->expires_after(std::chrono::seconds(timeout));
Patrick Williams304e82e2023-05-10 07:51:13 -0500644 pfrObjTimer->async_wait(
645 [&conn, &server](const boost::system::error_code& ec) {
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000646 if (ec)
647 {
648 if (ec == boost::asio::error::operation_aborted)
649 {
650 // Timer reset.
651 phosphor::logging::log<phosphor::logging::level::INFO>(
652 "pfr object found. Hence Object Timer aborted or stopped.");
653 }
654 else
655 {
656 phosphor::logging::log<phosphor::logging::level::ERR>(
657 "pfr object timer error.");
658 }
659 }
660 if (retrCount > 0)
661 {
662 checkPFRandAddObjects(server, conn);
663 }
664 else
665 {
666 pfr::monitorSignals(server, conn);
667
668 // Update the D-Bus properties.
669 updateDbusPropertiesCache();
670 // Update CPLD Version to cpld_active object in settings.
671 updateCPLDversion(conn);
672 }
673 retrCount--;
674 });
675}
AppaRao Pulidcf13122020-05-28 01:21:39 +0530676} // namespace pfr
677
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530678int main()
679{
680 // setup connection to dbus
681 boost::asio::io_service io;
682 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
AppaRao Pulidcf13122020-05-28 01:21:39 +0530683 pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
684 pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000685 pfr::pfrObjTimer = std::make_unique<boost::asio::steady_timer>(io);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530686 auto server = sdbusplus::asio::object_server(conn, true);
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000687 pfr::init(conn, pfr::i2cConfigLoaded);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000688
689 pfr::checkPFRandAddObjects(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530690
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000691 // Update CPLD Version to cpld_active object in settings.
692 pfr::updateCPLDversion(conn);
693
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530694 server.add_manager("/xyz/openbmc_project/pfr");
695
696 // Create PFR attributes object and interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530697 pfr::pfrConfigObject = std::make_unique<pfr::PfrConfig>(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530698
699 // Create Software objects using Versions interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530700 for (const auto& entry : pfr::verComponentList)
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530701 {
AppaRao Pulidcf13122020-05-28 01:21:39 +0530702 pfr::pfrVersionObjects.emplace_back(std::make_unique<pfr::PfrVersion>(
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530703 server, conn, std::get<0>(entry), std::get<1>(entry),
704 std::get<2>(entry)));
705 }
706
Zhikui Renc96f37d2021-12-08 15:40:51 -0800707 if (pfr::pfrConfigObject)
708 {
709 pfr::pfrConfigObject->updateProvisioningStatus();
710 if (pfr::pfrConfigObject->getPfrProvisioned())
711 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500712 pfr::pfrPostcodeObject = std::make_unique<pfr::PfrPostcode>(server,
713 conn);
Zhikui Renc96f37d2021-12-08 15:40:51 -0800714 }
715 }
716
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530717 conn->request_name("xyz.openbmc_project.PFR.Manager");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530718 phosphor::logging::log<phosphor::logging::level::INFO>(
719 "Intel PFR service started successfully");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530720 io.run();
721
722 return 0;
723}