blob: a9476d566cf435842b6b24395c5551eb36f3102d [file] [log] [blame]
Matt Spinler4e8078c2019-07-09 13:22:32 -05001#pragma once
2
Matt Spinlera34ab722019-12-16 10:39:32 -06003#include "config.h"
4
Matt Spinlerc8705e22019-09-11 12:36:07 -05005#include "data_interface.hpp"
Matt Spinlerf682b402019-12-18 13:48:08 -06006#include "event_logger.hpp"
Matt Spinlerf60ac272019-12-11 13:47:50 -06007#include "host_notifier.hpp"
Matt Spinler4e8078c2019-07-09 13:22:32 -05008#include "log_manager.hpp"
Matt Spinler89fa0822019-07-17 13:54:30 -05009#include "paths.hpp"
Matt Spinler56ad2a02020-03-26 14:00:52 -050010#include "pel.hpp"
Matt Spinler367144c2019-09-19 15:33:52 -050011#include "registry.hpp"
Matt Spinler89fa0822019-07-17 13:54:30 -050012#include "repository.hpp"
Matt Spinler4e8078c2019-07-09 13:22:32 -050013
Vijay Loboafb1b462021-07-21 23:29:13 -050014#include <org/open_power/Logging/PEL/Entry/server.hpp>
Matt Spinlera34ab722019-12-16 10:39:32 -060015#include <org/open_power/Logging/PEL/server.hpp>
16#include <sdbusplus/server.hpp>
Matt Spinler6b1a5c82020-01-07 08:48:53 -060017#include <sdeventplus/event.hpp>
18#include <sdeventplus/source/event.hpp>
Matt Spinler44893cc2020-08-26 11:34:17 -050019#include <xyz/openbmc_project/Logging/Create/server.hpp>
Matt Spinlera34ab722019-12-16 10:39:32 -060020
Matt Spinler4e8078c2019-07-09 13:22:32 -050021namespace openpower
22{
23namespace pels
24{
25
Matt Spinlera34ab722019-12-16 10:39:32 -060026using PELInterface = sdbusplus::server::object::object<
27 sdbusplus::org::open_power::Logging::server::PEL>;
28
Matt Spinler4e8078c2019-07-09 13:22:32 -050029/**
30 * @brief PEL manager object
31 */
Matt Spinlera34ab722019-12-16 10:39:32 -060032class Manager : public PELInterface
Matt Spinler4e8078c2019-07-09 13:22:32 -050033{
34 public:
35 Manager() = delete;
Matt Spinler4e8078c2019-07-09 13:22:32 -050036 Manager(const Manager&) = default;
37 Manager& operator=(const Manager&) = default;
38 Manager(Manager&&) = default;
39 Manager& operator=(Manager&&) = default;
40
41 /**
42 * @brief constructor
43 *
44 * @param[in] logManager - internal::Manager object
Matt Spinlerf60ac272019-12-11 13:47:50 -060045 * @param[in] dataIface - The data interface object
Matt Spinlerf682b402019-12-18 13:48:08 -060046 * @param[in] creatorFunc - The function that EventLogger will
47 * use for creating event logs
Matt Spinler4e8078c2019-07-09 13:22:32 -050048 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060049 Manager(phosphor::logging::internal::Manager& logManager,
Matt Spinlerf682b402019-12-18 13:48:08 -060050 std::unique_ptr<DataInterfaceBase> dataIface,
51 EventLogger::LogFunction creatorFunc) :
Matt Spinlera34ab722019-12-16 10:39:32 -060052 PELInterface(logManager.getBus(), OBJ_LOGGING),
Matt Spinler104e9362020-04-02 09:34:41 -050053 _logManager(logManager), _eventLogger(std::move(creatorFunc)),
Matt Spinlerf682b402019-12-18 13:48:08 -060054 _repo(getPELRepoPath()),
Matt Spinler0d804ef2020-05-12 16:16:26 -050055 _registry(getPELReadOnlyDataPath() / message::registryFileName),
Matt Spinlerff9cec22020-07-15 13:06:35 -050056 _event(sdeventplus::Event::get_default()),
Matt Spinler367144c2019-09-19 15:33:52 -050057 _dataIface(std::move(dataIface))
Matt Spinler4e8078c2019-07-09 13:22:32 -050058 {
Adriana Kobylake7d271a2020-12-07 14:32:44 -060059 for (const auto& entry : _logManager.entries)
60 {
61 setEntryPath(entry.first);
Vijay Lobocbc93a42021-05-20 19:04:07 -050062 setServiceProviderNotifyFlag(entry.first);
Vijay Loboafb1b462021-07-21 23:29:13 -050063 // Create PELEntry interface and setup properties with their values
64 createPELEntry(entry.first);
Adriana Kobylake7d271a2020-12-07 14:32:44 -060065 }
Matt Spinlerff9cec22020-07-15 13:06:35 -050066 setupPELDeleteWatch();
Matt Spinler4e8078c2019-07-09 13:22:32 -050067 }
68
69 /**
Matt Spinlerf60ac272019-12-11 13:47:50 -060070 * @brief constructor that enables host notification
71 *
72 * @param[in] logManager - internal::Manager object
73 * @param[in] dataIface - The data interface object
Matt Spinlerf682b402019-12-18 13:48:08 -060074 * @param[in] creatorFunc - The function that EventLogger will
75 * use for creating event logs
Matt Spinlerf60ac272019-12-11 13:47:50 -060076 * @param[in] hostIface - The hostInterface object
77 */
78 Manager(phosphor::logging::internal::Manager& logManager,
79 std::unique_ptr<DataInterfaceBase> dataIface,
Matt Spinlerf682b402019-12-18 13:48:08 -060080 EventLogger::LogFunction creatorFunc,
Matt Spinlerf60ac272019-12-11 13:47:50 -060081 std::unique_ptr<HostInterface> hostIface) :
Matt Spinlerf682b402019-12-18 13:48:08 -060082 Manager(logManager, std::move(dataIface), std::move(creatorFunc))
Matt Spinlerf60ac272019-12-11 13:47:50 -060083 {
84 _hostNotifier = std::make_unique<HostNotifier>(
85 _repo, *(_dataIface.get()), std::move(hostIface));
86 }
87
88 /**
Matt Spinlerff9cec22020-07-15 13:06:35 -050089 * @brief Destructor
90 */
91 ~Manager();
92
93 /**
Matt Spinler4e8078c2019-07-09 13:22:32 -050094 * @brief Creates a PEL based on the OpenBMC event log contents. If
95 * a PEL was passed in via the RAWPEL specifier in the
96 * additionalData parameter, use that instead.
97 *
98 * @param[in] message - the event log message property
99 * @param[in] obmcLogID - the corresponding OpenBMC event log id
100 * @param[in] timestamp - the Timestamp property
101 * @param[in] severity - the event log severity
102 * @param[in] additionalData - the AdditionalData property
103 * @param[in] associations - the Associations property
Matt Spinler56ad2a02020-03-26 14:00:52 -0500104 * @param[in] ffdc - A vector of FFDC file information
Matt Spinler4e8078c2019-07-09 13:22:32 -0500105 */
106 void create(const std::string& message, uint32_t obmcLogID,
Matt Spinler367144c2019-09-19 15:33:52 -0500107 uint64_t timestamp, phosphor::logging::Entry::Level severity,
Matt Spinler4e8078c2019-07-09 13:22:32 -0500108 const std::vector<std::string>& additionalData,
Matt Spinler56ad2a02020-03-26 14:00:52 -0500109 const std::vector<std::string>& associations,
110 const phosphor::logging::FFDCEntries& ffdc =
111 phosphor::logging::FFDCEntries{});
Matt Spinler4e8078c2019-07-09 13:22:32 -0500112
113 /**
114 * @brief Erase a PEL based on its OpenBMC event log ID
115 *
116 * @param[in] obmcLogID - the corresponding OpenBMC event log id
117 */
118 void erase(uint32_t obmcLogID);
119
120 /** @brief Says if an OpenBMC event log may not be manually deleted at this
121 * time because its corresponding PEL cannot be.
122 *
123 * There are PEL retention policies that can prohibit the manual deletion
124 * of PELs (and therefore OpenBMC event logs).
125 *
126 * @param[in] obmcLogID - the OpenBMC event log ID
127 * @return bool - true if prohibited
128 */
129 bool isDeleteProhibited(uint32_t obmcLogID);
130
Matt Spinlera34ab722019-12-16 10:39:32 -0600131 /**
132 * @brief Return a file descriptor to the raw PEL data
133 *
134 * Throws InvalidArgument if the PEL ID isn't found,
135 * and InternalFailure if anything else fails.
136 *
137 * @param[in] pelID - The PEL ID to get the data for
138 *
139 * @return unix_fd - File descriptor to the file that contains the PEL
140 */
141 sdbusplus::message::unix_fd getPEL(uint32_t pelID) override;
142
143 /**
144 * @brief Returns data for the PEL corresponding to an OpenBMC
145 * event log.
146 *
147 * @param[in] obmcLogID - The OpenBMC event log ID
148 *
149 * @return vector<uint8_t> - The raw PEL data
150 */
151 std::vector<uint8_t> getPELFromOBMCID(uint32_t obmcLogID) override;
152
153 /**
154 * @brief The D-Bus method called when a host successfully processes
155 * a PEL.
156 *
157 * This D-Bus method is called from the PLDM daemon when they get an
158 * 'Ack PEL' PLDM message from the host, which indicates the host
159 * firmware successfully sent it to the OS and this code doesn't need
160 * to send it to the host again.
161 *
162 * @param[in] pelID - The PEL ID
163 */
164 void hostAck(uint32_t pelID) override;
165
166 /**
167 * @brief D-Bus method called when the host rejects a PEL.
168 *
169 * This D-Bus method is called from the PLDM daemon when they get an
170 * 'Ack PEL' PLDM message from the host with a payload that says
171 * something when wrong.
172 *
173 * The choices are either:
174 * * Host Full - The host's staging area is full - try again later
175 * * Malrformed PEL - The host received an invalid PEL
176 *
177 * @param[in] pelID - The PEL ID
178 * @param[in] reason - One of the above two reasons
179 */
180 void hostReject(uint32_t pelID, RejectionReason reason) override;
181
Matt Spinler44893cc2020-08-26 11:34:17 -0500182 /**
183 * @brief D-Bus method to create a PEL/OpenBMC event log and
184 * return the created OpenBMC and PEL log IDs.
185 *
186 * The same as the CreateWithFFDCFiles method on the
187 * xyz.openbmc_project.Logging.Create interface, except for
188 * the return values.
189 *
190 * @param[in] message - The event log message property
191 * @param[in] severity - The event log severity
192 * @param[in] additionalData - The AdditionalData property
193 * @param[in] ffdc - A vector of FFDC file information
194 */
Matt Spinler9cc30072020-09-16 15:39:34 -0500195 std::tuple<uint32_t, uint32_t> createPELWithFFDCFiles(
196 std::string message, phosphor::logging::Entry::Level severity,
197 std::map<std::string, std::string> additionalData,
198 std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging::
199 server::Create::FFDCFormat,
200 uint8_t, uint8_t, sdbusplus::message::unix_fd>>
Matt Spinler44893cc2020-08-26 11:34:17 -0500201 fFDC) override;
Matt Spinler9cc30072020-09-16 15:39:34 -0500202
Matt Spinler19e72902020-01-24 11:05:20 -0600203 /**
204 * @brief Converts the ESEL field in an OpenBMC event log to a
205 * vector of uint8_ts that just contains the PEL data.
206 *
207 * That data string looks like: "50 48 00 ab ..."
208 *
209 * Throws an exception on any failures.
210 *
211 * @param[in] esel - The ESEL string
212 *
213 * @return std::vector<uint8_t> - The contained PEL data
214 */
215 static std::vector<uint8_t> eselToRawData(const std::string& esel);
216
Vijay Lobod354a392021-06-01 16:21:02 -0500217 /**
Vijay Lobo593a4c62021-06-16 14:25:26 -0500218 * @brief Generate resolution string from the PEL
219 *
220 * @param[in] pel - The PEL to use
221 */
222 std::string getResolution(const openpower::pels::PEL& pel) const;
223
224 /**
Vijay Lobod354a392021-06-01 16:21:02 -0500225 * @brief Generate event ID from the PEL
226 *
227 * @param[in] pel - The PEL to use
228 */
229 std::string getEventId(const openpower::pels::PEL& pel) const;
230
Ramesh Iyyarf4203c42021-06-24 06:09:23 -0500231 /** @brief Implementation for GetPELIdFromBMCLogId
232 *
233 * Returns the PEL Id (aka Entry ID (EID)) based on the given
234 * BMC event log id.
235 *
236 * @param[in] bmcLogId - The BMC event log id of the PEL to retrieve
237 * the PEL id.
238 *
239 * @return uint32_t - The Id of the PEL.
240 * Throw "InvalidArgument" if not found.
241 */
242 uint32_t getPELIdFromBMCLogId(uint32_t bmcLogId) override;
243
Ramesh Iyyar530efbf2021-06-24 06:22:22 -0500244 /** @brief Implementation for GetBMCLogIdFromPELId
245 *
246 * Returns the BMC event log id based on the given PEL id
247 * (aka Entry ID (EID)).
248 *
249 * @param[in] pelId - The PEL id to retrieve the BMC event log id.
250 *
251 * @return uint32_t - The BMC event log id of the PEL.
252 * Throw "InvalidArgument" if not found.
253 */
254 uint32_t getBMCLogIdFromPELId(uint32_t pelId) override;
255
Matt Spinler4e8078c2019-07-09 13:22:32 -0500256 private:
257 /**
258 * @brief Adds a received raw PEL to the PEL repository
259 *
260 * @param[in] rawPelPath - The path to the file that contains the
261 * raw PEL.
262 * @param[in] obmcLogID - the corresponding OpenBMC event log id
263 */
264 void addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID);
265
266 /**
267 * @brief Creates a PEL based on the OpenBMC event log contents.
268 *
269 * @param[in] message - The event log message property
270 * @param[in] obmcLogID - the corresponding OpenBMC event log id
271 * @param[in] timestamp - The timestamp property
272 * @param[in] severity - The event log severity
273 * @param[in] additionalData - The AdditionalData property
274 * @param[in] associations - The associations property
Matt Spinler56ad2a02020-03-26 14:00:52 -0500275 * @param[in] ffdc - A vector of FFDC file information
Matt Spinler4e8078c2019-07-09 13:22:32 -0500276 */
277 void createPEL(const std::string& message, uint32_t obmcLogID,
Matt Spinler367144c2019-09-19 15:33:52 -0500278 uint64_t timestamp, phosphor::logging::Entry::Level severity,
Matt Spinler4e8078c2019-07-09 13:22:32 -0500279 const std::vector<std::string>& additionalData,
Matt Spinler56ad2a02020-03-26 14:00:52 -0500280 const std::vector<std::string>& associations,
281 const phosphor::logging::FFDCEntries& ffdc);
Matt Spinler4e8078c2019-07-09 13:22:32 -0500282
283 /**
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600284 * @brief Schedules a close of the file descriptor to occur from
285 * the event loop.
286 *
287 * Uses sd_event_add_defer
288 *
289 * @param[in] fd - The file descriptor to close
290 */
291 void scheduleFDClose(int fd);
292
293 /**
294 * @brief Closes the file descriptor passed in.
295 *
296 * This is called from the event loop to close FDs returned
297 * from getPEL().
298 *
299 * @param[in] fd - The file descriptor to close
300 * @param[in] source - The event source object used
301 */
302 void closeFD(int fd, sdeventplus::source::EventBase& source);
303
304 /**
Matt Spinler19e72902020-01-24 11:05:20 -0600305 * @brief Adds a PEL to the repository given its data
306 *
307 * @param[in] pelData - The PEL to add as a vector of uint8_ts
308 * @param[in] obmcLogID - the OpenBMC event log ID
309 */
310 void addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID);
311
312 /**
313 * @brief Adds the PEL stored in the ESEL field of the AdditionalData
314 * property of an OpenBMC event log to the repository.
315 *
316 * @param[in] esel - The ESEL AdditionalData contents
317 * @param[in] obmcLogID - The OpenBMC event log ID
318 */
319 void addESELPEL(const std::string& esel, uint32_t obmcLogID);
320
321 /**
Matt Spinler56ad2a02020-03-26 14:00:52 -0500322 * @brief Converts the D-Bus FFDC method argument into a data
323 * structure understood by the PEL code.
324 *
325 * @param[in] ffdc - A vector of FFDC file information
326 *
327 * @return PelFFDC - The PEL FFDC data structure
328 */
329 PelFFDC convertToPelFFDC(const phosphor::logging::FFDCEntries& ffdc);
330
331 /**
Matt Spinler7e727a32020-07-07 15:00:17 -0500332 * @brief Schedules a PEL repository prune to occur from
333 * the event loop.
334 *
335 * Uses sd_event_add_defer
336 */
337 void scheduleRepoPrune();
338
339 /**
340 * @brief Prunes old PELs out of the repository to save space.
341 *
342 * This is called from the event loop.
343 *
344 * @param[in] source - The event source object used
345 */
346 void pruneRepo(sdeventplus::source::EventBase& source);
347
348 /**
Matt Spinlerff9cec22020-07-15 13:06:35 -0500349 * @brief Sets up an inotify watch to watch for deleted PEL
350 * files. Calls pelFileDeleted() when that occurs.
351 */
352 void setupPELDeleteWatch();
353
354 /**
355 * @brief Called when the inotify watch put on the repository directory
356 * detects a PEL file was deleted.
357 *
358 * Will tell the Repository class about the deleted PEL, and then tell
359 * the log manager class to delete the corresponding OpenBMC event log.
360 */
361 void pelFileDeleted(sdeventplus::source::IO& io, int fd, uint32_t revents);
362
363 /**
Andrew Geissler44fc3162020-07-09 09:21:31 -0500364 * @brief Check if the input PEL should cause a quiesce of the system
365 *
366 * If QuiesceOnHwError is enabled within phosphor-settings and the PEL
Matt Spinlerb2abc042021-05-17 15:32:50 -0600367 * from the host has a severity which is not SeverityType::nonError or
368 * recovered then execute the quiesce and boot block logic.
Andrew Geissler44fc3162020-07-09 09:21:31 -0500369 *
370 * @param[in] pel - The PEL to check
371 */
372 void checkPelAndQuiesce(std::unique_ptr<openpower::pels::PEL>& pel);
373
374 /**
Vijay Lobod354a392021-06-01 16:21:02 -0500375 * @brief Update eventId D-bus property for this error log
376 *
377 * Update the eventId property of D-bus with SRC and hexwords from the
378 * PEL created
379 *
380 * @param[in] pel - The PEL to use
381 */
382 void updateEventId(std::unique_ptr<openpower::pels::PEL>& pel);
383
384 /**
Adriana Kobylake7d271a2020-12-07 14:32:44 -0600385 * @brief Sets the FilePath of the specified error log entry to the PEL file
386 * path.
387 *
388 * @param[in] obmcLogID - The OpenBMC entry log ID
389 */
390 void setEntryPath(uint32_t obmcLogID);
391
392 /**
Vijay Lobocbc93a42021-05-20 19:04:07 -0500393 * @brief Sets the serviceProviderNotify D-bus property of PEL.
394 *
395 * @param[in] obmcLogID - The OpenBMC entry log ID
396 */
397 void setServiceProviderNotifyFlag(uint32_t obmcLogID);
398
399 /**
Vijay Lobo593a4c62021-06-16 14:25:26 -0500400 * @brief Update resolution D-bus property for this error log
401 *
402 * Update the resolution property of D-bus with callouts extracted from PEL
403 *
404 * @param[in] pel - The PEL to use
405 */
406 void updateResolution(std::unique_ptr<openpower::pels::PEL>& pel);
407
408 /**
Vijay Loboafb1b462021-07-21 23:29:13 -0500409 * @brief Create PELEntry Interface with supported properties
410 *
411 * Create PELEntry Interface and update all the properties which are
412 * supported
413 *
414 * @param[in] obmcLogID - The OpenBMC entry log ID
415 */
416 void createPELEntry(uint32_t obmcLogID);
417
418 /**
Matt Spinler4e8078c2019-07-09 13:22:32 -0500419 * @brief Reference to phosphor-logging's Manager class
420 */
Matt Spinler367144c2019-09-19 15:33:52 -0500421 phosphor::logging::internal::Manager& _logManager;
Matt Spinler89fa0822019-07-17 13:54:30 -0500422
423 /**
Matt Spinlerf682b402019-12-18 13:48:08 -0600424 * @brief Handles creating event logs/PELs from within
425 * the PEL extension code
426 */
427 EventLogger _eventLogger;
428
429 /**
Matt Spinler89fa0822019-07-17 13:54:30 -0500430 * @brief The PEL repository object
431 */
432 Repository _repo;
Matt Spinlerc8705e22019-09-11 12:36:07 -0500433
434 /**
Matt Spinler367144c2019-09-19 15:33:52 -0500435 * @brief The PEL message registry object
436 */
437 message::Registry _registry;
438
439 /**
Matt Spinlerff9cec22020-07-15 13:06:35 -0500440 * @brief The Event object this class uses
441 */
442 sdeventplus::Event _event;
443
444 /**
Matt Spinlerc8705e22019-09-11 12:36:07 -0500445 * @brief The API the PEL sections use to gather data
446 */
447 std::unique_ptr<DataInterfaceBase> _dataIface;
Matt Spinlerf60ac272019-12-11 13:47:50 -0600448
449 /**
Vijay Loboafb1b462021-07-21 23:29:13 -0500450 * @brief The map used to keep track of PEL entry pointer associated with
451 * event log.
452 */
453 std::map<std::string,
454 std::unique_ptr<
455 sdbusplus::org::open_power::Logging::PEL::server::Entry>>
456 _pelEntries;
457
458 /**
Matt Spinlerf60ac272019-12-11 13:47:50 -0600459 * @brief The HostNotifier object used for telling the
460 * host about new PELs
461 */
462 std::unique_ptr<HostNotifier> _hostNotifier;
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600463
464 /**
465 * @brief The event source for closing a PEL file descriptor after
466 * it has been returned from the getPEL D-Bus method.
467 */
468 std::unique_ptr<sdeventplus::source::Defer> _fdCloserEventSource;
Matt Spinler7e727a32020-07-07 15:00:17 -0500469
470 /**
471 * @brief The even source for removing old PELs when the repo is
472 * running out of space to make room for new ones.
473 */
474 std::unique_ptr<sdeventplus::source::Defer> _repoPrunerEventSource;
Matt Spinlerff9cec22020-07-15 13:06:35 -0500475
476 /**
477 * @brief The even source for watching for deleted PEL files.
478 */
479 std::unique_ptr<sdeventplus::source::IO> _pelFileDeleteEventSource;
480
481 /**
482 * @brief The file descriptor returned by inotify_init1() used
483 * for watching for deleted PEL files.
484 */
485 int _pelFileDeleteFD = -1;
486
487 /**
488 * @brief The file descriptor returned by inotify_add_watch().
489 */
490 int _pelFileDeleteWatchFD = -1;
Matt Spinler4e8078c2019-07-09 13:22:32 -0500491};
492
493} // namespace pels
494} // namespace openpower