blob: f7f860369083fe9a253f3a921a72ca5054626031 [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;
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +000034bool bmcBootCompleteChkPointDone = false;
35bool unProvChkPointStatus = false;
AppaRao Puli46cead92019-07-22 16:50:09 +053036static constexpr uint8_t bmcBootFinishedChkPoint = 0x09;
37
AppaRao Puli88aa33b2019-07-18 23:49:55 +053038std::unique_ptr<boost::asio::steady_timer> stateTimer = nullptr;
AppaRao Puli46cead92019-07-22 16:50:09 +053039std::unique_ptr<boost::asio::steady_timer> initTimer = nullptr;
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +000040std::unique_ptr<boost::asio::steady_timer> pfrObjTimer = nullptr;
AppaRao Pulidcf13122020-05-28 01:21:39 +053041std::vector<std::unique_ptr<PfrVersion>> pfrVersionObjects;
42std::unique_ptr<PfrConfig> pfrConfigObject;
Zhikui Renc96f37d2021-12-08 15:40:51 -080043std::unique_ptr<PfrPostcode> pfrPostcodeObject;
AppaRao Pulie4e95652019-07-19 16:52:01 +053044
AppaRao Pulie4e95652019-07-19 16:52:01 +053045// List holds <ObjPath> <ImageType> <VersionPurpose>
46static std::vector<std::tuple<std::string, ImageType, std::string>>
47 verComponentList = {
AppaRao Pulie4e95652019-07-19 16:52:01 +053048 std::make_tuple("bmc_recovery", ImageType::bmcRecovery,
49 versionPurposeBMC),
AppaRao Pulie4e95652019-07-19 16:52:01 +053050 std::make_tuple("bios_recovery", ImageType::biosRecovery,
51 versionPurposeHost),
ankita prasad56b0e662023-08-09 12:46:54 +000052 std::make_tuple("rot_fw_recovery", ImageType::cpldRecovery,
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053053 versionPurposeOther),
Vikram Bodireddy8292dc62021-05-26 13:31:47 +053054 std::make_tuple("afm_active", ImageType::afmActive,
55 versionPurposeOther),
56 std::make_tuple("afm_recovery", ImageType::afmRecovery,
57 versionPurposeOther),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053058};
AppaRao Pulie4e95652019-07-19 16:52:01 +053059
AppaRao Pulie90f1282019-11-05 01:07:05 +053060// Recovery reason map.
61// {<CPLD association>,{<Redfish MessageID>, <Recovery Reason>}}
62static const boost::container::flat_map<uint8_t,
63 std::pair<std::string, std::string>>
64 recoveryReasonMap = {
65 {0x01,
66 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000067 "BIOS active image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053068 {0x02,
69 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000070 "BIOS recovery image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053071 {0x03, {"MEFirmwareRecoveryReason", "ME launch failure"}},
72 {0x04, {"BIOSFirmwareRecoveryReason", "ACM launch failure"}},
73 {0x05, {"BIOSFirmwareRecoveryReason", "IBB launch failure"}},
74 {0x06, {"BIOSFirmwareRecoveryReason", "OBB launch failure"}},
75 {0x07,
76 {"BMCFirmwareRecoveryReason",
77 "BMC active image authentication failure"}},
78 {0x08,
79 {"BMCFirmwareRecoveryReason",
80 "BMC recovery image authentication failure"}},
81 {0x09, {"BMCFirmwareRecoveryReason", "BMC launch failure"}},
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +000082 {0x0A, {"CPLDFirmwareRecoveryReason", "CPLD watchdog expired"}},
83 {0x0B, {"BMCFirmwareRecoveryReason", "BMC attestation failure"}},
84 {0x0C, {"FirmwareResiliencyError", "CPU0 attestation failure"}},
85 {0x0D, {"FirmwareResiliencyError", "CPU1 attestation failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053086
AppaRao Pulie90f1282019-11-05 01:07:05 +053087// Panic Reason map.
88// {<CPLD association>, {<Redfish MessageID>, <Panic reason> })
89static const boost::container::flat_map<uint8_t,
90 std::pair<std::string, std::string>>
91 panicReasonMap = {
Chalapathi3fb544b2020-02-14 15:43:49 +000092 {0x01, {"BIOSFirmwarePanicReason", "BIOS update intent"}},
93 {0x02, {"BMCFirmwarePanicReason", "BMC update intent"}},
94 {0x03, {"BMCFirmwarePanicReason", "BMC reset detected"}},
95 {0x04, {"BMCFirmwarePanicReason", "BMC watchdog expired"}},
96 {0x05, {"MEFirmwarePanicReason", "ME watchdog expired"}},
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +000097 {0x06, {"BIOSFirmwarePanicReason", "ACM/IBB/OBB WDT expired"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053098 {0x09,
99 {"BIOSFirmwarePanicReason",
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +0000100 "ACM or IBB or OBB authentication failure"}},
101 {0x0A, {"FirmwareResiliencyError", "Attestation failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530102
AppaRao Puli24766942019-11-13 19:27:08 +0530103// Firmware resiliency major map.
104// {<CPLD association>, {<Redfish MessageID>, <Error reason> })
105static const boost::container::flat_map<uint8_t,
106 std::pair<std::string, std::string>>
107 majorErrorCodeMap = {
108 {0x01,
109 {"BMCFirmwareResiliencyError", "BMC image authentication failed"}},
110 {0x02,
111 {"BIOSFirmwareResiliencyError", "BIOS image authentication failed"}},
sri anjaneyulu alapatid5c49902023-06-20 11:05:40 +0000112 {0x03,
113 {"BIOSFirmwareResiliencyError", "in-band and oob update failure"}},
114 {0x04, {"BMCFirmwareResiliencyError", "Communication setup failed"}},
115 {0x05,
116 {"FirmwareResiliencyError",
117 "Attestation measurement mismatch-Attestation failure"}},
118 {0x06, {"FirmwareResiliencyError", "Attestation challenge timeout"}},
119 {0x07, {"FirmwareResiliencyError", "SPDM protocol timeout"}},
120 {0x08, {"FirmwareResiliencyError", "I2c Communication failure"}},
121 {0x09,
122 {"CPLDFirmwareResiliencyError",
123 "Combined CPLD authentication failure"}},
124 {0x0A, {"CPLDFirmwareResiliencyError", "Combined CPLD update failure"}},
125 {0x0B,
126 {"CPLDFirmwareResiliencyError", "Combined CPLD recovery failure"}},
127 {0x10, {"FirmwareResiliencyError", "Image copy Failed"}}};
AppaRao Puli24766942019-11-13 19:27:08 +0530128
AppaRao Pulie4e95652019-07-19 16:52:01 +0530129static void updateDbusPropertiesCache()
130{
131 for (const auto& pfrVerObj : pfrVersionObjects)
132 {
133 pfrVerObj->updateVersion();
134 }
135
136 // Update provisoningStatus properties
137 pfrConfigObject->updateProvisioningStatus();
138
139 phosphor::logging::log<phosphor::logging::level::INFO>(
140 "PFR Manager service cache data updated.");
141}
142
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530143static void logLastRecoveryEvent()
144{
145 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530146 if (0 != readCpldReg(ActionType::recoveryReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530147 {
148 return;
149 }
150
AppaRao Pulie90f1282019-11-05 01:07:05 +0530151 auto it = recoveryReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530152 if (it == recoveryReasonMap.end())
153 {
154 // No matching found. So just return without logging event.
155 return;
156 }
AppaRao Pulie90f1282019-11-05 01:07:05 +0530157 std::string msgId = "OpenBMC.0.1." + it->second.first;
158 sd_journal_send("MESSAGE=%s", "Platform firmware recovery occurred.",
159 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
160 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
161 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530162}
163
164static void logLastPanicEvent()
165{
166 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530167 if (0 != readCpldReg(ActionType::panicReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530168 {
169 return;
170 }
171
AppaRao Pulie90f1282019-11-05 01:07:05 +0530172 auto it = panicReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530173 if (it == panicReasonMap.end())
174 {
175 // No matching found. So just return without logging event.
176 return;
177 }
178
AppaRao Pulie90f1282019-11-05 01:07:05 +0530179 std::string msgId = "OpenBMC.0.1." + it->second.first;
180 sd_journal_send("MESSAGE=%s", "Platform firmware panic occurred.",
181 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
182 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
183 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530184}
185
AppaRao Puli24766942019-11-13 19:27:08 +0530186static void logResiliencyErrorEvent(const uint8_t majorErrorCode,
187 const uint8_t minorErrorCode)
188{
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000189 uint8_t cpldRoTRev = 0;
190 if (0 != readCpldReg(ActionType::readRoTRev, cpldRoTRev))
191 {
192 return;
193 }
194
AppaRao Puli24766942019-11-13 19:27:08 +0530195 auto it = majorErrorCodeMap.find(majorErrorCode);
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000196 if (cpldRoTRev == 0x02)
197 {
198 auto itRev2 = majorErrorCodeMapRev2.find(majorErrorCode);
199 if (itRev2 != majorErrorCodeMapRev2.end())
200 {
201 it = itRev2;
202 }
203 else if (it == majorErrorCodeMap.end())
204 {
205 // No matching found. So just return without logging event.
206 return;
207 }
208 }
209 else if (it == majorErrorCodeMap.end())
AppaRao Puli24766942019-11-13 19:27:08 +0530210 {
211 // No matching found. So just return without logging event.
212 return;
213 }
214
Patrick Williams1695ee32024-08-16 15:21:41 -0400215 std::string errorStr =
216 it->second.second + "(MinorCode:0x" + toHexString(minorErrorCode) + ")";
AppaRao Puli24766942019-11-13 19:27:08 +0530217 std::string msgId = "OpenBMC.0.1." + it->second.first;
218 sd_journal_send(
219 "MESSAGE=%s", "Platform firmware resiliency error occurred.",
220 "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s", msgId.c_str(),
221 "REDFISH_MESSAGE_ARGS=%s", errorStr.c_str(), NULL);
222}
223
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000224static void
225 handleLastCountChange(std::shared_ptr<sdbusplus::asio::connection> conn,
226 std::string eventName, uint8_t currentCount)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530227{
Patrick Williams1695ee32024-08-16 15:21:41 -0400228 sdbusplus::asio::setProperty(
229 *conn, "xyz.openbmc_project.Settings",
230 "/xyz/openbmc_project/pfr/last_events",
231 "xyz.openbmc_project.PFR.LastEvents", eventName, currentCount,
232 [](boost::system::error_code ec) {
233 if (ec)
234 {
235 phosphor::logging::log<phosphor::logging::level::ERR>(
236 "PFR: Unable to update currentCount",
237 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
238 return;
239 }
240 });
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000241 return;
242}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530243
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000244static void
245 checkAndLogEvents(std::shared_ptr<sdbusplus::asio::connection>& conn)
246{
247 sdbusplus::asio::getAllProperties(
248 *conn, "xyz.openbmc_project.Settings",
249 "/xyz/openbmc_project/pfr/last_events",
250 "xyz.openbmc_project.PFR.LastEvents",
251 [conn](
252 boost::system::error_code ec,
Jonathan Doman9b7b9f72022-06-03 15:31:35 -0700253 const std::vector<
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000254 std::pair<std::string, std::variant<std::monostate, uint8_t>>>&
255 properties) {
Patrick Williams1695ee32024-08-16 15:21:41 -0400256 if (ec)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000257 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400258 phosphor::logging::log<phosphor::logging::level::ERR>(
259 "PFR: Unable get PFR last events",
260 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
261 return;
262 }
263 uint8_t lastRecoveryCount = 0;
264 uint8_t lastPanicCount = 0;
265 uint8_t lastMajorErr = 0;
266 uint8_t lastMinorErr = 0;
267
268 try
269 {
270 sdbusplus::unpackProperties(
271 properties, "lastRecoveryCount", lastRecoveryCount,
272 "lastPanicCount", lastPanicCount, "lastMajorErr",
273 lastMajorErr, "lastMinorErr", lastMinorErr);
274 }
275 catch (const sdbusplus::exception::UnpackPropertyError& error)
276 {
277 phosphor::logging::log<phosphor::logging::level::ERR>(
278 "PFR: Unpack error",
279 phosphor::logging::entry("MSG=%s", error.what()));
280 return;
281 }
282
283 uint8_t currPanicCount = 0;
284 if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
285 {
286 if (lastPanicCount != currPanicCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000287 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400288 // Update cached data to dbus and log redfish
289 // event by reading reason.
290 handleLastCountChange(conn, "lastPanicCount",
291 currPanicCount);
292 if (currPanicCount)
293 {
294 logLastPanicEvent();
295 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000296 }
297 }
298
Patrick Williams1695ee32024-08-16 15:21:41 -0400299 uint8_t currRecoveryCount = 0;
300 if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000301 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400302 if (lastRecoveryCount != currRecoveryCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000303 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400304 // Update cached data to dbus and log redfish
305 // event by reading reason.
306 handleLastCountChange(conn, "lastRecoveryCount",
307 currRecoveryCount);
308 if (currRecoveryCount)
309 {
310 logLastRecoveryEvent();
311 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000312 }
313 }
314
Patrick Williams1695ee32024-08-16 15:21:41 -0400315 uint8_t majorErr = 0;
316 uint8_t minorErr = 0;
317 if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
318 (0 == readCpldReg(ActionType::minorError, minorErr)))
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000319 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400320 if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000321 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400322 // Update cached data to dbus and log redfish event by
323 // reading reason.
324 handleLastCountChange(conn, "lastMajorErr", majorErr);
325 handleLastCountChange(conn, "lastMinorErr", minorErr);
326 if (majorErr && minorErr)
327 {
328 logResiliencyErrorEvent(majorErr, minorErr);
329 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000330 }
331 }
Patrick Williams1695ee32024-08-16 15:21:41 -0400332 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530333}
334
335static void monitorPlatformStateChange(
336 sdbusplus::asio::object_server& server,
337 std::shared_ptr<sdbusplus::asio::connection>& conn)
338{
339 constexpr size_t pollTimeout = 10; // seconds
340 stateTimer->expires_after(std::chrono::seconds(pollTimeout));
341 stateTimer->async_wait(
342 [&server, &conn](const boost::system::error_code& ec) {
Patrick Williams1695ee32024-08-16 15:21:41 -0400343 if (ec == boost::asio::error::operation_aborted)
344 {
345 // Timer reset.
346 return;
347 }
348 if (ec)
349 {
350 // Platform State Monitor - Timer cancelled.
351 return;
352 }
353 checkAndLogEvents(conn);
354 monitorPlatformStateChange(server, conn);
355 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530356}
357
AppaRao Puli46cead92019-07-22 16:50:09 +0530358void checkAndSetCheckpoint(sdbusplus::asio::object_server& server,
359 std::shared_ptr<sdbusplus::asio::connection>& conn)
360{
361 // Check whether systemd completed all the loading.
362 conn->async_method_call(
363 [&server, &conn](boost::system::error_code ec,
364 const std::variant<uint64_t>& value) {
Patrick Williams1695ee32024-08-16 15:21:41 -0400365 if (!ec)
AppaRao Puli46cead92019-07-22 16:50:09 +0530366 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400367 if (std::get<uint64_t>(value))
AppaRao Puli46cead92019-07-22 16:50:09 +0530368 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400369 phosphor::logging::log<phosphor::logging::level::INFO>(
370 "BMC boot completed. Setting checkpoint 9.");
371 if (!bmcBootCompleteChkPointDone)
372 {
373 setBMCBootCompleteChkPoint(bmcBootFinishedChkPoint);
374 }
375 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530376 }
377 }
Patrick Williams1695ee32024-08-16 15:21:41 -0400378 else
AppaRao Puli46cead92019-07-22 16:50:09 +0530379 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400380 // Failed to get data from systemd. System might not
381 // be ready yet. Attempt again for data.
Patrick Williams304e82e2023-05-10 07:51:13 -0500382 phosphor::logging::log<phosphor::logging::level::ERR>(
Patrick Williams1695ee32024-08-16 15:21:41 -0400383 "aync call failed to get FinishTimestamp.",
384 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
Patrick Williams304e82e2023-05-10 07:51:13 -0500385 }
Patrick Williams1695ee32024-08-16 15:21:41 -0400386 // FIX-ME: Latest up-stream sync caused issue in receiving
387 // StartupFinished signal. Unable to get StartupFinished signal
388 // from systemd1 hence using poll method too, to trigger it
389 // properly.
390 constexpr size_t pollTimeout = 10; // seconds
391 initTimer->expires_after(std::chrono::seconds(pollTimeout));
392 initTimer->async_wait(
393 [&server, &conn](const boost::system::error_code& ec) {
394 if (ec == boost::asio::error::operation_aborted)
395 {
396 // Timer reset.
397 phosphor::logging::log<phosphor::logging::level::INFO>(
398 "Set boot Checkpoint - Timer aborted or stopped.");
399 return;
400 }
401 if (ec)
402 {
403 phosphor::logging::log<phosphor::logging::level::ERR>(
404 "Set boot Checkpoint - async wait error.");
405 return;
406 }
407 checkAndSetCheckpoint(server, conn);
408 });
409 },
AppaRao Puli46cead92019-07-22 16:50:09 +0530410 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
411 "org.freedesktop.DBus.Properties", "Get",
412 "org.freedesktop.systemd1.Manager", "FinishTimestamp");
413}
414
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530415void monitorSignals(sdbusplus::asio::object_server& server,
416 std::shared_ptr<sdbusplus::asio::connection>& conn)
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530417{
AppaRao Puli46cead92019-07-22 16:50:09 +0530418 // Monitor Boot finished signal and set the checkpoint 9 to
419 // notify CPLD about BMC boot finish.
Patrick Williamsf01de222022-07-22 19:26:57 -0500420 auto bootFinishedSignal = std::make_unique<sdbusplus::bus::match_t>(
421 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli46cead92019-07-22 16:50:09 +0530422 "type='signal',"
423 "member='StartupFinished',path='/org/freedesktop/systemd1',"
424 "interface='org.freedesktop.systemd1.Manager'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500425 [&server, &conn](sdbusplus::message_t& msg) {
Patrick Williams1695ee32024-08-16 15:21:41 -0400426 if (!bmcBootCompleteChkPointDone)
427 {
428 phosphor::logging::log<phosphor::logging::level::INFO>(
429 "BMC boot completed(StartupFinished). Setting "
430 "checkpoint 9.");
431 setBMCBootCompleteChkPoint(bmcBootFinishedChkPoint);
432 }
433 });
AppaRao Puli46cead92019-07-22 16:50:09 +0530434 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 Williams1695ee32024-08-16 15:21:41 -0400446 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 Williams1695ee32024-08-16 15:21:41 -0400450 const auto it = properties.find("CurrentPowerState");
451 if (it != properties.end())
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530452 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400453 const std::string* state =
454 std::get_if<std::string>(&it->second);
455 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530456 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400457 if ((*state ==
458 "xyz.openbmc_project.State.Chassis.PowerState.On") &&
459 (!stateTimerRunning))
460 {
461 stateTimerRunning = true;
462 monitorPlatformStateChange(server, conn);
463 }
464 else if ((*state == "xyz.openbmc_project.State.Chassis."
465 "PowerState.Off") &&
466 (stateTimerRunning))
467 {
468 stateTimer->cancel();
469 checkAndLogEvents(conn);
470 stateTimerRunning = false;
471 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530472 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500473
Patrick Williams1695ee32024-08-16 15:21:41 -0400474 // Update the D-Bus properties when chassis state changes.
475 updateDbusPropertiesCache();
476 }
477 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530478
479 // Capture the Host state and Start the monitor timer
480 // if state changed to 'Running'. Run timer until OS boot.
481 // Stop timer if state changed to 'Off'.
Patrick Williamsf01de222022-07-22 19:26:57 -0500482 static auto matchHostState = sdbusplus::bus::match_t(
483 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530484 "type='signal',member='PropertiesChanged', "
485 "interface='org.freedesktop.DBus.Properties', "
486 "sender='xyz.openbmc_project.State.Chassis', "
487 "arg0namespace='xyz.openbmc_project.State.Host'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500488 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams1695ee32024-08-16 15:21:41 -0400489 std::string intfName;
490 std::map<std::string, std::variant<std::string>> properties;
491 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530492
Patrick Williams1695ee32024-08-16 15:21:41 -0400493 const auto it = properties.find("CurrentHostState");
494 if (it != properties.end())
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530495 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400496 const std::string* state =
497 std::get_if<std::string>(&it->second);
498 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530499 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400500 if ((*state ==
501 "xyz.openbmc_project.State.Host.HostState.Running") &&
502 (!stateTimerRunning))
503 {
504 stateTimerRunning = true;
505 monitorPlatformStateChange(server, conn);
506 }
507 else if (((*state == "xyz.openbmc_project.State.Host."
508 "HostState.Off") ||
509 (*state == "xyz.openbmc_project.State.Host."
510 "HostState.Quiesced")) &&
511 (stateTimerRunning))
512 {
513 stateTimer->cancel();
514 checkAndLogEvents(conn);
515 stateTimerRunning = false;
516 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530517 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500518
Patrick Williams1695ee32024-08-16 15:21:41 -0400519 // Update the D-Bus properties when host state changes.
520 updateDbusPropertiesCache();
521 }
522 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530523
524 // Capture the OS state change and stop monitor timer
Manojkiran Eda76b85db2024-06-17 11:51:22 +0530525 // if OS boots completely or becomes Inactive.
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530526 // start timer in other cases to mnitor states.
Patrick Williamsf01de222022-07-22 19:26:57 -0500527 static auto matchOsState = sdbusplus::bus::match_t(
528 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530529 "type='signal',member='PropertiesChanged', "
530 "interface='org.freedesktop.DBus.Properties', "
531 "sender='xyz.openbmc_project.State.Chassis', "
532 "arg0namespace='xyz.openbmc_project.State.OperatingSystem.Status'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500533 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams1695ee32024-08-16 15:21:41 -0400534 std::string intfName;
535 std::map<std::string, std::variant<std::string>> properties;
536 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530537
Patrick Williams1695ee32024-08-16 15:21:41 -0400538 const auto it = properties.find("OperatingSystemState");
539 if (it != properties.end())
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530540 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400541 const std::string* state =
542 std::get_if<std::string>(&it->second);
543 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530544 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400545 // The short strings "BootComplete" and "Standby" are
546 // deprecated in favor of the full enum strings
547 // Support for the short strings will be removed in the
548 // future.
549 if (((*state == "BootComplete") ||
550 (*state == "xyz.openbmc_project.State.OperatingSystem."
551 "Status.OSStatus.BootComplete") ||
552 (*state == "Inactive") ||
553 (*state == "xyz.openbmc_project.State.OperatingSystem."
554 "Status.OSStatus.Inactive")) &&
555 (stateTimerRunning))
556 {
557 stateTimer->cancel();
558 checkAndLogEvents(conn);
559 stateTimerRunning = false;
560 }
561 else if (!stateTimerRunning)
562 {
563 stateTimerRunning = true;
564 monitorPlatformStateChange(server, conn);
565 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530566 }
567 }
Patrick Williams1695ee32024-08-16 15:21:41 -0400568 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530569
570 // First time, check and log events if any.
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000571 checkAndLogEvents(conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530572}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530573
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000574static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)
575{
576 std::string cpldVersion = pfr::readCPLDVersion();
ankita prasad56b0e662023-08-09 12:46:54 +0000577 lg2::info("VERSION INFO - rot_fw_active - {VER}", "VER", cpldVersion);
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000578 conn->async_method_call(
579 [](const boost::system::error_code ec) {
Patrick Williams1695ee32024-08-16 15:21:41 -0400580 if (ec)
581 {
582 phosphor::logging::log<phosphor::logging::level::ERR>(
583 "Unable to update rot_fw_active version",
584 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
585 return;
586 }
587 },
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000588 "xyz.openbmc_project.Settings",
ankita prasad56b0e662023-08-09 12:46:54 +0000589 "/xyz/openbmc_project/software/rot_fw_active",
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000590 "org.freedesktop.DBus.Properties", "Set",
591 "xyz.openbmc_project.Software.Version", "Version",
592 std::variant<std::string>(cpldVersion));
593 return;
594}
595
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000596void checkPfrInterface(std::shared_ptr<sdbusplus::asio::connection> conn,
597 sdbusplus::asio::object_server& server)
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000598{
599 if (!i2cConfigLoaded)
600 {
601 init(conn, i2cConfigLoaded);
602 if (retrCount > 0)
603 {
604 // pfr object not loaded yet. query again.
605 return;
606 }
607 else
608 {
609 // Platform does not contain pfr object. Stop the service.
610 phosphor::logging::log<phosphor::logging::level::INFO>(
611 "Platform does not support PFR, hence stop the "
612 "service.");
613 std::exit(EXIT_SUCCESS);
614 return;
615 }
616 }
617 else
618 {
619 retrCount = 0;
620
621 bool locked = false;
622 bool prov = false;
623 bool support = false;
624 pfr::getProvisioningStatus(locked, prov, support);
625 if (support && prov)
626 {
627 // pfr provisioned.
628 phosphor::logging::log<phosphor::logging::level::INFO>(
629 "PFR Supported.");
630 return;
631 }
632 else
633 {
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000634 unProvChkPointStatus = true;
635 pfr::monitorSignals(server, conn);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000636 }
637 }
638}
639void checkPFRandAddObjects(sdbusplus::asio::object_server& server,
640 std::shared_ptr<sdbusplus::asio::connection>& conn)
641{
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000642 checkPfrInterface(conn, server);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000643
644 constexpr size_t timeout = 10; // seconds
645 pfrObjTimer->expires_after(std::chrono::seconds(timeout));
Patrick Williams1695ee32024-08-16 15:21:41 -0400646 pfrObjTimer->async_wait([&conn,
647 &server](const boost::system::error_code& ec) {
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000648 if (ec)
649 {
650 if (ec == boost::asio::error::operation_aborted)
651 {
652 // Timer reset.
653 phosphor::logging::log<phosphor::logging::level::INFO>(
654 "pfr object found. Hence Object Timer aborted or stopped.");
655 }
656 else
657 {
658 phosphor::logging::log<phosphor::logging::level::ERR>(
659 "pfr object timer error.");
660 }
661 }
662 if (retrCount > 0)
663 {
664 checkPFRandAddObjects(server, conn);
665 }
666 else
667 {
668 pfr::monitorSignals(server, conn);
669
670 // Update the D-Bus properties.
671 updateDbusPropertiesCache();
ankita prasad56b0e662023-08-09 12:46:54 +0000672 // Update CPLD Version to rot_fw_active object in settings.
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000673 updateCPLDversion(conn);
674 }
675 retrCount--;
676 });
677}
AppaRao Pulidcf13122020-05-28 01:21:39 +0530678} // namespace pfr
679
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530680int main()
681{
682 // setup connection to dbus
683 boost::asio::io_service io;
684 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
AppaRao Pulidcf13122020-05-28 01:21:39 +0530685 pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
686 pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000687 pfr::pfrObjTimer = std::make_unique<boost::asio::steady_timer>(io);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530688 auto server = sdbusplus::asio::object_server(conn, true);
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000689 pfr::init(conn, pfr::i2cConfigLoaded);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000690
691 pfr::checkPFRandAddObjects(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530692
ankita prasad56b0e662023-08-09 12:46:54 +0000693 // Update CPLD Version to rot_fw_active object in settings.
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000694 pfr::updateCPLDversion(conn);
695
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530696 server.add_manager("/xyz/openbmc_project/pfr");
697
698 // Create PFR attributes object and interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530699 pfr::pfrConfigObject = std::make_unique<pfr::PfrConfig>(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530700
701 // Create Software objects using Versions interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530702 for (const auto& entry : pfr::verComponentList)
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530703 {
AppaRao Pulidcf13122020-05-28 01:21:39 +0530704 pfr::pfrVersionObjects.emplace_back(std::make_unique<pfr::PfrVersion>(
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530705 server, conn, std::get<0>(entry), std::get<1>(entry),
706 std::get<2>(entry)));
707 }
708
Zhikui Renc96f37d2021-12-08 15:40:51 -0800709 if (pfr::pfrConfigObject)
710 {
711 pfr::pfrConfigObject->updateProvisioningStatus();
712 if (pfr::pfrConfigObject->getPfrProvisioned())
713 {
Patrick Williams1695ee32024-08-16 15:21:41 -0400714 pfr::pfrPostcodeObject =
715 std::make_unique<pfr::PfrPostcode>(server, conn);
Zhikui Renc96f37d2021-12-08 15:40:51 -0800716 }
717 }
718
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530719 conn->request_name("xyz.openbmc_project.PFR.Manager");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530720 phosphor::logging::log<phosphor::logging::level::INFO>(
721 "Intel PFR service started successfully");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530722 io.run();
723
724 return 0;
725}