blob: 83750c9e429f90c9b7b18a918bc8a3181bf03d66 [file] [log] [blame]
AppaRao Pulie63eeda2019-07-05 16:25:38 +05301/*
2// Copyright (c) 2019 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
AppaRao Puli67d184c2020-05-29 00:48:33 +053017#include "pfr.hpp"
18#include "pfr_mgr.hpp"
19
AppaRao Puli88aa33b2019-07-18 23:49:55 +053020#include <systemd/sd-journal.h>
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +000021#include <unistd.h>
AppaRao Puli88aa33b2019-07-18 23:49:55 +053022
AppaRao Puli46cead92019-07-22 16:50:09 +053023#include <boost/asio.hpp>
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +000024#include <sdbusplus/asio/property.hpp>
25#include <sdbusplus/unpack_properties.hpp>
AppaRao Pulie63eeda2019-07-05 16:25:38 +053026
AppaRao Pulidcf13122020-05-28 01:21:39 +053027namespace pfr
28{
AppaRao Puli88aa33b2019-07-18 23:49:55 +053029
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +000030static bool i2cConfigLoaded = false;
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +000031static int retrCount = 10;
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +000032
AppaRao Puli88aa33b2019-07-18 23:49:55 +053033static bool stateTimerRunning = false;
AppaRao Puli46cead92019-07-22 16:50:09 +053034bool finishedSettingChkPoint = false;
35static constexpr uint8_t bmcBootFinishedChkPoint = 0x09;
36
AppaRao Puli88aa33b2019-07-18 23:49:55 +053037std::unique_ptr<boost::asio::steady_timer> stateTimer = nullptr;
AppaRao Puli46cead92019-07-22 16:50:09 +053038std::unique_ptr<boost::asio::steady_timer> initTimer = nullptr;
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +000039std::unique_ptr<boost::asio::steady_timer> pfrObjTimer = nullptr;
AppaRao Pulidcf13122020-05-28 01:21:39 +053040std::vector<std::unique_ptr<PfrVersion>> pfrVersionObjects;
41std::unique_ptr<PfrConfig> pfrConfigObject;
Zhikui Renc96f37d2021-12-08 15:40:51 -080042std::unique_ptr<PfrPostcode> pfrPostcodeObject;
AppaRao Pulie4e95652019-07-19 16:52:01 +053043
AppaRao Pulie4e95652019-07-19 16:52:01 +053044// List holds <ObjPath> <ImageType> <VersionPurpose>
45static std::vector<std::tuple<std::string, ImageType, std::string>>
46 verComponentList = {
AppaRao Pulie4e95652019-07-19 16:52:01 +053047 std::make_tuple("bmc_recovery", ImageType::bmcRecovery,
48 versionPurposeBMC),
AppaRao Pulie4e95652019-07-19 16:52:01 +053049 std::make_tuple("bios_recovery", ImageType::biosRecovery,
50 versionPurposeHost),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053051 std::make_tuple("cpld_recovery", ImageType::cpldRecovery,
52 versionPurposeOther),
Vikram Bodireddy8292dc62021-05-26 13:31:47 +053053 std::make_tuple("afm_active", ImageType::afmActive,
54 versionPurposeOther),
55 std::make_tuple("afm_recovery", ImageType::afmRecovery,
56 versionPurposeOther),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053057};
AppaRao Pulie4e95652019-07-19 16:52:01 +053058
AppaRao Pulie90f1282019-11-05 01:07:05 +053059// Recovery reason map.
60// {<CPLD association>,{<Redfish MessageID>, <Recovery Reason>}}
61static const boost::container::flat_map<uint8_t,
62 std::pair<std::string, std::string>>
63 recoveryReasonMap = {
64 {0x01,
65 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000066 "BIOS active image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053067 {0x02,
68 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000069 "BIOS recovery image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053070 {0x03, {"MEFirmwareRecoveryReason", "ME launch failure"}},
71 {0x04, {"BIOSFirmwareRecoveryReason", "ACM launch failure"}},
72 {0x05, {"BIOSFirmwareRecoveryReason", "IBB launch failure"}},
73 {0x06, {"BIOSFirmwareRecoveryReason", "OBB launch failure"}},
74 {0x07,
75 {"BMCFirmwareRecoveryReason",
76 "BMC active image authentication failure"}},
77 {0x08,
78 {"BMCFirmwareRecoveryReason",
79 "BMC recovery image authentication failure"}},
80 {0x09, {"BMCFirmwareRecoveryReason", "BMC launch failure"}},
81 {0x0A, {"CPLDFirmwareRecoveryReason", "CPLD watchdog expired"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053082
AppaRao Pulie90f1282019-11-05 01:07:05 +053083// Panic Reason map.
84// {<CPLD association>, {<Redfish MessageID>, <Panic reason> })
85static const boost::container::flat_map<uint8_t,
86 std::pair<std::string, std::string>>
87 panicReasonMap = {
Chalapathi3fb544b2020-02-14 15:43:49 +000088 {0x01, {"BIOSFirmwarePanicReason", "BIOS update intent"}},
89 {0x02, {"BMCFirmwarePanicReason", "BMC update intent"}},
90 {0x03, {"BMCFirmwarePanicReason", "BMC reset detected"}},
91 {0x04, {"BMCFirmwarePanicReason", "BMC watchdog expired"}},
92 {0x05, {"MEFirmwarePanicReason", "ME watchdog expired"}},
93 {0x06, {"BIOSFirmwarePanicReason", "ACM watchdog expired"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053094 {0x09,
95 {"BIOSFirmwarePanicReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000096 "ACM or IBB or OBB authentication failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053097
AppaRao Puli24766942019-11-13 19:27:08 +053098// Firmware resiliency major map.
99// {<CPLD association>, {<Redfish MessageID>, <Error reason> })
100static const boost::container::flat_map<uint8_t,
101 std::pair<std::string, std::string>>
102 majorErrorCodeMap = {
103 {0x01,
104 {"BMCFirmwareResiliencyError", "BMC image authentication failed"}},
105 {0x02,
106 {"BIOSFirmwareResiliencyError", "BIOS image authentication failed"}},
Chalapathi3fb544b2020-02-14 15:43:49 +0000107 {0x03, {"BIOSFirmwareResiliencyError", "Update from BIOS failed"}},
108 {0x04, {"BMCFirmwareResiliencyError", "Update from BMC failed"}}};
AppaRao Puli24766942019-11-13 19:27:08 +0530109
AppaRao Pulie4e95652019-07-19 16:52:01 +0530110static void updateDbusPropertiesCache()
111{
112 for (const auto& pfrVerObj : pfrVersionObjects)
113 {
114 pfrVerObj->updateVersion();
115 }
116
117 // Update provisoningStatus properties
118 pfrConfigObject->updateProvisioningStatus();
119
120 phosphor::logging::log<phosphor::logging::level::INFO>(
121 "PFR Manager service cache data updated.");
122}
123
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530124static void logLastRecoveryEvent()
125{
126 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530127 if (0 != readCpldReg(ActionType::recoveryReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530128 {
129 return;
130 }
131
AppaRao Pulie90f1282019-11-05 01:07:05 +0530132 auto it = recoveryReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530133 if (it == recoveryReasonMap.end())
134 {
135 // No matching found. So just return without logging event.
136 return;
137 }
AppaRao Pulie90f1282019-11-05 01:07:05 +0530138 std::string msgId = "OpenBMC.0.1." + it->second.first;
139 sd_journal_send("MESSAGE=%s", "Platform firmware recovery occurred.",
140 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
141 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
142 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530143}
144
145static void logLastPanicEvent()
146{
147 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530148 if (0 != readCpldReg(ActionType::panicReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530149 {
150 return;
151 }
152
AppaRao Pulie90f1282019-11-05 01:07:05 +0530153 auto it = panicReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530154 if (it == panicReasonMap.end())
155 {
156 // No matching found. So just return without logging event.
157 return;
158 }
159
AppaRao Pulie90f1282019-11-05 01:07:05 +0530160 std::string msgId = "OpenBMC.0.1." + it->second.first;
161 sd_journal_send("MESSAGE=%s", "Platform firmware panic occurred.",
162 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
163 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
164 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530165}
166
AppaRao Puli24766942019-11-13 19:27:08 +0530167static void logResiliencyErrorEvent(const uint8_t majorErrorCode,
168 const uint8_t minorErrorCode)
169{
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000170 uint8_t cpldRoTRev = 0;
171 if (0 != readCpldReg(ActionType::readRoTRev, cpldRoTRev))
172 {
173 return;
174 }
175
AppaRao Puli24766942019-11-13 19:27:08 +0530176 auto it = majorErrorCodeMap.find(majorErrorCode);
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000177 if (cpldRoTRev == 0x02)
178 {
179 auto itRev2 = majorErrorCodeMapRev2.find(majorErrorCode);
180 if (itRev2 != majorErrorCodeMapRev2.end())
181 {
182 it = itRev2;
183 }
184 else if (it == majorErrorCodeMap.end())
185 {
186 // No matching found. So just return without logging event.
187 return;
188 }
189 }
190 else if (it == majorErrorCodeMap.end())
AppaRao Puli24766942019-11-13 19:27:08 +0530191 {
192 // No matching found. So just return without logging event.
193 return;
194 }
195
Patrick Williams304e82e2023-05-10 07:51:13 -0500196 std::string errorStr = it->second.second + "(MinorCode:0x" +
197 toHexString(minorErrorCode) + ")";
AppaRao Puli24766942019-11-13 19:27:08 +0530198 std::string msgId = "OpenBMC.0.1." + it->second.first;
199 sd_journal_send(
200 "MESSAGE=%s", "Platform firmware resiliency error occurred.",
201 "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s", msgId.c_str(),
202 "REDFISH_MESSAGE_ARGS=%s", errorStr.c_str(), NULL);
203}
204
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000205static void
206 handleLastCountChange(std::shared_ptr<sdbusplus::asio::connection> conn,
207 std::string eventName, uint8_t currentCount)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530208{
Patrick Williams304e82e2023-05-10 07:51:13 -0500209 sdbusplus::asio::setProperty(*conn, "xyz.openbmc_project.Settings",
210 "/xyz/openbmc_project/pfr/last_events",
211 "xyz.openbmc_project.PFR.LastEvents",
212 eventName, currentCount,
213 [](boost::system::error_code ec) {
214 if (ec)
215 {
216 phosphor::logging::log<phosphor::logging::level::ERR>(
217 "PFR: Unable to update currentCount",
218 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
219 return;
220 }
221 });
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000222 return;
223}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530224
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000225static void
226 checkAndLogEvents(std::shared_ptr<sdbusplus::asio::connection>& conn)
227{
228 sdbusplus::asio::getAllProperties(
229 *conn, "xyz.openbmc_project.Settings",
230 "/xyz/openbmc_project/pfr/last_events",
231 "xyz.openbmc_project.PFR.LastEvents",
232 [conn](
233 boost::system::error_code ec,
Jonathan Doman9b7b9f72022-06-03 15:31:35 -0700234 const std::vector<
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000235 std::pair<std::string, std::variant<std::monostate, uint8_t>>>&
236 properties) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500237 if (ec)
238 {
239 phosphor::logging::log<phosphor::logging::level::ERR>(
240 "PFR: Unable get PFR last events",
241 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
242 return;
243 }
244 uint8_t lastRecoveryCount = 0;
245 uint8_t lastPanicCount = 0;
246 uint8_t lastMajorErr = 0;
247 uint8_t lastMinorErr = 0;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530248
Patrick Williams304e82e2023-05-10 07:51:13 -0500249 try
250 {
251 sdbusplus::unpackProperties(
252 properties, "lastRecoveryCount", lastRecoveryCount,
253 "lastPanicCount", lastPanicCount, "lastMajorErr", lastMajorErr,
254 "lastMinorErr", lastMinorErr);
255 }
256 catch (const sdbusplus::exception::UnpackPropertyError& error)
257 {
258 phosphor::logging::log<phosphor::logging::level::ERR>(
259 "PFR: Unpack error",
260 phosphor::logging::entry("MSG=%s", error.what()));
261 return;
262 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530263
Patrick Williams304e82e2023-05-10 07:51:13 -0500264 uint8_t currPanicCount = 0;
265 if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
266 {
267 if (lastPanicCount != currPanicCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000268 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500269 // Update cached data to dbus and log redfish
270 // event by reading reason.
271 handleLastCountChange(conn, "lastPanicCount", currPanicCount);
272 if (currPanicCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000273 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500274 logLastPanicEvent();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000275 }
276 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500277 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000278
Patrick Williams304e82e2023-05-10 07:51:13 -0500279 uint8_t currRecoveryCount = 0;
280 if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
281 {
282 if (lastRecoveryCount != currRecoveryCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000283 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500284 // Update cached data to dbus and log redfish
285 // event by reading reason.
286 handleLastCountChange(conn, "lastRecoveryCount",
287 currRecoveryCount);
288 if (currRecoveryCount)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000289 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500290 logLastRecoveryEvent();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000291 }
292 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500293 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000294
Patrick Williams304e82e2023-05-10 07:51:13 -0500295 uint8_t majorErr = 0;
296 uint8_t minorErr = 0;
297 if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
298 (0 == readCpldReg(ActionType::minorError, minorErr)))
299 {
300 if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000301 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500302 // Update cached data to dbus and log redfish event by
303 // reading reason.
304 handleLastCountChange(conn, "lastMajorErr", majorErr);
305 handleLastCountChange(conn, "lastMinorErr", minorErr);
306 if (majorErr && minorErr)
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000307 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500308 logResiliencyErrorEvent(majorErr, minorErr);
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 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530313}
314
315static void monitorPlatformStateChange(
316 sdbusplus::asio::object_server& server,
317 std::shared_ptr<sdbusplus::asio::connection>& conn)
318{
319 constexpr size_t pollTimeout = 10; // seconds
320 stateTimer->expires_after(std::chrono::seconds(pollTimeout));
321 stateTimer->async_wait(
322 [&server, &conn](const boost::system::error_code& ec) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500323 if (ec == boost::asio::error::operation_aborted)
324 {
325 // Timer reset.
326 return;
327 }
328 if (ec)
329 {
330 // Platform State Monitor - Timer cancelled.
331 return;
332 }
333 checkAndLogEvents(conn);
334 monitorPlatformStateChange(server, conn);
335 });
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530336}
337
AppaRao Puli46cead92019-07-22 16:50:09 +0530338void checkAndSetCheckpoint(sdbusplus::asio::object_server& server,
339 std::shared_ptr<sdbusplus::asio::connection>& conn)
340{
341 // Check whether systemd completed all the loading.
342 conn->async_method_call(
343 [&server, &conn](boost::system::error_code ec,
344 const std::variant<uint64_t>& value) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500345 if (!ec)
346 {
347 if (std::get<uint64_t>(value))
AppaRao Puli46cead92019-07-22 16:50:09 +0530348 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500349 phosphor::logging::log<phosphor::logging::level::INFO>(
350 "BMC boot completed. Setting checkpoint 9.");
351 if (!finishedSettingChkPoint)
AppaRao Puli46cead92019-07-22 16:50:09 +0530352 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500353 finishedSettingChkPoint = true;
354 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Puli46cead92019-07-22 16:50:09 +0530355 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500356 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530357 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500358 }
359 else
360 {
361 // Failed to get data from systemd. System might not
362 // be ready yet. Attempt again for data.
363 phosphor::logging::log<phosphor::logging::level::ERR>(
364 "aync call failed to get FinishTimestamp.",
365 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
366 }
367 // FIX-ME: Latest up-stream sync caused issue in receiving
368 // StartupFinished signal. Unable to get StartupFinished signal
369 // from systemd1 hence using poll method too, to trigger it
370 // properly.
371 constexpr size_t pollTimeout = 10; // seconds
372 initTimer->expires_after(std::chrono::seconds(pollTimeout));
373 initTimer->async_wait(
374 [&server, &conn](const boost::system::error_code& ec) {
375 if (ec == boost::asio::error::operation_aborted)
AppaRao Puli46cead92019-07-22 16:50:09 +0530376 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500377 // Timer reset.
378 phosphor::logging::log<phosphor::logging::level::INFO>(
379 "Set boot Checkpoint - Timer aborted or stopped.");
380 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530381 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500382 if (ec)
383 {
384 phosphor::logging::log<phosphor::logging::level::ERR>(
385 "Set boot Checkpoint - async wait error.");
386 return;
387 }
388 checkAndSetCheckpoint(server, conn);
389 });
AppaRao Puli46cead92019-07-22 16:50:09 +0530390 },
391 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
392 "org.freedesktop.DBus.Properties", "Get",
393 "org.freedesktop.systemd1.Manager", "FinishTimestamp");
394}
395
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530396void monitorSignals(sdbusplus::asio::object_server& server,
397 std::shared_ptr<sdbusplus::asio::connection>& conn)
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530398{
AppaRao Puli46cead92019-07-22 16:50:09 +0530399 // Monitor Boot finished signal and set the checkpoint 9 to
400 // notify CPLD about BMC boot finish.
Patrick Williamsf01de222022-07-22 19:26:57 -0500401 auto bootFinishedSignal = std::make_unique<sdbusplus::bus::match_t>(
402 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli46cead92019-07-22 16:50:09 +0530403 "type='signal',"
404 "member='StartupFinished',path='/org/freedesktop/systemd1',"
405 "interface='org.freedesktop.systemd1.Manager'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500406 [&server, &conn](sdbusplus::message_t& msg) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500407 if (!finishedSettingChkPoint)
408 {
409 phosphor::logging::log<phosphor::logging::level::INFO>(
410 "BMC boot completed(StartupFinished). Setting "
411 "checkpoint 9.");
412 finishedSettingChkPoint = true;
413 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
414 }
AppaRao Puli46cead92019-07-22 16:50:09 +0530415 });
416 checkAndSetCheckpoint(server, conn);
417
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530418 // Capture the Chassis state and Start the monitor timer
419 // if state changed to 'On'. Run timer until OS boot.
420 // Stop timer if state changed to 'Off'.
Patrick Williamsf01de222022-07-22 19:26:57 -0500421 static auto matchChassisState = sdbusplus::bus::match_t(
422 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530423 "type='signal',member='PropertiesChanged', "
424 "interface='org.freedesktop.DBus.Properties', "
425 "sender='xyz.openbmc_project.State.Chassis', "
426 "arg0namespace='xyz.openbmc_project.State.Chassis'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500427 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500428 std::string intfName;
429 std::map<std::string, std::variant<std::string>> properties;
430 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530431
Patrick Williams304e82e2023-05-10 07:51:13 -0500432 const auto it = properties.find("CurrentPowerState");
433 if (it != properties.end())
434 {
435 const std::string* state = std::get_if<std::string>(&it->second);
436 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530437 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500438 if ((*state ==
439 "xyz.openbmc_project.State.Chassis.PowerState.On") &&
440 (!stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530441 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500442 stateTimerRunning = true;
443 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530444 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500445 else if ((*state == "xyz.openbmc_project.State.Chassis."
446 "PowerState.Off") &&
447 (stateTimerRunning))
448 {
449 stateTimer->cancel();
450 checkAndLogEvents(conn);
451 stateTimerRunning = false;
452 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530453 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500454
455 // Update the D-Bus properties when chassis state changes.
456 updateDbusPropertiesCache();
457 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530458 });
459
460 // Capture the Host state and Start the monitor timer
461 // if state changed to 'Running'. Run timer until OS boot.
462 // Stop timer if state changed to 'Off'.
Patrick Williamsf01de222022-07-22 19:26:57 -0500463 static auto matchHostState = sdbusplus::bus::match_t(
464 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530465 "type='signal',member='PropertiesChanged', "
466 "interface='org.freedesktop.DBus.Properties', "
467 "sender='xyz.openbmc_project.State.Chassis', "
468 "arg0namespace='xyz.openbmc_project.State.Host'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500469 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500470 std::string intfName;
471 std::map<std::string, std::variant<std::string>> properties;
472 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530473
Patrick Williams304e82e2023-05-10 07:51:13 -0500474 const auto it = properties.find("CurrentHostState");
475 if (it != properties.end())
476 {
477 const std::string* state = std::get_if<std::string>(&it->second);
478 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530479 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500480 if ((*state ==
481 "xyz.openbmc_project.State.Host.HostState.Running") &&
482 (!stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530483 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500484 stateTimerRunning = true;
485 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530486 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500487 else if (((*state == "xyz.openbmc_project.State.Host."
488 "HostState.Off") ||
489 (*state == "xyz.openbmc_project.State.Host."
490 "HostState.Quiesced")) &&
491 (stateTimerRunning))
492 {
493 stateTimer->cancel();
494 checkAndLogEvents(conn);
495 stateTimerRunning = false;
496 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530497 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500498
499 // Update the D-Bus properties when host state changes.
500 updateDbusPropertiesCache();
501 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530502 });
503
504 // Capture the OS state change and stop monitor timer
505 // if OS boots completly or becomes Inactive.
506 // start timer in other cases to mnitor states.
Patrick Williamsf01de222022-07-22 19:26:57 -0500507 static auto matchOsState = sdbusplus::bus::match_t(
508 static_cast<sdbusplus::bus_t&>(*conn),
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530509 "type='signal',member='PropertiesChanged', "
510 "interface='org.freedesktop.DBus.Properties', "
511 "sender='xyz.openbmc_project.State.Chassis', "
512 "arg0namespace='xyz.openbmc_project.State.OperatingSystem.Status'",
Patrick Williamsf01de222022-07-22 19:26:57 -0500513 [&server, &conn](sdbusplus::message_t& message) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500514 std::string intfName;
515 std::map<std::string, std::variant<std::string>> properties;
516 message.read(intfName, properties);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530517
Patrick Williams304e82e2023-05-10 07:51:13 -0500518 const auto it = properties.find("OperatingSystemState");
519 if (it != properties.end())
520 {
521 const std::string* state = std::get_if<std::string>(&it->second);
522 if (state != nullptr)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530523 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500524 // The short strings "BootComplete" and "Standby" are
525 // deprecated in favor of the full enum strings
526 // Support for the short strings will be removed in the
527 // future.
528 if (((*state == "BootComplete") ||
529 (*state == "xyz.openbmc_project.State.OperatingSystem."
530 "Status.OSStatus.BootComplete") ||
531 (*state == "Inactive") ||
532 (*state == "xyz.openbmc_project.State.OperatingSystem."
533 "Status.OSStatus.Inactive")) &&
534 (stateTimerRunning))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530535 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500536 stateTimer->cancel();
537 checkAndLogEvents(conn);
538 stateTimerRunning = false;
539 }
540 else if (!stateTimerRunning)
541 {
542 stateTimerRunning = true;
543 monitorPlatformStateChange(server, conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530544 }
545 }
Patrick Williams304e82e2023-05-10 07:51:13 -0500546 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530547 });
548
549 // First time, check and log events if any.
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000550 checkAndLogEvents(conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530551}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530552
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000553static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)
554{
555 std::string cpldVersion = pfr::readCPLDVersion();
Alex Schendel5cf320c2021-12-09 12:11:04 -0800556 lg2::info("VERSION INFO - cpld_active - {VER}", "VER", cpldVersion);
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000557 conn->async_method_call(
558 [](const boost::system::error_code ec) {
Patrick Williams304e82e2023-05-10 07:51:13 -0500559 if (ec)
560 {
561 phosphor::logging::log<phosphor::logging::level::ERR>(
562 "Unable to update cpld_active version",
563 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
564 return;
565 }
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000566 },
567 "xyz.openbmc_project.Settings",
568 "/xyz/openbmc_project/software/cpld_active",
569 "org.freedesktop.DBus.Properties", "Set",
570 "xyz.openbmc_project.Software.Version", "Version",
571 std::variant<std::string>(cpldVersion));
572 return;
573}
574
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000575void checkPfrInterface(std::shared_ptr<sdbusplus::asio::connection> conn)
576{
577 if (!i2cConfigLoaded)
578 {
579 init(conn, i2cConfigLoaded);
580 if (retrCount > 0)
581 {
582 // pfr object not loaded yet. query again.
583 return;
584 }
585 else
586 {
587 // Platform does not contain pfr object. Stop the service.
588 phosphor::logging::log<phosphor::logging::level::INFO>(
589 "Platform does not support PFR, hence stop the "
590 "service.");
591 std::exit(EXIT_SUCCESS);
592 return;
593 }
594 }
595 else
596 {
597 retrCount = 0;
598
599 bool locked = false;
600 bool prov = false;
601 bool support = false;
602 pfr::getProvisioningStatus(locked, prov, support);
603 if (support && prov)
604 {
605 // pfr provisioned.
606 phosphor::logging::log<phosphor::logging::level::INFO>(
607 "PFR Supported.");
608 return;
609 }
610 else
611 {
612 // pfr not supported, stop the service
613 phosphor::logging::log<phosphor::logging::level::INFO>(
614 "PFR not Supported. Hence stop the service");
615 std::exit(EXIT_SUCCESS);
616 }
617 }
618}
619void checkPFRandAddObjects(sdbusplus::asio::object_server& server,
620 std::shared_ptr<sdbusplus::asio::connection>& conn)
621{
622 checkPfrInterface(conn);
623
624 constexpr size_t timeout = 10; // seconds
625 pfrObjTimer->expires_after(std::chrono::seconds(timeout));
Patrick Williams304e82e2023-05-10 07:51:13 -0500626 pfrObjTimer->async_wait(
627 [&conn, &server](const boost::system::error_code& ec) {
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000628 if (ec)
629 {
630 if (ec == boost::asio::error::operation_aborted)
631 {
632 // Timer reset.
633 phosphor::logging::log<phosphor::logging::level::INFO>(
634 "pfr object found. Hence Object Timer aborted or stopped.");
635 }
636 else
637 {
638 phosphor::logging::log<phosphor::logging::level::ERR>(
639 "pfr object timer error.");
640 }
641 }
642 if (retrCount > 0)
643 {
644 checkPFRandAddObjects(server, conn);
645 }
646 else
647 {
648 pfr::monitorSignals(server, conn);
649
650 // Update the D-Bus properties.
651 updateDbusPropertiesCache();
652 // Update CPLD Version to cpld_active object in settings.
653 updateCPLDversion(conn);
654 }
655 retrCount--;
656 });
657}
AppaRao Pulidcf13122020-05-28 01:21:39 +0530658} // namespace pfr
659
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530660int main()
661{
662 // setup connection to dbus
663 boost::asio::io_service io;
664 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
AppaRao Pulidcf13122020-05-28 01:21:39 +0530665 pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
666 pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000667 pfr::pfrObjTimer = std::make_unique<boost::asio::steady_timer>(io);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530668 auto server = sdbusplus::asio::object_server(conn, true);
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000669 pfr::init(conn, pfr::i2cConfigLoaded);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000670
671 pfr::checkPFRandAddObjects(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530672
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000673 // Update CPLD Version to cpld_active object in settings.
674 pfr::updateCPLDversion(conn);
675
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530676 server.add_manager("/xyz/openbmc_project/pfr");
677
678 // Create PFR attributes object and interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530679 pfr::pfrConfigObject = std::make_unique<pfr::PfrConfig>(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530680
681 // Create Software objects using Versions interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530682 for (const auto& entry : pfr::verComponentList)
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530683 {
AppaRao Pulidcf13122020-05-28 01:21:39 +0530684 pfr::pfrVersionObjects.emplace_back(std::make_unique<pfr::PfrVersion>(
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530685 server, conn, std::get<0>(entry), std::get<1>(entry),
686 std::get<2>(entry)));
687 }
688
Zhikui Renc96f37d2021-12-08 15:40:51 -0800689 if (pfr::pfrConfigObject)
690 {
691 pfr::pfrConfigObject->updateProvisioningStatus();
692 if (pfr::pfrConfigObject->getPfrProvisioned())
693 {
Patrick Williams304e82e2023-05-10 07:51:13 -0500694 pfr::pfrPostcodeObject = std::make_unique<pfr::PfrPostcode>(server,
695 conn);
Zhikui Renc96f37d2021-12-08 15:40:51 -0800696 }
697 }
698
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530699 conn->request_name("xyz.openbmc_project.PFR.Manager");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530700 phosphor::logging::log<phosphor::logging::level::INFO>(
701 "Intel PFR service started successfully");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530702 io.run();
703
704 return 0;
705}