blob: 0894a4545a3de9436f529dc4888e34c65d7537a9 [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 IBM 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 */
Matt Spinler4e8078c2019-07-09 13:22:32 -050016#include "manager.hpp"
17
18#include "additional_data.hpp"
Matt Spinler3387eac2023-07-06 14:56:02 -050019#include "elog_serialize.hpp"
Matt Spinler05c2c6c2019-12-18 14:02:09 -060020#include "json_utils.hpp"
Matt Spinler89fa0822019-07-17 13:54:30 -050021#include "pel.hpp"
Vijay Lobo2fb10212021-08-22 23:24:16 -050022#include "pel_entry.hpp"
Matt Spinler1962e082020-08-05 13:44:53 -050023#include "service_indicators.hpp"
Matt Spinler8b81ec02022-07-12 13:25:37 -050024#include "severity.hpp"
Matt Spinler89fa0822019-07-17 13:54:30 -050025
Matt Spinler22421b92020-07-17 09:41:08 -050026#include <fmt/format.h>
Matt Spinlerff9cec22020-07-15 13:06:35 -050027#include <sys/inotify.h>
Matt Spinler6b1a5c82020-01-07 08:48:53 -060028#include <unistd.h>
29
Patrick Williams2544b412022-10-04 08:41:06 -050030#include <xyz/openbmc_project/Common/error.hpp>
31#include <xyz/openbmc_project/Logging/Create/server.hpp>
32
Matt Spinler89fa0822019-07-17 13:54:30 -050033#include <filesystem>
34#include <fstream>
Matt Spinler0003af12022-06-08 10:46:17 -050035#include <locale>
Matt Spinler4e8078c2019-07-09 13:22:32 -050036
37namespace openpower
38{
39namespace pels
40{
41
42using namespace phosphor::logging;
Matt Spinler89fa0822019-07-17 13:54:30 -050043namespace fs = std::filesystem;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080044namespace rg = openpower::pels::message;
Matt Spinler4e8078c2019-07-09 13:22:32 -050045
Matt Spinlera34ab722019-12-16 10:39:32 -060046namespace common_error = sdbusplus::xyz::openbmc_project::Common::Error;
47
Matt Spinler56ad2a02020-03-26 14:00:52 -050048using Create = sdbusplus::xyz::openbmc_project::Logging::server::Create;
49
Matt Spinler4e8078c2019-07-09 13:22:32 -050050namespace additional_data
51{
52constexpr auto rawPEL = "RAWPEL";
Matt Spinler19e72902020-01-24 11:05:20 -060053constexpr auto esel = "ESEL";
Matt Spinler30ddc9f2020-07-16 15:39:59 -050054constexpr auto error = "ERROR_NAME";
Matt Spinler19e72902020-01-24 11:05:20 -060055} // namespace additional_data
Matt Spinler4e8078c2019-07-09 13:22:32 -050056
Matt Spinler30ddc9f2020-07-16 15:39:59 -050057constexpr auto defaultLogMessage = "xyz.openbmc_project.Logging.Error.Default";
Matt Spinler0dd22c82023-05-04 15:28:12 -050058constexpr uint32_t bmcThermalCompID = 0x2700;
59constexpr uint32_t bmcFansCompID = 0x2800;
Matt Spinler30ddc9f2020-07-16 15:39:59 -050060
Matt Spinlerff9cec22020-07-15 13:06:35 -050061Manager::~Manager()
62{
63 if (_pelFileDeleteFD != -1)
64 {
65 if (_pelFileDeleteWatchFD != -1)
66 {
67 inotify_rm_watch(_pelFileDeleteFD, _pelFileDeleteWatchFD);
68 }
69 close(_pelFileDeleteFD);
70 }
71}
72
Matt Spinler4e8078c2019-07-09 13:22:32 -050073void Manager::create(const std::string& message, uint32_t obmcLogID,
74 uint64_t timestamp, Entry::Level severity,
75 const std::vector<std::string>& additionalData,
Matt Spinler56ad2a02020-03-26 14:00:52 -050076 const std::vector<std::string>& associations,
77 const FFDCEntries& ffdc)
Matt Spinler4e8078c2019-07-09 13:22:32 -050078{
79 AdditionalData ad{additionalData};
80
Matt Spinler19e72902020-01-24 11:05:20 -060081 // If a PEL was passed in via a filename or in an ESEL,
82 // use that. Otherwise, create one.
Matt Spinler4e8078c2019-07-09 13:22:32 -050083 auto rawPelPath = ad.getValue(additional_data::rawPEL);
84 if (rawPelPath)
85 {
86 addRawPEL(*rawPelPath, obmcLogID);
87 }
88 else
89 {
Matt Spinler19e72902020-01-24 11:05:20 -060090 auto esel = ad.getValue(additional_data::esel);
91 if (esel)
92 {
93 addESELPEL(*esel, obmcLogID);
94 }
95 else
96 {
97 createPEL(message, obmcLogID, timestamp, severity, additionalData,
Matt Spinler56ad2a02020-03-26 14:00:52 -050098 associations, ffdc);
Matt Spinler19e72902020-01-24 11:05:20 -060099 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500100 }
Adriana Kobylake7d271a2020-12-07 14:32:44 -0600101
102 setEntryPath(obmcLogID);
Vijay Lobocbc93a42021-05-20 19:04:07 -0500103 setServiceProviderNotifyFlag(obmcLogID);
Matt Spinler4e8078c2019-07-09 13:22:32 -0500104}
105
106void Manager::addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID)
107{
Matt Spinler89fa0822019-07-17 13:54:30 -0500108 if (fs::exists(rawPelPath))
109 {
110 std::ifstream file(rawPelPath, std::ios::in | std::ios::binary);
111
112 auto data = std::vector<uint8_t>(std::istreambuf_iterator<char>(file),
113 std::istreambuf_iterator<char>());
114 if (file.fail())
115 {
116 log<level::ERR>("Filesystem error reading a raw PEL",
117 entry("PELFILE=%s", rawPelPath.c_str()),
118 entry("OBMCLOGID=%d", obmcLogID));
119 // TODO, Decide what to do here. Maybe nothing.
120 return;
121 }
122
123 file.close();
124
Matt Spinler19e72902020-01-24 11:05:20 -0600125 addPEL(data, obmcLogID);
Matt Spinler67416922021-07-19 12:34:57 -0600126
127 std::error_code ec;
128 fs::remove(rawPelPath, ec);
Matt Spinler89fa0822019-07-17 13:54:30 -0500129 }
130 else
131 {
132 log<level::ERR>("Raw PEL file from BMC event log does not exist",
133 entry("PELFILE=%s", (rawPelPath).c_str()),
134 entry("OBMCLOGID=%d", obmcLogID));
135 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500136}
137
Matt Spinler19e72902020-01-24 11:05:20 -0600138void Manager::addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID)
139{
Matt Spinler19e72902020-01-24 11:05:20 -0600140 auto pel = std::make_unique<openpower::pels::PEL>(pelData, obmcLogID);
141 if (pel->valid())
142 {
Sumit Kumar8ec41562021-10-29 05:39:37 -0500143 // PELs created by others still need this field set by us.
144 pel->setCommitTime();
145
Sumit Kumara1e40842021-06-23 09:52:25 -0500146 // Assign Id other than to Hostbot PEL
147 if ((pel->privateHeader()).creatorID() !=
148 static_cast<uint8_t>(CreatorID::hostboot))
149 {
150 pel->assignID();
151 }
Sumit Kumar2ccdcef2021-07-31 10:04:58 -0500152 else
153 {
154 const Repository::LogID id{Repository::LogID::Pel(pel->id())};
155 auto result = _repo.hasPEL(id);
156 if (result)
157 {
158 log<level::WARNING>(
159 fmt::format("Duplicate HostBoot PEL Id {:#X} found; "
160 "moving it to archive folder",
161 pel->id())
162 .c_str());
163
164 _repo.archivePEL(*pel);
Matt Spinlerd8fb5ba2022-01-25 13:01:14 -0600165
166 // No need to keep around the openBMC event log entry
167 scheduleObmcLogDelete(obmcLogID);
Sumit Kumar2ccdcef2021-07-31 10:04:58 -0500168 return;
169 }
170 }
Sumit Kumara1e40842021-06-23 09:52:25 -0500171
Sumit Kumar3160a542021-04-26 08:07:04 -0500172 // Update System Info to Extended User Data
173 pel->updateSysInfoInExtendedUserDataSection(*_dataIface);
174
Sumit Kumar3e274432021-09-14 06:37:56 -0500175 // Check for severity 0x51 and update boot progress SRC
176 updateProgressSRC(pel);
177
Matt Spinler19e72902020-01-24 11:05:20 -0600178 try
179 {
Matt Spinlerd0ab1cf2021-02-10 13:26:18 -0600180 log<level::DEBUG>(
Matt Spinler6321ba32020-07-17 09:58:19 -0500181 fmt::format("Adding external PEL {:#x} (BMC ID {}) to repo",
182 pel->id(), obmcLogID)
183 .c_str());
Matt Spinler5f5352e2020-03-05 16:23:27 -0600184
Matt Spinler19e72902020-01-24 11:05:20 -0600185 _repo.add(pel);
Matt Spinler7e727a32020-07-07 15:00:17 -0500186
187 if (_repo.sizeWarning())
188 {
189 scheduleRepoPrune();
190 }
Matt Spinler1962e082020-08-05 13:44:53 -0500191
192 // Activate any resulting service indicators if necessary
193 auto policy = service_indicators::getPolicy(*_dataIface);
194 policy->activate(*pel);
Matt Spinler19e72902020-01-24 11:05:20 -0600195 }
Patrick Williams66491c62021-10-06 12:23:37 -0500196 catch (const std::exception& e)
Matt Spinler19e72902020-01-24 11:05:20 -0600197 {
198 // Probably a full or r/o filesystem, not much we can do.
199 log<level::ERR>("Unable to add PEL to Repository",
200 entry("PEL_ID=0x%X", pel->id()));
201 }
Andrew Geissler44fc3162020-07-09 09:21:31 -0500202
Vijay Lobod354a392021-06-01 16:21:02 -0500203 updateEventId(pel);
Matt Spinler28d6ae22022-03-18 11:18:27 -0500204 updateResolution(*pel);
Matt Spinler3387eac2023-07-06 14:56:02 -0500205 serializeLogEntry(obmcLogID);
Vijay Loboafb1b462021-07-21 23:29:13 -0500206 createPELEntry(obmcLogID);
Matt Spinlerdf5cb832022-07-12 12:47:26 -0500207
208 // Check if firmware should quiesce system due to error
209 checkPelAndQuiesce(pel);
Matt Spinler19e72902020-01-24 11:05:20 -0600210 }
211 else
212 {
213 log<level::ERR>("Invalid PEL received from the host",
214 entry("OBMCLOGID=%d", obmcLogID));
215
216 AdditionalData ad;
217 ad.add("PLID", getNumberString("0x%08X", pel->plid()));
218 ad.add("OBMC_LOG_ID", std::to_string(obmcLogID));
219 ad.add("PEL_SIZE", std::to_string(pelData.size()));
220
221 std::string asciiString;
222 auto src = pel->primarySRC();
223 if (src)
224 {
225 asciiString = (*src)->asciiString();
226 }
227
228 ad.add("SRC", asciiString);
229
230 _eventLogger.log("org.open_power.Logging.Error.BadHostPEL",
231 Entry::Level::Error, ad);
Matt Spinlerfe721892020-04-02 10:28:08 -0500232
233 // Save it to a file for debug in the lab. Just keep the latest.
234 // Not adding it to the PEL because it could already be max size
235 // and don't want to truncate an already invalid PEL.
236 std::ofstream pelFile{getPELRepoPath() / "badPEL"};
237 pelFile.write(reinterpret_cast<const char*>(pelData.data()),
238 pelData.size());
Matt Spinlerd8fb5ba2022-01-25 13:01:14 -0600239
240 // No need to keep around the openBMC event log entry
241 scheduleObmcLogDelete(obmcLogID);
Matt Spinler19e72902020-01-24 11:05:20 -0600242 }
243}
244
245void Manager::addESELPEL(const std::string& esel, uint32_t obmcLogID)
246{
247 std::vector<uint8_t> data;
248
Matt Spinler5f5352e2020-03-05 16:23:27 -0600249 log<level::DEBUG>("Adding PEL from ESEL",
250 entry("OBMC_LOG_ID=%d", obmcLogID));
251
Matt Spinler19e72902020-01-24 11:05:20 -0600252 try
253 {
254 data = std::move(eselToRawData(esel));
255 }
Patrick Williams66491c62021-10-06 12:23:37 -0500256 catch (const std::exception& e)
Matt Spinler19e72902020-01-24 11:05:20 -0600257 {
258 // Try to add it below anyway, so it follows the usual bad data path.
259 log<level::ERR>("Problems converting ESEL string to a byte vector");
260 }
261
262 addPEL(data, obmcLogID);
263}
264
265std::vector<uint8_t> Manager::eselToRawData(const std::string& esel)
266{
267 std::vector<uint8_t> data;
268 std::string byteString;
269
270 // As the eSEL string looks like: "50 48 00 ab ..." there are 3
271 // characters per raw byte, and since the actual PEL data starts
272 // at the 16th byte, the code will grab the PEL data starting at
273 // offset 48 in the string.
274 static constexpr size_t pelStart = 16 * 3;
275
276 if (esel.size() <= pelStart)
277 {
278 log<level::ERR>("ESEL data too short",
279 entry("ESEL_SIZE=%d", esel.size()));
280
281 throw std::length_error("ESEL data too short");
282 }
283
284 for (size_t i = pelStart; i < esel.size(); i += 3)
285 {
286 if (i + 1 < esel.size())
287 {
288 byteString = esel.substr(i, 2);
289 data.push_back(std::stoi(byteString, nullptr, 16));
290 }
291 else
292 {
293 log<level::ERR>("ESEL data too short",
294 entry("ESEL_SIZE=%d", esel.size()));
295 throw std::length_error("ESEL data too short");
296 }
297 }
298
299 return data;
300}
301
Matt Spinler4e8078c2019-07-09 13:22:32 -0500302void Manager::erase(uint32_t obmcLogID)
303{
Matt Spinler475e5742019-07-18 16:09:49 -0500304 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
305
Vijay Loboafb1b462021-07-21 23:29:13 -0500306 auto path = std::string(OBJ_ENTRY) + '/' + std::to_string(obmcLogID);
307 _pelEntries.erase(path);
Matt Spinler475e5742019-07-18 16:09:49 -0500308 _repo.remove(id);
Matt Spinler4e8078c2019-07-09 13:22:32 -0500309}
310
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500311bool Manager::isDeleteProhibited(uint32_t /*obmcLogID*/)
Matt Spinler4e8078c2019-07-09 13:22:32 -0500312{
313 return false;
314}
315
Matt Spinler56ad2a02020-03-26 14:00:52 -0500316PelFFDC Manager::convertToPelFFDC(const FFDCEntries& ffdc)
317{
318 PelFFDC pelFFDC;
319
320 std::for_each(ffdc.begin(), ffdc.end(), [&pelFFDC](const auto& f) {
321 PelFFDCfile pf;
322 pf.subType = std::get<ffdcSubtypePos>(f);
323 pf.version = std::get<ffdcVersionPos>(f);
324 pf.fd = std::get<ffdcFDPos>(f);
325
326 switch (std::get<ffdcFormatPos>(f))
327 {
328 case Create::FFDCFormat::JSON:
329 pf.format = UserDataFormat::json;
330 break;
331 case Create::FFDCFormat::CBOR:
332 pf.format = UserDataFormat::cbor;
333 break;
334 case Create::FFDCFormat::Text:
335 pf.format = UserDataFormat::text;
336 break;
337 case Create::FFDCFormat::Custom:
338 pf.format = UserDataFormat::custom;
339 break;
340 }
341
342 pelFFDC.push_back(pf);
343 });
344
345 return pelFFDC;
346}
347
Matt Spinler4e8078c2019-07-09 13:22:32 -0500348void Manager::createPEL(const std::string& message, uint32_t obmcLogID,
349 uint64_t timestamp,
350 phosphor::logging::Entry::Level severity,
351 const std::vector<std::string>& additionalData,
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500352 const std::vector<std::string>& /*associations*/,
Matt Spinler56ad2a02020-03-26 14:00:52 -0500353 const FFDCEntries& ffdc)
Matt Spinler4e8078c2019-07-09 13:22:32 -0500354{
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800355 auto entry = _registry.lookup(message, rg::LookupType::name);
Matt Spinler30ddc9f2020-07-16 15:39:59 -0500356 auto pelFFDC = convertToPelFFDC(ffdc);
357 AdditionalData ad{additionalData};
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600358 std::string msg;
Matt Spinler67456c22019-10-21 12:22:49 -0500359
Matt Spinler30ddc9f2020-07-16 15:39:59 -0500360 if (!entry)
Matt Spinler67456c22019-10-21 12:22:49 -0500361 {
Matt Spinler30ddc9f2020-07-16 15:39:59 -0500362 // Instead, get the default entry that means there is no
363 // other matching entry. This error will still use the
364 // AdditionalData values of the original error, and this
365 // code will add the error message value that wasn't found
366 // to this AD. This way, there will at least be a PEL,
367 // possibly with callouts, to allow users to debug the
368 // issue that caused the error even without its own PEL.
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600369 msg = "Event not found in PEL message registry: " + message;
370 log<level::INFO>(msg.c_str());
Matt Spinler30ddc9f2020-07-16 15:39:59 -0500371
372 entry = _registry.lookup(defaultLogMessage, rg::LookupType::name);
373 if (!entry)
374 {
375 log<level::ERR>("Default event not found in PEL message registry");
376 return;
377 }
378
379 ad.add(additional_data::error, message);
380 }
381
382 auto pel = std::make_unique<openpower::pels::PEL>(
Matt Spinler9d921092022-12-15 11:54:49 -0600383 *entry, obmcLogID, timestamp, severity, ad, pelFFDC, *_dataIface,
384 *_journal);
Matt Spinler30ddc9f2020-07-16 15:39:59 -0500385
386 _repo.add(pel);
387
388 if (_repo.sizeWarning())
389 {
390 scheduleRepoPrune();
391 }
392
393 auto src = pel->primarySRC();
394 if (src)
395 {
Patrick Williams2544b412022-10-04 08:41:06 -0500396 auto m = fmt::format("Created PEL {:#x} (BMC ID {}) with SRC {}",
397 pel->id(), pel->obmcLogID(),
398 (*src)->asciiString());
Matt Spinler45796e82022-07-01 11:25:27 -0500399 while (m.back() == ' ')
Matt Spinler30ddc9f2020-07-16 15:39:59 -0500400 {
Matt Spinler45796e82022-07-01 11:25:27 -0500401 m.pop_back();
Matt Spinler30ddc9f2020-07-16 15:39:59 -0500402 }
Matt Spinler45796e82022-07-01 11:25:27 -0500403 log<level::INFO>(m.c_str());
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600404 }
Matt Spinler1962e082020-08-05 13:44:53 -0500405
Sumit Kumar3e274432021-09-14 06:37:56 -0500406 // Check for severity 0x51 and update boot progress SRC
407 updateProgressSRC(pel);
408
Matt Spinler1962e082020-08-05 13:44:53 -0500409 // Activate any resulting service indicators if necessary
410 auto policy = service_indicators::getPolicy(*_dataIface);
411 policy->activate(*pel);
Andrew Geissler44fc3162020-07-09 09:21:31 -0500412
Matt Spinler8b81ec02022-07-12 13:25:37 -0500413 updateDBusSeverity(*pel);
Vijay Lobod354a392021-06-01 16:21:02 -0500414 updateEventId(pel);
Matt Spinler28d6ae22022-03-18 11:18:27 -0500415 updateResolution(*pel);
Matt Spinler3387eac2023-07-06 14:56:02 -0500416 serializeLogEntry(obmcLogID);
Vijay Loboafb1b462021-07-21 23:29:13 -0500417 createPELEntry(obmcLogID);
Matt Spinlerdf5cb832022-07-12 12:47:26 -0500418
419 // Check if firmware should quiesce system due to error
420 checkPelAndQuiesce(pel);
Matt Spinler4e8078c2019-07-09 13:22:32 -0500421}
422
Matt Spinlera34ab722019-12-16 10:39:32 -0600423sdbusplus::message::unix_fd Manager::getPEL(uint32_t pelID)
424{
425 Repository::LogID id{Repository::LogID::Pel(pelID)};
426 std::optional<int> fd;
427
Matt Spinler5f5352e2020-03-05 16:23:27 -0600428 log<level::DEBUG>("getPEL", entry("PEL_ID=0x%X", pelID));
429
Matt Spinlera34ab722019-12-16 10:39:32 -0600430 try
431 {
432 fd = _repo.getPELFD(id);
433 }
Patrick Williams66491c62021-10-06 12:23:37 -0500434 catch (const std::exception& e)
Matt Spinlera34ab722019-12-16 10:39:32 -0600435 {
436 throw common_error::InternalFailure();
437 }
438
439 if (!fd)
440 {
441 throw common_error::InvalidArgument();
442 }
443
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600444 scheduleFDClose(*fd);
445
Matt Spinlera34ab722019-12-16 10:39:32 -0600446 return *fd;
447}
448
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600449void Manager::scheduleFDClose(int fd)
450{
451 _fdCloserEventSource = std::make_unique<sdeventplus::source::Defer>(
Matt Spinlerff9cec22020-07-15 13:06:35 -0500452 _event, std::bind(std::mem_fn(&Manager::closeFD), this, fd,
453 std::placeholders::_1));
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600454}
455
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500456void Manager::closeFD(int fd, sdeventplus::source::EventBase& /*source*/)
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600457{
458 close(fd);
459 _fdCloserEventSource.reset();
460}
461
Matt Spinlera34ab722019-12-16 10:39:32 -0600462std::vector<uint8_t> Manager::getPELFromOBMCID(uint32_t obmcLogID)
463{
464 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
465 std::optional<std::vector<uint8_t>> data;
466
Matt Spinler5f5352e2020-03-05 16:23:27 -0600467 log<level::DEBUG>("getPELFromOBMCID", entry("OBMC_LOG_ID=%d", obmcLogID));
468
Matt Spinlera34ab722019-12-16 10:39:32 -0600469 try
470 {
471 data = _repo.getPELData(id);
472 }
Patrick Williams66491c62021-10-06 12:23:37 -0500473 catch (const std::exception& e)
Matt Spinlera34ab722019-12-16 10:39:32 -0600474 {
475 throw common_error::InternalFailure();
476 }
477
478 if (!data)
479 {
480 throw common_error::InvalidArgument();
481 }
482
483 return *data;
484}
485
486void Manager::hostAck(uint32_t pelID)
487{
488 Repository::LogID id{Repository::LogID::Pel(pelID)};
489
Matt Spinler5f5352e2020-03-05 16:23:27 -0600490 log<level::DEBUG>("HostAck", entry("PEL_ID=0x%X", pelID));
491
Matt Spinlera34ab722019-12-16 10:39:32 -0600492 if (!_repo.hasPEL(id))
493 {
494 throw common_error::InvalidArgument();
495 }
496
497 if (_hostNotifier)
498 {
499 _hostNotifier->ackPEL(pelID);
500 }
501}
502
503void Manager::hostReject(uint32_t pelID, RejectionReason reason)
504{
505 Repository::LogID id{Repository::LogID::Pel(pelID)};
506
Matt Spinler5f5352e2020-03-05 16:23:27 -0600507 log<level::DEBUG>("HostReject", entry("PEL_ID=0x%X", pelID),
508 entry("REASON=%d", static_cast<int>(reason)));
509
Matt Spinlera34ab722019-12-16 10:39:32 -0600510 if (!_repo.hasPEL(id))
511 {
512 throw common_error::InvalidArgument();
513 }
514
Matt Spinler05c2c6c2019-12-18 14:02:09 -0600515 if (reason == RejectionReason::BadPEL)
Matt Spinlera34ab722019-12-16 10:39:32 -0600516 {
Matt Spinler05c2c6c2019-12-18 14:02:09 -0600517 AdditionalData data;
518 data.add("BAD_ID", getNumberString("0x%08X", pelID));
519 _eventLogger.log("org.open_power.Logging.Error.SentBadPELToHost",
520 Entry::Level::Informational, data);
521 if (_hostNotifier)
Matt Spinlera34ab722019-12-16 10:39:32 -0600522 {
523 _hostNotifier->setBadPEL(pelID);
524 }
Matt Spinler05c2c6c2019-12-18 14:02:09 -0600525 }
526 else if ((reason == RejectionReason::HostFull) && _hostNotifier)
527 {
528 _hostNotifier->setHostFull(pelID);
Matt Spinlera34ab722019-12-16 10:39:32 -0600529 }
530}
531
Matt Spinler7e727a32020-07-07 15:00:17 -0500532void Manager::scheduleRepoPrune()
533{
Matt Spinler7e727a32020-07-07 15:00:17 -0500534 _repoPrunerEventSource = std::make_unique<sdeventplus::source::Defer>(
Matt Spinlerff9cec22020-07-15 13:06:35 -0500535 _event, std::bind(std::mem_fn(&Manager::pruneRepo), this,
536 std::placeholders::_1));
Matt Spinler7e727a32020-07-07 15:00:17 -0500537}
538
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500539void Manager::pruneRepo(sdeventplus::source::EventBase& /*source*/)
Matt Spinler7e727a32020-07-07 15:00:17 -0500540{
Sumit Kumar027bf282022-01-24 11:25:19 -0600541 auto idsWithHwIsoEntry = _dataIface->getLogIDWithHwIsolation();
542
543 auto idsToDelete = _repo.prune(idsWithHwIsoEntry);
Matt Spinler7e727a32020-07-07 15:00:17 -0500544
545 // Remove the OpenBMC event logs for the PELs that were just removed.
546 std::for_each(idsToDelete.begin(), idsToDelete.end(),
547 [this](auto id) { this->_logManager.erase(id); });
548
549 _repoPrunerEventSource.reset();
550}
551
Matt Spinlerff9cec22020-07-15 13:06:35 -0500552void Manager::setupPELDeleteWatch()
553{
554 _pelFileDeleteFD = inotify_init1(IN_NONBLOCK);
555 if (-1 == _pelFileDeleteFD)
556 {
557 auto e = errno;
Patrick Williams2544b412022-10-04 08:41:06 -0500558 std::string msg = "inotify_init1 failed with errno " +
559 std::to_string(e);
Matt Spinlerff9cec22020-07-15 13:06:35 -0500560 log<level::ERR>(msg.c_str());
561 abort();
562 }
563
564 _pelFileDeleteWatchFD = inotify_add_watch(
565 _pelFileDeleteFD, _repo.repoPath().c_str(), IN_DELETE);
566 if (-1 == _pelFileDeleteWatchFD)
567 {
568 auto e = errno;
Patrick Williams2544b412022-10-04 08:41:06 -0500569 std::string msg = "inotify_add_watch failed with error " +
570 std::to_string(e);
Matt Spinlerff9cec22020-07-15 13:06:35 -0500571 log<level::ERR>(msg.c_str());
572 abort();
573 }
574
575 _pelFileDeleteEventSource = std::make_unique<sdeventplus::source::IO>(
576 _event, _pelFileDeleteFD, EPOLLIN,
577 std::bind(std::mem_fn(&Manager::pelFileDeleted), this,
578 std::placeholders::_1, std::placeholders::_2,
579 std::placeholders::_3));
580}
581
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500582void Manager::pelFileDeleted(sdeventplus::source::IO& /*io*/, int /*fd*/,
Matt Spinlerff9cec22020-07-15 13:06:35 -0500583 uint32_t revents)
584{
585 if (!(revents & EPOLLIN))
586 {
587 return;
588 }
589
590 // An event for 1 PEL uses 48B. When all PELs are deleted at once,
591 // as many events as there is room for can be handled in one callback.
592 // A size of 2000 will allow 41 to be processed, with additional
593 // callbacks being needed to process the remaining ones.
Matt Spinler9d59d582021-05-19 07:57:10 -0600594 std::array<uint8_t, 2000> data{};
Matt Spinlerff9cec22020-07-15 13:06:35 -0500595 auto bytesRead = read(_pelFileDeleteFD, data.data(), data.size());
596 if (bytesRead < 0)
597 {
598 auto e = errno;
599 std::string msg = "Failed reading data from inotify event, errno = " +
600 std::to_string(e);
601 log<level::ERR>(msg.c_str());
602 abort();
603 }
604
605 auto offset = 0;
606 while (offset < bytesRead)
607 {
608 auto event = reinterpret_cast<inotify_event*>(&data[offset]);
609 if (event->mask & IN_DELETE)
610 {
611 std::string filename{event->name};
612
613 // Get the PEL ID from the filename and tell the
614 // repo it's been removed, and then delete the BMC
615 // event log if it's there.
616 auto pos = filename.find_first_of('_');
617 if (pos != std::string::npos)
618 {
619 try
620 {
621 auto idString = filename.substr(pos + 1);
622 auto pelID = std::stoul(idString, nullptr, 16);
623
624 Repository::LogID id{Repository::LogID::Pel(pelID)};
625 auto removedLogID = _repo.remove(id);
626 if (removedLogID)
627 {
628 _logManager.erase(removedLogID->obmcID.id);
629 }
630 }
631 catch (const std::exception& e)
632 {
633 log<level::INFO>("Could not find PEL ID from its filename",
634 entry("FILENAME=%s", filename.c_str()));
635 }
636 }
637 }
638
639 offset += offsetof(inotify_event, name) + event->len;
640 }
641}
Matt Spinler9cc30072020-09-16 15:39:34 -0500642
643std::tuple<uint32_t, uint32_t> Manager::createPELWithFFDCFiles(
644 std::string message, Entry::Level severity,
645 std::map<std::string, std::string> additionalData,
646 std::vector<std::tuple<
647 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
648 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
649 fFDC)
650{
Matt Spinler44893cc2020-08-26 11:34:17 -0500651 _logManager.createWithFFDC(message, severity, additionalData, fFDC);
652
653 return {_logManager.lastEntryID(), _repo.lastPelID()};
Matt Spinler9cc30072020-09-16 15:39:34 -0500654}
655
Matt Spinler8bd4ca42022-04-01 16:06:06 -0500656std::string Manager::getPELJSON(uint32_t obmcLogID)
Matt Spinleraa85a072022-03-23 11:26:41 -0500657{
Matt Spinler8bd4ca42022-04-01 16:06:06 -0500658 // Throws InvalidArgument if not found
659 auto pelID = getPELIdFromBMCLogId(obmcLogID);
660
661 auto cmd = fmt::format("/usr/bin/peltool -i {:#x}", pelID);
662
663 FILE* pipe = popen(cmd.c_str(), "r");
664 if (!pipe)
665 {
666 log<level::ERR>(fmt::format("Error running {}", cmd).c_str());
667 throw common_error::InternalFailure();
668 }
669
670 std::string output;
671 std::array<char, 1024> buffer;
672 while (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
673 {
674 output.append(buffer.data());
675 }
676
677 int rc = pclose(pipe);
678 if (WEXITSTATUS(rc) != 0)
679 {
680 log<level::ERR>(
681 fmt::format("Error running {}, rc = {}", cmd, rc).c_str());
682 throw common_error::InternalFailure();
683 }
684
685 return output;
Matt Spinleraa85a072022-03-23 11:26:41 -0500686}
687
Andrew Geissler44fc3162020-07-09 09:21:31 -0500688void Manager::checkPelAndQuiesce(std::unique_ptr<openpower::pels::PEL>& pel)
689{
Matt Spinlerb2abc042021-05-17 15:32:50 -0600690 if ((pel->userHeader().severity() ==
691 static_cast<uint8_t>(SeverityType::nonError)) ||
692 (pel->userHeader().severity() ==
693 static_cast<uint8_t>(SeverityType::recovered)))
Andrew Geissler44fc3162020-07-09 09:21:31 -0500694 {
Matt Spinlerb2abc042021-05-17 15:32:50 -0600695 log<level::DEBUG>(
696 "PEL severity informational or recovered. no quiesce needed");
Andrew Geissler44fc3162020-07-09 09:21:31 -0500697 return;
698 }
699 if (!_logManager.isQuiesceOnErrorEnabled())
700 {
701 log<level::DEBUG>("QuiesceOnHwError not enabled, no quiesce needed");
702 return;
703 }
704
Matt Spinler845c6242022-03-01 16:45:08 -0600705 CreatorID creatorID{pel->privateHeader().creatorID()};
706
707 if ((creatorID != CreatorID::openBMC) &&
708 (creatorID != CreatorID::hostboot) &&
709 (creatorID != CreatorID::ioDrawer) && (creatorID != CreatorID::occ) &&
710 (creatorID != CreatorID::phyp))
711 {
712 return;
713 }
714
Andrew Geissler44fc3162020-07-09 09:21:31 -0500715 // Now check if it has any type of callout
Andrew Geisslerf8e750d2022-01-14 14:56:13 -0600716 if (pel->isHwCalloutPresent())
Andrew Geissler44fc3162020-07-09 09:21:31 -0500717 {
Matt Spinlerb2abc042021-05-17 15:32:50 -0600718 log<level::INFO>(
719 "QuiesceOnHwError enabled, PEL severity not nonError or recovered, "
720 "and callout is present");
Andrew Geissler44fc3162020-07-09 09:21:31 -0500721
722 _logManager.quiesceOnError(pel->obmcLogID());
723 }
724}
725
Vijay Lobod354a392021-06-01 16:21:02 -0500726std::string Manager::getEventId(const openpower::pels::PEL& pel) const
727{
728 std::string str;
729 auto src = pel.primarySRC();
730 if (src)
731 {
732 const auto& hexwords = (*src)->hexwordData();
733
734 std::string refcode = (*src)->asciiString();
735 size_t pos = refcode.find_last_not_of(0x20);
736 if (pos != std::string::npos)
737 {
738 refcode.erase(pos + 1);
739 }
740 str = refcode;
741
742 for (auto& value : hexwords)
743 {
744 str += " ";
745 str += getNumberString("%08X", value);
746 }
747 }
Matt Spinler0003af12022-06-08 10:46:17 -0500748 return sanitizeFieldForDBus(str);
Vijay Lobod354a392021-06-01 16:21:02 -0500749}
750
751void Manager::updateEventId(std::unique_ptr<openpower::pels::PEL>& pel)
752{
753 std::string eventIdStr = getEventId(*pel);
754
755 auto entryN = _logManager.entries.find(pel->obmcLogID());
756 if (entryN != _logManager.entries.end())
757 {
Matt Spinlerb25e8a32023-06-07 16:05:36 -0500758 entryN->second->eventId(eventIdStr, true);
Vijay Lobod354a392021-06-01 16:21:02 -0500759 }
760}
761
Matt Spinler0003af12022-06-08 10:46:17 -0500762std::string Manager::sanitizeFieldForDBus(std::string field)
763{
764 std::for_each(field.begin(), field.end(), [](char& ch) {
765 if (((ch < ' ') || (ch > '~')) && (ch != '\n') && (ch != '\t'))
766 {
767 ch = ' ';
768 }
769 });
770 return field;
771}
772
Vijay Lobo593a4c62021-06-16 14:25:26 -0500773std::string Manager::getResolution(const openpower::pels::PEL& pel) const
774{
775 std::string str;
776 std::string resolution;
777 auto src = pel.primarySRC();
778 if (src)
779 {
780 // First extract the callout pointer and then go through
781 const auto& callouts = (*src)->callouts();
782 namespace pv = openpower::pels::pel_values;
783 // All PELs dont have callout, check before parsing callout data
784 if (callouts)
785 {
786 const auto& entries = callouts->callouts();
787 // Entry starts with index 1
788 uint8_t index = 1;
789 for (auto& entry : entries)
790 {
791 resolution += std::to_string(index) + ". ";
792 // Adding Location code to resolution
793 if (!entry->locationCode().empty())
Patrick Williams2544b412022-10-04 08:41:06 -0500794 resolution += "Location Code: " + entry->locationCode() +
795 ", ";
Vijay Lobo593a4c62021-06-16 14:25:26 -0500796 if (entry->fruIdentity())
797 {
798 // Get priority and set the resolution string
799 str = pv::getValue(entry->priority(),
800 pel_values::calloutPriorityValues,
801 pel_values::registryNamePos);
802 str[0] = toupper(str[0]);
803 resolution += "Priority: " + str + ", ";
804 if (entry->fruIdentity()->getPN().has_value())
805 {
806 resolution +=
807 "PN: " + entry->fruIdentity()->getPN().value() +
808 ", ";
809 }
810 if (entry->fruIdentity()->getSN().has_value())
811 {
812 resolution +=
813 "SN: " + entry->fruIdentity()->getSN().value() +
814 ", ";
815 }
816 if (entry->fruIdentity()->getCCIN().has_value())
817 {
818 resolution +=
819 "CCIN: " + entry->fruIdentity()->getCCIN().value() +
820 ", ";
821 }
822 // Add the maintenance procedure
823 if (entry->fruIdentity()->getMaintProc().has_value())
824 {
825 resolution +=
826 "Procedure: " +
827 entry->fruIdentity()->getMaintProc().value() + ", ";
828 }
829 }
830 resolution.resize(resolution.size() - 2);
831 resolution += "\n";
832 index++;
833 }
834 }
835 }
Matt Spinler0003af12022-06-08 10:46:17 -0500836 return sanitizeFieldForDBus(resolution);
Vijay Lobo593a4c62021-06-16 14:25:26 -0500837}
838
Matt Spinler28d6ae22022-03-18 11:18:27 -0500839bool Manager::updateResolution(const openpower::pels::PEL& pel)
Vijay Lobo593a4c62021-06-16 14:25:26 -0500840{
Matt Spinler28d6ae22022-03-18 11:18:27 -0500841 std::string callouts = getResolution(pel);
842 auto entryN = _logManager.entries.find(pel.obmcLogID());
Vijay Lobo593a4c62021-06-16 14:25:26 -0500843 if (entryN != _logManager.entries.end())
844 {
Matt Spinler734ed2b2022-01-21 09:31:46 -0600845 entryN->second->resolution(callouts, true);
Vijay Lobo593a4c62021-06-16 14:25:26 -0500846 }
Matt Spinler28d6ae22022-03-18 11:18:27 -0500847
848 return false;
Vijay Lobo593a4c62021-06-16 14:25:26 -0500849}
850
Matt Spinler3387eac2023-07-06 14:56:02 -0500851void Manager::serializeLogEntry(uint32_t obmcLogID)
852{
853 auto entryN = _logManager.entries.find(obmcLogID);
854 if (entryN != _logManager.entries.end())
855 {
856 serialize(*entryN->second);
857 }
858}
859
Matt Spinler8b81ec02022-07-12 13:25:37 -0500860void Manager::updateDBusSeverity(const openpower::pels::PEL& pel)
861{
862 // The final severity of the PEL may not agree with the
863 // original severity of the D-Bus event log. Update the
864 // D-Bus property to match in some cases. This is to
865 // ensure there isn't a Critical or Warning Redfish event
866 // log for an informational or recovered PEL (or vice versa).
867 // This doesn't make an explicit call to serialize the new
868 // event log property value because updateEventId() is called
869 // right after this and will do it.
870 auto sevType =
871 static_cast<SeverityType>(pel.userHeader().severity() & 0xF0);
872
873 auto entryN = _logManager.entries.find(pel.obmcLogID());
874 if (entryN != _logManager.entries.end())
875 {
Patrick Williams2544b412022-10-04 08:41:06 -0500876 auto newSeverity = fixupLogSeverity(entryN->second->severity(),
877 sevType);
Matt Spinler8b81ec02022-07-12 13:25:37 -0500878 if (newSeverity)
879 {
880 log<level::INFO>(
881 fmt::format(
882 "Changing event log {} severity from {} "
883 "to {} to match PEL",
884 entryN->second->id(),
885 Entry::convertLevelToString(entryN->second->severity()),
886 Entry::convertLevelToString(*newSeverity))
887 .c_str());
888
889 entryN->second->severity(*newSeverity, true);
890 }
891 }
892}
893
Adriana Kobylake7d271a2020-12-07 14:32:44 -0600894void Manager::setEntryPath(uint32_t obmcLogID)
895{
896 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
897 if (auto attributes = _repo.getPELAttributes(id); attributes)
898 {
899 auto& attr = attributes.value().get();
900 auto entry = _logManager.entries.find(obmcLogID);
901 if (entry != _logManager.entries.end())
902 {
Matt Spinler734ed2b2022-01-21 09:31:46 -0600903 entry->second->path(attr.path, true);
Adriana Kobylake7d271a2020-12-07 14:32:44 -0600904 }
905 }
906}
907
Vijay Lobocbc93a42021-05-20 19:04:07 -0500908void Manager::setServiceProviderNotifyFlag(uint32_t obmcLogID)
909{
910 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
911 if (auto attributes = _repo.getPELAttributes(id); attributes)
912 {
913 auto& attr = attributes.value().get();
914 auto entry = _logManager.entries.find(obmcLogID);
915 if (entry != _logManager.entries.end())
916 {
Lakshmi Yadlapati7a3ede52022-11-18 13:26:17 -0600917 if (attr.actionFlags.test(callHomeFlagBit))
918 {
Matt Spinlerb25e8a32023-06-07 16:05:36 -0500919 entry->second->serviceProviderNotify(Entry::Notify::Notify,
920 true);
Lakshmi Yadlapati7a3ede52022-11-18 13:26:17 -0600921 }
922 else
923 {
Matt Spinlerb25e8a32023-06-07 16:05:36 -0500924 entry->second->serviceProviderNotify(Entry::Notify::Inhibit,
925 true);
Lakshmi Yadlapati7a3ede52022-11-18 13:26:17 -0600926 }
Vijay Lobocbc93a42021-05-20 19:04:07 -0500927 }
928 }
929}
930
Matt Spinler734ed2b2022-01-21 09:31:46 -0600931void Manager::createPELEntry(uint32_t obmcLogID, bool skipIaSignal)
Vijay Loboafb1b462021-07-21 23:29:13 -0500932{
933 std::map<std::string, PropertiesVariant> varData;
934 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
935 if (auto attributes = _repo.getPELAttributes(id); attributes)
936 {
937 namespace pv = openpower::pels::pel_values;
938 auto& attr = attributes.value().get();
Vijay Lobob2e541e2021-08-31 23:12:47 -0500939
940 // get the hidden flag values
941 auto sevType = static_cast<SeverityType>(attr.severity & 0xF0);
942 auto isHidden = true;
943 if (((sevType != SeverityType::nonError) &&
944 attr.actionFlags.test(reportFlagBit) &&
945 !attr.actionFlags.test(hiddenFlagBit)) ||
946 ((sevType == SeverityType::nonError) &&
947 attr.actionFlags.test(serviceActionFlagBit)))
948 {
949 isHidden = false;
950 }
951 varData.emplace(std::string("Hidden"), isHidden);
Vijay Loboafb1b462021-07-21 23:29:13 -0500952 varData.emplace(
953 std::string("Subsystem"),
954 pv::getValue(attr.subsystem, pel_values::subsystemValues));
Vijay Lobo2fb10212021-08-22 23:24:16 -0500955
956 varData.emplace(
957 std::string("ManagementSystemAck"),
958 (attr.hmcState == TransmissionState::acked ? true : false));
959
Matt Spinler8e65f4e2023-05-02 13:40:08 -0500960 varData.emplace("PlatformLogID", attr.plid);
961 varData.emplace("Deconfig", attr.deconfig);
962 varData.emplace("Guard", attr.guard);
963 varData.emplace("Timestamp", attr.creationTime);
964
Vijay Loboafb1b462021-07-21 23:29:13 -0500965 // Path to create PELEntry Interface is same as PEL
966 auto path = std::string(OBJ_ENTRY) + '/' + std::to_string(obmcLogID);
967 // Create Interface for PELEntry and set properties
Vijay Lobo2fb10212021-08-22 23:24:16 -0500968 auto pelEntry = std::make_unique<PELEntry>(_logManager.getBus(), path,
969 varData, obmcLogID, &_repo);
Matt Spinler734ed2b2022-01-21 09:31:46 -0600970 if (!skipIaSignal)
971 {
972 pelEntry->emit_added();
973 }
Vijay Loboafb1b462021-07-21 23:29:13 -0500974 _pelEntries.emplace(std::move(path), std::move(pelEntry));
975 }
976}
977
Ramesh Iyyarf4203c42021-06-24 06:09:23 -0500978uint32_t Manager::getPELIdFromBMCLogId(uint32_t bmcLogId)
979{
980 Repository::LogID id{Repository::LogID::Obmc(bmcLogId)};
981 if (auto logId = _repo.getLogID(id); !logId.has_value())
982 {
983 throw common_error::InvalidArgument();
984 }
985 else
986 {
987 return logId->pelID.id;
988 }
989}
990
Ramesh Iyyar530efbf2021-06-24 06:22:22 -0500991uint32_t Manager::getBMCLogIdFromPELId(uint32_t pelId)
992{
993 Repository::LogID id{Repository::LogID::Pel(pelId)};
994 if (auto logId = _repo.getLogID(id); !logId.has_value())
995 {
996 throw common_error::InvalidArgument();
997 }
998 else
999 {
1000 return logId->obmcID.id;
1001 }
1002}
1003
Sumit Kumar3e274432021-09-14 06:37:56 -05001004void Manager::updateProgressSRC(
1005 std::unique_ptr<openpower::pels::PEL>& pel) const
1006{
1007 // Check for pel severity of type - 0x51 = critical error, system
1008 // termination
1009 if (pel->userHeader().severity() == 0x51)
1010 {
1011 auto src = pel->primarySRC();
1012 if (src)
1013 {
1014 std::vector<uint8_t> asciiSRC = (*src)->getSrcStruct();
1015 uint64_t srcRefCode = 0;
1016
1017 // Read bytes from offset [40-47] e.g. BD8D1001
1018 for (int i = 0; i < 8; i++)
1019 {
Patrick Williams2544b412022-10-04 08:41:06 -05001020 srcRefCode |= (static_cast<uint64_t>(asciiSRC[40 + i])
1021 << (8 * i));
Sumit Kumar3e274432021-09-14 06:37:56 -05001022 }
1023
1024 try
1025 {
1026 _dataIface->createProgressSRC(srcRefCode, asciiSRC);
1027 }
Matt Spinler87f39242023-05-01 11:36:18 -05001028 catch (const std::exception&)
Sumit Kumar3e274432021-09-14 06:37:56 -05001029 {
1030 // Exception - may be no boot progress interface on dbus
1031 }
1032 }
1033 }
1034}
1035
Matt Spinlerd8fb5ba2022-01-25 13:01:14 -06001036void Manager::scheduleObmcLogDelete(uint32_t obmcLogID)
1037{
1038 _obmcLogDeleteEventSource = std::make_unique<sdeventplus::source::Defer>(
1039 _event, std::bind(std::mem_fn(&Manager::deleteObmcLog), this,
1040 std::placeholders::_1, obmcLogID));
1041}
1042
1043void Manager::deleteObmcLog(sdeventplus::source::EventBase&, uint32_t obmcLogID)
1044{
1045 log<level::INFO>(
1046 fmt::format("Removing event log with no PEL: {}", obmcLogID).c_str());
1047 _logManager.erase(obmcLogID);
1048 _obmcLogDeleteEventSource.reset();
1049}
1050
Matt Spinler0dd22c82023-05-04 15:28:12 -05001051bool Manager::clearPowerThermalDeconfigFlag(const std::string& locationCode,
1052 openpower::pels::PEL& pel)
1053{
1054 // The requirements state that only power-thermal or
1055 // fan PELs need their deconfig flag cleared.
1056 static const std::vector<uint32_t> compIDs{bmcThermalCompID, bmcFansCompID};
1057
1058 if (std::find(compIDs.begin(), compIDs.end(),
1059 pel.privateHeader().header().componentID) == compIDs.end())
1060 {
1061 return false;
1062 }
1063
1064 auto src = pel.primarySRC();
1065 const auto& callouts = (*src)->callouts();
1066 if (!callouts)
1067 {
1068 return false;
1069 }
1070
1071 for (const auto& callout : callouts->callouts())
1072 {
1073 // Look for the passed in location code in a callout that
1074 // is either a normal HW callout or a symbolic FRU with
1075 // a trusted location code callout.
1076 if ((callout->locationCode() != locationCode) ||
1077 !callout->fruIdentity())
1078 {
1079 continue;
1080 }
1081
1082 if ((callout->fruIdentity()->failingComponentType() !=
1083 src::FRUIdentity::hardwareFRU) &&
1084 (callout->fruIdentity()->failingComponentType() !=
1085 src::FRUIdentity::symbolicFRUTrustedLocCode))
1086 {
1087 continue;
1088 }
1089
1090 log<level::INFO>(
1091 fmt::format(
1092 "Clearing deconfig flag in PEL {:#x} with SRC {} because {} was replaced",
1093 pel.id(), (*src)->asciiString().substr(0, 8), locationCode)
1094 .c_str());
1095 (*src)->clearErrorStatusFlag(SRC::ErrorStatusFlags::deconfigured);
1096 return true;
1097 }
1098 return false;
1099}
1100
1101void Manager::hardwarePresent(const std::string& locationCode)
1102{
1103 Repository::PELUpdateFunc handlePowerThermalHardwarePresent =
1104 [locationCode](openpower::pels::PEL& pel) {
1105 return Manager::clearPowerThermalDeconfigFlag(locationCode, pel);
1106 };
1107
1108 // If the PEL was created by the BMC and has the deconfig flag set,
1109 // it's a candidate to have the deconfig flag cleared.
1110 for (const auto& [id, attributes] : _repo.getAttributesMap())
1111 {
1112 if ((attributes.creator == static_cast<uint8_t>(CreatorID::openBMC)) &&
1113 attributes.deconfig)
1114 {
1115 _repo.updatePEL(attributes.path, handlePowerThermalHardwarePresent);
1116 }
1117 }
1118}
1119
Matt Spinler4e8078c2019-07-09 13:22:32 -05001120} // namespace pels
1121} // namespace openpower