blob: fc3f75af51c11b76988f0f672d6d38d34b5a60a3 [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 Williams304e82e2023-05-10 07:51:13 -0500215 std::string errorStr = it->second.second + "(MinorCode:0x" +
216 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 Williams304e82e2023-05-10 07:51:13 -0500228 sdbusplus::asio::setProperty(*conn, "xyz.openbmc_project.Settings",
229 "/xyz/openbmc_project/pfr/last_events",
230 "xyz.openbmc_project.PFR.LastEvents",
231 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 Williams304e82e2023-05-10 07:51:13 -0500256 if (ec)
257 {
258 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;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530267
Patrick Williams304e82e2023-05-10 07:51:13 -0500268 try
269 {
270 sdbusplus::unpackProperties(
271 properties, "lastRecoveryCount", lastRecoveryCount,
272 "lastPanicCount", lastPanicCount, "lastMajorErr", lastMajorErr,
273 "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 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530282
Patrick Williams304e82e2023-05-10 07:51:13 -0500283 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 Williams304e82e2023-05-10 07:51:13 -0500288 // Update cached data to dbus and log redfish
289 // event by reading reason.
290 handleLastCountChange(conn, "lastPanicCount", currPanicCount);
291 if (currPanicCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000292 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500293 logLastPanicEvent();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000294 }
295 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500296 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000297
Patrick Williams304e82e2023-05-10 07:51:13 -0500298 uint8_t currRecoveryCount = 0;
299 if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
300 {
301 if (lastRecoveryCount != currRecoveryCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000302 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500303 // Update cached data to dbus and log redfish
304 // event by reading reason.
305 handleLastCountChange(conn, "lastRecoveryCount",
306 currRecoveryCount);
307 if (currRecoveryCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000308 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500309 logLastRecoveryEvent();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000310 }
311 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500312 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000313
Patrick Williams304e82e2023-05-10 07:51:13 -0500314 uint8_t majorErr = 0;
315 uint8_t minorErr = 0;
316 if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
317 (0 == readCpldReg(ActionType::minorError, minorErr)))
318 {
319 if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000320 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500321 // Update cached data to dbus and log redfish event by
322 // reading reason.
323 handleLastCountChange(conn, "lastMajorErr", majorErr);
324 handleLastCountChange(conn, "lastMinorErr", minorErr);
325 if (majorErr && minorErr)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000326 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500327 logResiliencyErrorEvent(majorErr, minorErr);
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000328 }
329 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500330 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000331 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530332}
333
334static void monitorPlatformStateChange(
335 sdbusplus::asio::object_server& server,
336 std::shared_ptr<sdbusplus::asio::connection>& conn)
337{
338 constexpr size_t pollTimeout = 10; // seconds
339 stateTimer->expires_after(std::chrono::seconds(pollTimeout));
340 stateTimer->async_wait(
341 [&server, &conn](const boost::system::error_code& ec) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500342 if (ec == boost::asio::error::operation_aborted)
343 {
344 // Timer reset.
345 return;
346 }
347 if (ec)
348 {
349 // Platform State Monitor - Timer cancelled.
350 return;
351 }
352 checkAndLogEvents(conn);
353 monitorPlatformStateChange(server, conn);
354 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530355}
356
AppaRao Puli46cead92019-07-22 16:50:09 +0530357void checkAndSetCheckpoint(sdbusplus::asio::object_server& server,
358 std::shared_ptr<sdbusplus::asio::connection>& conn)
359{
360 // Check whether systemd completed all the loading.
361 conn->async_method_call(
362 [&server, &conn](boost::system::error_code ec,
363 const std::variant<uint64_t>& value) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500364 if (!ec)
365 {
366 if (std::get<uint64_t>(value))
AppaRao Puli46cead92019-07-22 16:50:09 +0530367 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500368 phosphor::logging::log<phosphor::logging::level::INFO>(
369 "BMC boot completed. Setting checkpoint 9.");
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000370 if (!bmcBootCompleteChkPointDone)
AppaRao Puli46cead92019-07-22 16:50:09 +0530371 {
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000372 setBMCBootCompleteChkPoint(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) {
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000425 if (!bmcBootCompleteChkPointDone)
Patrick Williams304e82e2023-05-10 07:51:13 -0500426 {
427 phosphor::logging::log<phosphor::logging::level::INFO>(
428 "BMC boot completed(StartupFinished). Setting "
429 "checkpoint 9.");
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000430 setBMCBootCompleteChkPoint(bmcBootFinishedChkPoint);
Patrick Williams304e82e2023-05-10 07:51:13 -0500431 }
AppaRao Puli46cead92019-07-22 16:50:09 +0530432 });
433 checkAndSetCheckpoint(server, conn);
434
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530435 // Capture the Chassis state and Start the monitor timer
436 // if state changed to 'On'. Run timer until OS boot.
437 // Stop timer if state changed to 'Off'.
Patrick Williamsf01de222022-07-22 19:26:57 -0500438 static auto matchChassisState = sdbusplus::bus::match_t(
439 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530440 "type='signal',member='PropertiesChanged', "
441 "interface='org.freedesktop.DBus.Properties', "
442 "sender='xyz.openbmc_project.State.Chassis', "
443 "arg0namespace='xyz.openbmc_project.State.Chassis'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500444 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500445 std::string intfName;
446 std::map<std::string, std::variant<std::string>> properties;
447 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530448
Patrick Williams304e82e2023-05-10 07:51:13 -0500449 const auto it = properties.find("CurrentPowerState");
450 if (it != properties.end())
451 {
452 const std::string* state = std::get_if<std::string>(&it->second);
453 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530454 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500455 if ((*state ==
456 "xyz.openbmc_project.State.Chassis.PowerState.On") &&
457 (!stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530458 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500459 stateTimerRunning = true;
460 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530461 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500462 else if ((*state == "xyz.openbmc_project.State.Chassis."
463 "PowerState.Off") &&
464 (stateTimerRunning))
465 {
466 stateTimer->cancel();
467 checkAndLogEvents(conn);
468 stateTimerRunning = false;
469 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530470 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500471
472 // Update the D-Bus properties when chassis state changes.
473 updateDbusPropertiesCache();
474 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530475 });
476
477 // Capture the Host state and Start the monitor timer
478 // if state changed to 'Running'. Run timer until OS boot.
479 // Stop timer if state changed to 'Off'.
Patrick Williamsf01de222022-07-22 19:26:57 -0500480 static auto matchHostState = sdbusplus::bus::match_t(
481 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530482 "type='signal',member='PropertiesChanged', "
483 "interface='org.freedesktop.DBus.Properties', "
484 "sender='xyz.openbmc_project.State.Chassis', "
485 "arg0namespace='xyz.openbmc_project.State.Host'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500486 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500487 std::string intfName;
488 std::map<std::string, std::variant<std::string>> properties;
489 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530490
Patrick Williams304e82e2023-05-10 07:51:13 -0500491 const auto it = properties.find("CurrentHostState");
492 if (it != properties.end())
493 {
494 const std::string* state = std::get_if<std::string>(&it->second);
495 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530496 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500497 if ((*state ==
498 "xyz.openbmc_project.State.Host.HostState.Running") &&
499 (!stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530500 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500501 stateTimerRunning = true;
502 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530503 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500504 else if (((*state == "xyz.openbmc_project.State.Host."
505 "HostState.Off") ||
506 (*state == "xyz.openbmc_project.State.Host."
507 "HostState.Quiesced")) &&
508 (stateTimerRunning))
509 {
510 stateTimer->cancel();
511 checkAndLogEvents(conn);
512 stateTimerRunning = false;
513 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530514 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500515
516 // Update the D-Bus properties when host state changes.
517 updateDbusPropertiesCache();
518 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530519 });
520
521 // Capture the OS state change and stop monitor timer
522 // if OS boots completly or becomes Inactive.
523 // start timer in other cases to mnitor states.
Patrick Williamsf01de222022-07-22 19:26:57 -0500524 static auto matchOsState = sdbusplus::bus::match_t(
525 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530526 "type='signal',member='PropertiesChanged', "
527 "interface='org.freedesktop.DBus.Properties', "
528 "sender='xyz.openbmc_project.State.Chassis', "
529 "arg0namespace='xyz.openbmc_project.State.OperatingSystem.Status'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500530 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500531 std::string intfName;
532 std::map<std::string, std::variant<std::string>> properties;
533 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530534
Patrick Williams304e82e2023-05-10 07:51:13 -0500535 const auto it = properties.find("OperatingSystemState");
536 if (it != properties.end())
537 {
538 const std::string* state = std::get_if<std::string>(&it->second);
539 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530540 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500541 // The short strings "BootComplete" and "Standby" are
542 // deprecated in favor of the full enum strings
543 // Support for the short strings will be removed in the
544 // future.
545 if (((*state == "BootComplete") ||
546 (*state == "xyz.openbmc_project.State.OperatingSystem."
547 "Status.OSStatus.BootComplete") ||
548 (*state == "Inactive") ||
549 (*state == "xyz.openbmc_project.State.OperatingSystem."
550 "Status.OSStatus.Inactive")) &&
551 (stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530552 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500553 stateTimer->cancel();
554 checkAndLogEvents(conn);
555 stateTimerRunning = false;
556 }
557 else if (!stateTimerRunning)
558 {
559 stateTimerRunning = true;
560 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530561 }
562 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500563 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530564 });
565
566 // First time, check and log events if any.
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000567 checkAndLogEvents(conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530568}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530569
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000570static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)
571{
572 std::string cpldVersion = pfr::readCPLDVersion();
ankita prasad56b0e662023-08-09 12:46:54 +0000573 lg2::info("VERSION INFO - rot_fw_active - {VER}", "VER", cpldVersion);
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000574 conn->async_method_call(
575 [](const boost::system::error_code ec) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500576 if (ec)
577 {
578 phosphor::logging::log<phosphor::logging::level::ERR>(
ankita prasad56b0e662023-08-09 12:46:54 +0000579 "Unable to update rot_fw_active version",
Patrick Williams304e82e2023-05-10 07:51:13 -0500580 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
581 return;
582 }
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000583 },
584 "xyz.openbmc_project.Settings",
ankita prasad56b0e662023-08-09 12:46:54 +0000585 "/xyz/openbmc_project/software/rot_fw_active",
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000586 "org.freedesktop.DBus.Properties", "Set",
587 "xyz.openbmc_project.Software.Version", "Version",
588 std::variant<std::string>(cpldVersion));
589 return;
590}
591
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000592void checkPfrInterface(std::shared_ptr<sdbusplus::asio::connection> conn,
593 sdbusplus::asio::object_server& server)
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000594{
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 {
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000630 unProvChkPointStatus = true;
631 pfr::monitorSignals(server, conn);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000632 }
633 }
634}
635void checkPFRandAddObjects(sdbusplus::asio::object_server& server,
636 std::shared_ptr<sdbusplus::asio::connection>& conn)
637{
sri anjaneyulu alapatibe132592023-07-17 10:16:39 +0000638 checkPfrInterface(conn, server);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000639
640 constexpr size_t timeout = 10; // seconds
641 pfrObjTimer->expires_after(std::chrono::seconds(timeout));
Patrick Williams304e82e2023-05-10 07:51:13 -0500642 pfrObjTimer->async_wait(
643 [&conn, &server](const boost::system::error_code& ec) {
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000644 if (ec)
645 {
646 if (ec == boost::asio::error::operation_aborted)
647 {
648 // Timer reset.
649 phosphor::logging::log<phosphor::logging::level::INFO>(
650 "pfr object found. Hence Object Timer aborted or stopped.");
651 }
652 else
653 {
654 phosphor::logging::log<phosphor::logging::level::ERR>(
655 "pfr object timer error.");
656 }
657 }
658 if (retrCount > 0)
659 {
660 checkPFRandAddObjects(server, conn);
661 }
662 else
663 {
664 pfr::monitorSignals(server, conn);
665
666 // Update the D-Bus properties.
667 updateDbusPropertiesCache();
ankita prasad56b0e662023-08-09 12:46:54 +0000668 // Update CPLD Version to rot_fw_active object in settings.
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000669 updateCPLDversion(conn);
670 }
671 retrCount--;
672 });
673}
AppaRao Pulidcf13122020-05-28 01:21:39 +0530674} // namespace pfr
675
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530676int main()
677{
678 // setup connection to dbus
679 boost::asio::io_service io;
680 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
AppaRao Pulidcf13122020-05-28 01:21:39 +0530681 pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
682 pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000683 pfr::pfrObjTimer = std::make_unique<boost::asio::steady_timer>(io);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530684 auto server = sdbusplus::asio::object_server(conn, true);
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000685 pfr::init(conn, pfr::i2cConfigLoaded);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000686
687 pfr::checkPFRandAddObjects(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530688
ankita prasad56b0e662023-08-09 12:46:54 +0000689 // Update CPLD Version to rot_fw_active object in settings.
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000690 pfr::updateCPLDversion(conn);
691
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530692 server.add_manager("/xyz/openbmc_project/pfr");
693
694 // Create PFR attributes object and interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530695 pfr::pfrConfigObject = std::make_unique<pfr::PfrConfig>(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530696
697 // Create Software objects using Versions interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530698 for (const auto& entry : pfr::verComponentList)
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530699 {
AppaRao Pulidcf13122020-05-28 01:21:39 +0530700 pfr::pfrVersionObjects.emplace_back(std::make_unique<pfr::PfrVersion>(
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530701 server, conn, std::get<0>(entry), std::get<1>(entry),
702 std::get<2>(entry)));
703 }
704
Zhikui Renc96f37d2021-12-08 15:40:51 -0800705 if (pfr::pfrConfigObject)
706 {
707 pfr::pfrConfigObject->updateProvisioningStatus();
708 if (pfr::pfrConfigObject->getPfrProvisioned())
709 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500710 pfr::pfrPostcodeObject = std::make_unique<pfr::PfrPostcode>(server,
711 conn);
Zhikui Renc96f37d2021-12-08 15:40:51 -0800712 }
713 }
714
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530715 conn->request_name("xyz.openbmc_project.PFR.Manager");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530716 phosphor::logging::log<phosphor::logging::level::INFO>(
717 "Intel PFR service started successfully");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530718 io.run();
719
720 return 0;
721}