blob: 5560d5f866ba95e63cd42411307764b06a7ce797 [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;
AppaRao Pulie4e95652019-07-19 16:52:01 +053042
AppaRao Pulie4e95652019-07-19 16:52:01 +053043// List holds <ObjPath> <ImageType> <VersionPurpose>
44static std::vector<std::tuple<std::string, ImageType, std::string>>
45 verComponentList = {
AppaRao Pulie4e95652019-07-19 16:52:01 +053046 std::make_tuple("bmc_recovery", ImageType::bmcRecovery,
47 versionPurposeBMC),
AppaRao Pulie4e95652019-07-19 16:52:01 +053048 std::make_tuple("bios_recovery", ImageType::biosRecovery,
49 versionPurposeHost),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053050 std::make_tuple("cpld_recovery", ImageType::cpldRecovery,
51 versionPurposeOther),
Vikram Bodireddy8292dc62021-05-26 13:31:47 +053052 std::make_tuple("afm_active", ImageType::afmActive,
53 versionPurposeOther),
54 std::make_tuple("afm_recovery", ImageType::afmRecovery,
55 versionPurposeOther),
Vikram Bodireddy3c6c8c32019-12-05 11:06:15 +053056};
AppaRao Pulie4e95652019-07-19 16:52:01 +053057
AppaRao Pulie90f1282019-11-05 01:07:05 +053058// Recovery reason map.
59// {<CPLD association>,{<Redfish MessageID>, <Recovery Reason>}}
60static const boost::container::flat_map<uint8_t,
61 std::pair<std::string, std::string>>
62 recoveryReasonMap = {
63 {0x01,
64 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000065 "BIOS active image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053066 {0x02,
67 {"BIOSFirmwareRecoveryReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000068 "BIOS recovery image authentication failure"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053069 {0x03, {"MEFirmwareRecoveryReason", "ME launch failure"}},
70 {0x04, {"BIOSFirmwareRecoveryReason", "ACM launch failure"}},
71 {0x05, {"BIOSFirmwareRecoveryReason", "IBB launch failure"}},
72 {0x06, {"BIOSFirmwareRecoveryReason", "OBB launch failure"}},
73 {0x07,
74 {"BMCFirmwareRecoveryReason",
75 "BMC active image authentication failure"}},
76 {0x08,
77 {"BMCFirmwareRecoveryReason",
78 "BMC recovery image authentication failure"}},
79 {0x09, {"BMCFirmwareRecoveryReason", "BMC launch failure"}},
80 {0x0A, {"CPLDFirmwareRecoveryReason", "CPLD watchdog expired"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053081
AppaRao Pulie90f1282019-11-05 01:07:05 +053082// Panic Reason map.
83// {<CPLD association>, {<Redfish MessageID>, <Panic reason> })
84static const boost::container::flat_map<uint8_t,
85 std::pair<std::string, std::string>>
86 panicReasonMap = {
Chalapathi3fb544b2020-02-14 15:43:49 +000087 {0x01, {"BIOSFirmwarePanicReason", "BIOS update intent"}},
88 {0x02, {"BMCFirmwarePanicReason", "BMC update intent"}},
89 {0x03, {"BMCFirmwarePanicReason", "BMC reset detected"}},
90 {0x04, {"BMCFirmwarePanicReason", "BMC watchdog expired"}},
91 {0x05, {"MEFirmwarePanicReason", "ME watchdog expired"}},
92 {0x06, {"BIOSFirmwarePanicReason", "ACM watchdog expired"}},
AppaRao Pulie90f1282019-11-05 01:07:05 +053093 {0x09,
94 {"BIOSFirmwarePanicReason",
Chalapathi3fb544b2020-02-14 15:43:49 +000095 "ACM or IBB or OBB authentication failure"}}};
AppaRao Puli88aa33b2019-07-18 23:49:55 +053096
AppaRao Puli24766942019-11-13 19:27:08 +053097// Firmware resiliency major map.
98// {<CPLD association>, {<Redfish MessageID>, <Error reason> })
99static const boost::container::flat_map<uint8_t,
100 std::pair<std::string, std::string>>
101 majorErrorCodeMap = {
102 {0x01,
103 {"BMCFirmwareResiliencyError", "BMC image authentication failed"}},
104 {0x02,
105 {"BIOSFirmwareResiliencyError", "BIOS image authentication failed"}},
Chalapathi3fb544b2020-02-14 15:43:49 +0000106 {0x03, {"BIOSFirmwareResiliencyError", "Update from BIOS failed"}},
107 {0x04, {"BMCFirmwareResiliencyError", "Update from BMC failed"}}};
AppaRao Puli24766942019-11-13 19:27:08 +0530108
AppaRao Pulie4e95652019-07-19 16:52:01 +0530109static void updateDbusPropertiesCache()
110{
111 for (const auto& pfrVerObj : pfrVersionObjects)
112 {
113 pfrVerObj->updateVersion();
114 }
115
116 // Update provisoningStatus properties
117 pfrConfigObject->updateProvisioningStatus();
118
119 phosphor::logging::log<phosphor::logging::level::INFO>(
120 "PFR Manager service cache data updated.");
121}
122
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530123static void logLastRecoveryEvent()
124{
125 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530126 if (0 != readCpldReg(ActionType::recoveryReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530127 {
128 return;
129 }
130
AppaRao Pulie90f1282019-11-05 01:07:05 +0530131 auto it = recoveryReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530132 if (it == recoveryReasonMap.end())
133 {
134 // No matching found. So just return without logging event.
135 return;
136 }
AppaRao Pulie90f1282019-11-05 01:07:05 +0530137 std::string msgId = "OpenBMC.0.1." + it->second.first;
138 sd_journal_send("MESSAGE=%s", "Platform firmware recovery occurred.",
139 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
140 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
141 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530142}
143
144static void logLastPanicEvent()
145{
146 uint8_t reason = 0;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530147 if (0 != readCpldReg(ActionType::panicReason, reason))
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530148 {
149 return;
150 }
151
AppaRao Pulie90f1282019-11-05 01:07:05 +0530152 auto it = panicReasonMap.find(reason);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530153 if (it == panicReasonMap.end())
154 {
155 // No matching found. So just return without logging event.
156 return;
157 }
158
AppaRao Pulie90f1282019-11-05 01:07:05 +0530159 std::string msgId = "OpenBMC.0.1." + it->second.first;
160 sd_journal_send("MESSAGE=%s", "Platform firmware panic occurred.",
161 "PRIORITY=%i", LOG_WARNING, "REDFISH_MESSAGE_ID=%s",
162 msgId.c_str(), "REDFISH_MESSAGE_ARGS=%s",
163 it->second.second.c_str(), NULL);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530164}
165
AppaRao Puli24766942019-11-13 19:27:08 +0530166static void logResiliencyErrorEvent(const uint8_t majorErrorCode,
167 const uint8_t minorErrorCode)
168{
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000169 uint8_t cpldRoTRev = 0;
170 if (0 != readCpldReg(ActionType::readRoTRev, cpldRoTRev))
171 {
172 return;
173 }
174
AppaRao Puli24766942019-11-13 19:27:08 +0530175 auto it = majorErrorCodeMap.find(majorErrorCode);
Chalapathi Venkataramashettybcc7ce12021-05-17 04:27:21 +0000176 if (cpldRoTRev == 0x02)
177 {
178 auto itRev2 = majorErrorCodeMapRev2.find(majorErrorCode);
179 if (itRev2 != majorErrorCodeMapRev2.end())
180 {
181 it = itRev2;
182 }
183 else if (it == majorErrorCodeMap.end())
184 {
185 // No matching found. So just return without logging event.
186 return;
187 }
188 }
189 else if (it == majorErrorCodeMap.end())
AppaRao Puli24766942019-11-13 19:27:08 +0530190 {
191 // No matching found. So just return without logging event.
192 return;
193 }
194
195 std::string errorStr =
196 it->second.second + "(MinorCode:0x" + toHexString(minorErrorCode) + ")";
197 std::string msgId = "OpenBMC.0.1." + it->second.first;
198 sd_journal_send(
199 "MESSAGE=%s", "Platform firmware resiliency error occurred.",
200 "PRIORITY=%i", LOG_ERR, "REDFISH_MESSAGE_ID=%s", msgId.c_str(),
201 "REDFISH_MESSAGE_ARGS=%s", errorStr.c_str(), NULL);
202}
203
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000204static void
205 handleLastCountChange(std::shared_ptr<sdbusplus::asio::connection> conn,
206 std::string eventName, uint8_t currentCount)
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530207{
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000208 sdbusplus::asio::setProperty(
209 *conn, "xyz.openbmc_project.Settings",
210 "/xyz/openbmc_project/pfr/last_events",
211 "xyz.openbmc_project.PFR.LastEvents", eventName, currentCount,
212 [](boost::system::error_code ec) {
213 if (ec)
214 {
215 phosphor::logging::log<phosphor::logging::level::ERR>(
216 "PFR: Unable to update currentCount",
217 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
218 return;
219 }
220 });
221 return;
222}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530223
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000224static void
225 checkAndLogEvents(std::shared_ptr<sdbusplus::asio::connection>& conn)
226{
227 sdbusplus::asio::getAllProperties(
228 *conn, "xyz.openbmc_project.Settings",
229 "/xyz/openbmc_project/pfr/last_events",
230 "xyz.openbmc_project.PFR.LastEvents",
231 [conn](
232 boost::system::error_code ec,
233 std::vector<
234 std::pair<std::string, std::variant<std::monostate, uint8_t>>>&
235 properties) {
236 if (ec)
237 {
238 phosphor::logging::log<phosphor::logging::level::ERR>(
239 "PFR: Unable get PFR last events",
240 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
241 return;
242 }
243 uint8_t lastRecoveryCount = 0;
244 uint8_t lastPanicCount = 0;
245 uint8_t lastMajorErr = 0;
246 uint8_t lastMinorErr = 0;
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530247
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000248 try
249 {
250 sdbusplus::unpackProperties(
251 properties, "lastRecoveryCount", lastRecoveryCount,
252 "lastPanicCount", lastPanicCount, "lastMajorErr",
253 lastMajorErr, "lastMinorErr", lastMinorErr);
254 }
255 catch (const sdbusplus::exception::UnpackPropertyError& error)
256 {
257 phosphor::logging::log<phosphor::logging::level::ERR>(
258 "PFR: Unpack error",
259 phosphor::logging::entry("MSG=%s", error.what()));
260 return;
261 }
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530262
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000263 uint8_t currPanicCount = 0;
264 if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
265 {
266 if (lastPanicCount != currPanicCount)
267 {
268 // Update cached data to dbus and log redfish
269 // event by reading reason.
270 handleLastCountChange(conn, "lastPanicCount",
271 currPanicCount);
272 if (currPanicCount)
273 {
274 logLastPanicEvent();
275 }
276 }
277 }
278
279 uint8_t currRecoveryCount = 0;
280 if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
281 {
282 if (lastRecoveryCount != currRecoveryCount)
283 {
284 // Update cached data to dbus and log redfish
285 // event by reading reason.
286 handleLastCountChange(conn, "lastRecoveryCount",
287 currRecoveryCount);
288 if (currRecoveryCount)
289 {
290 logLastRecoveryEvent();
291 }
292 }
293 }
294
295 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))
301 {
302 // 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)
307 {
308 logResiliencyErrorEvent(majorErr, minorErr);
309 }
310 }
311 }
312 });
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) {
323 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 }
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000333 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530334 monitorPlatformStateChange(server, conn);
335 });
336}
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) {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530345 if (!ec)
AppaRao Puli46cead92019-07-22 16:50:09 +0530346 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530347 if (std::get<uint64_t>(value))
AppaRao Puli46cead92019-07-22 16:50:09 +0530348 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530349 phosphor::logging::log<phosphor::logging::level::INFO>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000350 "BMC boot completed. Setting checkpoint 9.");
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530351 if (!finishedSettingChkPoint)
352 {
353 finishedSettingChkPoint = true;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530354 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530355 }
356 return;
AppaRao Puli46cead92019-07-22 16:50:09 +0530357 }
358 }
359 else
360 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530361 // 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>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000364 "aync call failed to get FinishTimestamp.",
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530365 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
AppaRao Puli46cead92019-07-22 16:50:09 +0530366 }
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530367 // 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));
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000373 initTimer->async_wait(
374 [&server, &conn](const boost::system::error_code& ec) {
375 if (ec == boost::asio::error::operation_aborted)
376 {
377 // Timer reset.
378 phosphor::logging::log<phosphor::logging::level::INFO>(
379 "Set boot Checkpoint - Timer aborted or stopped.");
380 return;
381 }
382 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.
401 auto bootFinishedSignal = std::make_unique<sdbusplus::bus::match::match>(
402 static_cast<sdbusplus::bus::bus&>(*conn),
403 "type='signal',"
404 "member='StartupFinished',path='/org/freedesktop/systemd1',"
405 "interface='org.freedesktop.systemd1.Manager'",
406 [&server, &conn](sdbusplus::message::message& msg) {
407 if (!finishedSettingChkPoint)
408 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530409 phosphor::logging::log<phosphor::logging::level::INFO>(
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000410 "BMC boot completed(StartupFinished). Setting "
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530411 "checkpoint 9.");
AppaRao Puli46cead92019-07-22 16:50:09 +0530412 finishedSettingChkPoint = true;
AppaRao Pulidcf13122020-05-28 01:21:39 +0530413 setBMCBootCheckpoint(bmcBootFinishedChkPoint);
AppaRao Puli46cead92019-07-22 16:50:09 +0530414 }
415 });
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'.
421 static auto matchChassisState = sdbusplus::bus::match::match(
422 static_cast<sdbusplus::bus::bus&>(*conn),
423 "type='signal',member='PropertiesChanged', "
424 "interface='org.freedesktop.DBus.Properties', "
425 "sender='xyz.openbmc_project.State.Chassis', "
426 "arg0namespace='xyz.openbmc_project.State.Chassis'",
427 [&server, &conn](sdbusplus::message::message& message) {
428 std::string intfName;
429 std::map<std::string, std::variant<std::string>> properties;
430 message.read(intfName, properties);
431
432 const auto it = properties.find("CurrentPowerState");
433 if (it != properties.end())
434 {
435 const std::string* state =
436 std::get_if<std::string>(&it->second);
437 if (state != nullptr)
438 {
439 if ((*state ==
440 "xyz.openbmc_project.State.Chassis.PowerState.On") &&
441 (!stateTimerRunning))
442 {
443 stateTimerRunning = true;
444 monitorPlatformStateChange(server, conn);
445 }
446 else if ((*state == "xyz.openbmc_project.State.Chassis."
447 "PowerState.Off") &&
448 (stateTimerRunning))
449 {
450 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000451 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530452 stateTimerRunning = false;
453 }
454 }
AppaRao Pulie4e95652019-07-19 16:52:01 +0530455
456 // Update the D-Bus properties when chassis state changes.
457 updateDbusPropertiesCache();
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530458 }
459 });
460
461 // Capture the Host state and Start the monitor timer
462 // if state changed to 'Running'. Run timer until OS boot.
463 // Stop timer if state changed to 'Off'.
464 static auto matchHostState = sdbusplus::bus::match::match(
465 static_cast<sdbusplus::bus::bus&>(*conn),
466 "type='signal',member='PropertiesChanged', "
467 "interface='org.freedesktop.DBus.Properties', "
468 "sender='xyz.openbmc_project.State.Chassis', "
469 "arg0namespace='xyz.openbmc_project.State.Host'",
470 [&server, &conn](sdbusplus::message::message& message) {
471 std::string intfName;
472 std::map<std::string, std::variant<std::string>> properties;
473 message.read(intfName, properties);
474
475 const auto it = properties.find("CurrentHostState");
476 if (it != properties.end())
477 {
478 const std::string* state =
479 std::get_if<std::string>(&it->second);
480 if (state != nullptr)
481 {
482 if ((*state ==
483 "xyz.openbmc_project.State.Host.HostState.Running") &&
484 (!stateTimerRunning))
485 {
486 stateTimerRunning = true;
487 monitorPlatformStateChange(server, conn);
488 }
489 else if (((*state == "xyz.openbmc_project.State.Host."
490 "HostState.Off") ||
491 (*state == "xyz.openbmc_project.State.Host."
492 "HostState.Quiesced")) &&
493 (stateTimerRunning))
494 {
495 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000496 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530497 stateTimerRunning = false;
498 }
499 }
AppaRao Pulie4e95652019-07-19 16:52:01 +0530500
501 // Update the D-Bus properties when host state changes.
502 updateDbusPropertiesCache();
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530503 }
504 });
505
506 // Capture the OS state change and stop monitor timer
507 // if OS boots completly or becomes Inactive.
508 // start timer in other cases to mnitor states.
509 static auto matchOsState = sdbusplus::bus::match::match(
510 static_cast<sdbusplus::bus::bus&>(*conn),
511 "type='signal',member='PropertiesChanged', "
512 "interface='org.freedesktop.DBus.Properties', "
513 "sender='xyz.openbmc_project.State.Chassis', "
514 "arg0namespace='xyz.openbmc_project.State.OperatingSystem.Status'",
515 [&server, &conn](sdbusplus::message::message& message) {
516 std::string intfName;
517 std::map<std::string, std::variant<std::string>> properties;
518 message.read(intfName, properties);
519
520 const auto it = properties.find("OperatingSystemState");
521 if (it != properties.end())
522 {
523 const std::string* state =
524 std::get_if<std::string>(&it->second);
525 if (state != nullptr)
526 {
Jason M. Billsf89de472022-01-19 16:14:19 -0800527 // The short strings "BootComplete" and "Standby" are
528 // deprecated in favor of the full enum strings
529 // Support for the short strings will be removed in the
530 // future.
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530531 if (((*state == "BootComplete") ||
Jason M. Billsf89de472022-01-19 16:14:19 -0800532 (*state == "xyz.openbmc_project.State.OperatingSystem."
533 "Status.OSStatus.BootComplete") ||
534 (*state == "Inactive") ||
535 (*state == "xyz.openbmc_project.State.OperatingSystem."
536 "Status.OSStatus.Inactive")) &&
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530537 (stateTimerRunning))
538 {
539 stateTimer->cancel();
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000540 checkAndLogEvents(conn);
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530541 stateTimerRunning = false;
542 }
543 else if (!stateTimerRunning)
544 {
545 stateTimerRunning = true;
546 monitorPlatformStateChange(server, conn);
547 }
548 }
549 }
550 });
551
552 // First time, check and log events if any.
Chalapathi Venkataramashettyb2134872020-10-02 21:45:36 +0000553 checkAndLogEvents(conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530554}
AppaRao Puli88aa33b2019-07-18 23:49:55 +0530555
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000556static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)
557{
558 std::string cpldVersion = pfr::readCPLDVersion();
559 conn->async_method_call(
560 [](const boost::system::error_code ec) {
561 if (ec)
562 {
563 phosphor::logging::log<phosphor::logging::level::ERR>(
564 "Unable to update cpld_active version",
565 phosphor::logging::entry("MSG=%s", ec.message().c_str()));
566 return;
567 }
568 },
569 "xyz.openbmc_project.Settings",
570 "/xyz/openbmc_project/software/cpld_active",
571 "org.freedesktop.DBus.Properties", "Set",
572 "xyz.openbmc_project.Software.Version", "Version",
573 std::variant<std::string>(cpldVersion));
574 return;
575}
576
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000577void checkPfrInterface(std::shared_ptr<sdbusplus::asio::connection> conn)
578{
579 if (!i2cConfigLoaded)
580 {
581 init(conn, i2cConfigLoaded);
582 if (retrCount > 0)
583 {
584 // pfr object not loaded yet. query again.
585 return;
586 }
587 else
588 {
589 // Platform does not contain pfr object. Stop the service.
590 phosphor::logging::log<phosphor::logging::level::INFO>(
591 "Platform does not support PFR, hence stop the "
592 "service.");
593 std::exit(EXIT_SUCCESS);
594 return;
595 }
596 }
597 else
598 {
599 retrCount = 0;
600
601 bool locked = false;
602 bool prov = false;
603 bool support = false;
604 pfr::getProvisioningStatus(locked, prov, support);
605 if (support && prov)
606 {
607 // pfr provisioned.
608 phosphor::logging::log<phosphor::logging::level::INFO>(
609 "PFR Supported.");
610 return;
611 }
612 else
613 {
614 // pfr not supported, stop the service
615 phosphor::logging::log<phosphor::logging::level::INFO>(
616 "PFR not Supported. Hence stop the service");
617 std::exit(EXIT_SUCCESS);
618 }
619 }
620}
621void checkPFRandAddObjects(sdbusplus::asio::object_server& server,
622 std::shared_ptr<sdbusplus::asio::connection>& conn)
623{
624 checkPfrInterface(conn);
625
626 constexpr size_t timeout = 10; // seconds
627 pfrObjTimer->expires_after(std::chrono::seconds(timeout));
628 pfrObjTimer->async_wait([&conn,
629 &server](const boost::system::error_code& ec) {
630 if (ec)
631 {
632 if (ec == boost::asio::error::operation_aborted)
633 {
634 // Timer reset.
635 phosphor::logging::log<phosphor::logging::level::INFO>(
636 "pfr object found. Hence Object Timer aborted or stopped.");
637 }
638 else
639 {
640 phosphor::logging::log<phosphor::logging::level::ERR>(
641 "pfr object timer error.");
642 }
643 }
644 if (retrCount > 0)
645 {
646 checkPFRandAddObjects(server, conn);
647 }
648 else
649 {
650 pfr::monitorSignals(server, conn);
651
652 // Update the D-Bus properties.
653 updateDbusPropertiesCache();
654 // Update CPLD Version to cpld_active object in settings.
655 updateCPLDversion(conn);
656 }
657 retrCount--;
658 });
659}
AppaRao Pulidcf13122020-05-28 01:21:39 +0530660} // namespace pfr
661
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530662int main()
663{
664 // setup connection to dbus
665 boost::asio::io_service io;
666 auto conn = std::make_shared<sdbusplus::asio::connection>(io);
AppaRao Pulidcf13122020-05-28 01:21:39 +0530667 pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
668 pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000669 pfr::pfrObjTimer = std::make_unique<boost::asio::steady_timer>(io);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530670 auto server = sdbusplus::asio::object_server(conn, true);
Chalapathi Venkataramashetty55e79342021-03-29 10:17:48 +0000671 pfr::init(conn, pfr::i2cConfigLoaded);
Chalapathi Venkataramashetty29b47792020-09-10 21:43:53 +0000672
673 pfr::checkPFRandAddObjects(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530674
Chalapathi Venkataramashettye6fb18e2021-02-03 14:51:00 +0000675 // Update CPLD Version to cpld_active object in settings.
676 pfr::updateCPLDversion(conn);
677
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530678 server.add_manager("/xyz/openbmc_project/pfr");
679
680 // Create PFR attributes object and interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530681 pfr::pfrConfigObject = std::make_unique<pfr::PfrConfig>(server, conn);
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530682
683 // Create Software objects using Versions interface
AppaRao Pulidcf13122020-05-28 01:21:39 +0530684 for (const auto& entry : pfr::verComponentList)
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530685 {
AppaRao Pulidcf13122020-05-28 01:21:39 +0530686 pfr::pfrVersionObjects.emplace_back(std::make_unique<pfr::PfrVersion>(
AppaRao Pulia9bf9712020-01-12 05:45:48 +0530687 server, conn, std::get<0>(entry), std::get<1>(entry),
688 std::get<2>(entry)));
689 }
690
691 conn->request_name("xyz.openbmc_project.PFR.Manager");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530692 phosphor::logging::log<phosphor::logging::level::INFO>(
693 "Intel PFR service started successfully");
AppaRao Pulie63eeda2019-07-05 16:25:38 +0530694 io.run();
695
696 return 0;
697}