1 #pragma once 2 3 #include "config.h" 4 5 #include "data_interface.hpp" 6 #include "event_logger.hpp" 7 #include "host_notifier.hpp" 8 #include "log_manager.hpp" 9 #include "paths.hpp" 10 #include "pel.hpp" 11 #include "registry.hpp" 12 #include "repository.hpp" 13 14 #include <org/open_power/Logging/PEL/Entry/server.hpp> 15 #include <org/open_power/Logging/PEL/server.hpp> 16 #include <sdbusplus/server.hpp> 17 #include <sdeventplus/event.hpp> 18 #include <sdeventplus/source/event.hpp> 19 #include <xyz/openbmc_project/Logging/Create/server.hpp> 20 21 namespace openpower 22 { 23 namespace pels 24 { 25 26 using PELInterface = sdbusplus::server::object::object< 27 sdbusplus::org::open_power::Logging::server::PEL>; 28 29 /** 30 * @brief PEL manager object 31 */ 32 class Manager : public PELInterface 33 { 34 public: 35 Manager() = delete; 36 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 45 * @param[in] dataIface - The data interface object 46 * @param[in] creatorFunc - The function that EventLogger will 47 * use for creating event logs 48 */ 49 Manager(phosphor::logging::internal::Manager& logManager, 50 std::unique_ptr<DataInterfaceBase> dataIface, 51 EventLogger::LogFunction creatorFunc) : 52 PELInterface(logManager.getBus(), OBJ_LOGGING), 53 _logManager(logManager), _eventLogger(std::move(creatorFunc)), 54 _repo(getPELRepoPath()), 55 _registry(getPELReadOnlyDataPath() / message::registryFileName), 56 _event(sdeventplus::Event::get_default()), 57 _dataIface(std::move(dataIface)) 58 { 59 for (const auto& entry : _logManager.entries) 60 { 61 setEntryPath(entry.first); 62 setServiceProviderNotifyFlag(entry.first); 63 // Create PELEntry interface and setup properties with their values 64 createPELEntry(entry.first, true); 65 } 66 setupPELDeleteWatch(); 67 } 68 69 /** 70 * @brief constructor that enables host notification 71 * 72 * @param[in] logManager - internal::Manager object 73 * @param[in] dataIface - The data interface object 74 * @param[in] creatorFunc - The function that EventLogger will 75 * use for creating event logs 76 * @param[in] hostIface - The hostInterface object 77 */ 78 Manager(phosphor::logging::internal::Manager& logManager, 79 std::unique_ptr<DataInterfaceBase> dataIface, 80 EventLogger::LogFunction creatorFunc, 81 std::unique_ptr<HostInterface> hostIface) : 82 Manager(logManager, std::move(dataIface), std::move(creatorFunc)) 83 { 84 _hostNotifier = std::make_unique<HostNotifier>( 85 _repo, *(_dataIface.get()), std::move(hostIface)); 86 } 87 88 /** 89 * @brief Destructor 90 */ 91 ~Manager(); 92 93 /** 94 * @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 104 * @param[in] ffdc - A vector of FFDC file information 105 */ 106 void create(const std::string& message, uint32_t obmcLogID, 107 uint64_t timestamp, phosphor::logging::Entry::Level severity, 108 const std::vector<std::string>& additionalData, 109 const std::vector<std::string>& associations, 110 const phosphor::logging::FFDCEntries& ffdc = 111 phosphor::logging::FFDCEntries{}); 112 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 131 /** 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 182 /** 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 */ 195 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>> 201 fFDC) override; 202 203 /** 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 217 /** 218 * @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 /** 225 * @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 231 /** @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 244 /** @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 256 /** 257 * @brief Update boot progress SRC based on severity 0x51, critical error 258 * 259 * @param[in] pel - The PEL to use 260 */ 261 void updateProgressSRC(std::unique_ptr<openpower::pels::PEL>& pel) const; 262 263 private: 264 /** 265 * @brief Adds a received raw PEL to the PEL repository 266 * 267 * @param[in] rawPelPath - The path to the file that contains the 268 * raw PEL. 269 * @param[in] obmcLogID - the corresponding OpenBMC event log id 270 */ 271 void addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID); 272 273 /** 274 * @brief Creates a PEL based on the OpenBMC event log contents. 275 * 276 * @param[in] message - The event log message property 277 * @param[in] obmcLogID - the corresponding OpenBMC event log id 278 * @param[in] timestamp - The timestamp property 279 * @param[in] severity - The event log severity 280 * @param[in] additionalData - The AdditionalData property 281 * @param[in] associations - The associations property 282 * @param[in] ffdc - A vector of FFDC file information 283 */ 284 void createPEL(const std::string& message, uint32_t obmcLogID, 285 uint64_t timestamp, phosphor::logging::Entry::Level severity, 286 const std::vector<std::string>& additionalData, 287 const std::vector<std::string>& associations, 288 const phosphor::logging::FFDCEntries& ffdc); 289 290 /** 291 * @brief Schedules a close of the file descriptor to occur from 292 * the event loop. 293 * 294 * Uses sd_event_add_defer 295 * 296 * @param[in] fd - The file descriptor to close 297 */ 298 void scheduleFDClose(int fd); 299 300 /** 301 * @brief Closes the file descriptor passed in. 302 * 303 * This is called from the event loop to close FDs returned 304 * from getPEL(). 305 * 306 * @param[in] fd - The file descriptor to close 307 * @param[in] source - The event source object used 308 */ 309 void closeFD(int fd, sdeventplus::source::EventBase& source); 310 311 /** 312 * @brief Adds a PEL to the repository given its data 313 * 314 * @param[in] pelData - The PEL to add as a vector of uint8_ts 315 * @param[in] obmcLogID - the OpenBMC event log ID 316 */ 317 void addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID); 318 319 /** 320 * @brief Adds the PEL stored in the ESEL field of the AdditionalData 321 * property of an OpenBMC event log to the repository. 322 * 323 * @param[in] esel - The ESEL AdditionalData contents 324 * @param[in] obmcLogID - The OpenBMC event log ID 325 */ 326 void addESELPEL(const std::string& esel, uint32_t obmcLogID); 327 328 /** 329 * @brief Converts the D-Bus FFDC method argument into a data 330 * structure understood by the PEL code. 331 * 332 * @param[in] ffdc - A vector of FFDC file information 333 * 334 * @return PelFFDC - The PEL FFDC data structure 335 */ 336 PelFFDC convertToPelFFDC(const phosphor::logging::FFDCEntries& ffdc); 337 338 /** 339 * @brief Schedules a PEL repository prune to occur from 340 * the event loop. 341 * 342 * Uses sd_event_add_defer 343 */ 344 void scheduleRepoPrune(); 345 346 /** 347 * @brief Prunes old PELs out of the repository to save space. 348 * 349 * This is called from the event loop. 350 * 351 * @param[in] source - The event source object used 352 */ 353 void pruneRepo(sdeventplus::source::EventBase& source); 354 355 /** 356 * @brief Sets up an inotify watch to watch for deleted PEL 357 * files. Calls pelFileDeleted() when that occurs. 358 */ 359 void setupPELDeleteWatch(); 360 361 /** 362 * @brief Called when the inotify watch put on the repository directory 363 * detects a PEL file was deleted. 364 * 365 * Will tell the Repository class about the deleted PEL, and then tell 366 * the log manager class to delete the corresponding OpenBMC event log. 367 */ 368 void pelFileDeleted(sdeventplus::source::IO& io, int fd, uint32_t revents); 369 370 /** 371 * @brief Check if the input PEL should cause a quiesce of the system 372 * 373 * If QuiesceOnHwError is enabled within phosphor-settings and the PEL 374 * from the host has a severity which is not SeverityType::nonError or 375 * recovered then execute the quiesce and boot block logic. 376 * 377 * @param[in] pel - The PEL to check 378 */ 379 void checkPelAndQuiesce(std::unique_ptr<openpower::pels::PEL>& pel); 380 381 /** 382 * @brief Update eventId D-bus property for this error log 383 * 384 * Update the eventId property of D-bus with SRC and hexwords from the 385 * PEL created 386 * 387 * @param[in] pel - The PEL to use 388 */ 389 void updateEventId(std::unique_ptr<openpower::pels::PEL>& pel); 390 391 /** 392 * @brief Sets the FilePath of the specified error log entry to the PEL file 393 * path. 394 * 395 * @param[in] obmcLogID - The OpenBMC entry log ID 396 */ 397 void setEntryPath(uint32_t obmcLogID); 398 399 /** 400 * @brief Sets the serviceProviderNotify D-bus property of PEL. 401 * 402 * @param[in] obmcLogID - The OpenBMC entry log ID 403 */ 404 void setServiceProviderNotifyFlag(uint32_t obmcLogID); 405 406 /** 407 * @brief Update resolution D-bus property for this error log 408 * 409 * Update the resolution property of D-bus with callouts extracted from PEL 410 * 411 * @param[in] pel - The PEL to use 412 */ 413 void updateResolution(std::unique_ptr<openpower::pels::PEL>& pel); 414 415 /** 416 * @brief Create PELEntry Interface with supported properties 417 * 418 * Create PELEntry Interface and update all the properties which are 419 * supported 420 * 421 * @param[in] obmcLogID - The OpenBMC entry log ID 422 * @param[in] skipIaSignal - If The InterfacesAdded signal should be 423 * skipped after creating the interfaces. 424 */ 425 void createPELEntry(uint32_t obmcLogID, bool skipIaSignal = false); 426 427 /** 428 * @brief Schedules the delete of the OpenBMC event log for when 429 * execution gets back to the event loop (uses sd_event_add_defer). 430 * 431 * @param[in] obmcLogID - The OpenBMC entry log ID 432 */ 433 void scheduleObmcLogDelete(uint32_t obmcLogID); 434 435 /** 436 * @brief SD event callback to delete an OpenBMC event log 437 * 438 * @param[in] obmcLogID - The OpenBMC entry log ID 439 */ 440 void deleteObmcLog(sdeventplus::source::EventBase&, uint32_t obmcLogID); 441 442 /** 443 * @brief Reference to phosphor-logging's Manager class 444 */ 445 phosphor::logging::internal::Manager& _logManager; 446 447 /** 448 * @brief Handles creating event logs/PELs from within 449 * the PEL extension code 450 */ 451 EventLogger _eventLogger; 452 453 /** 454 * @brief The PEL repository object 455 */ 456 Repository _repo; 457 458 /** 459 * @brief The PEL message registry object 460 */ 461 message::Registry _registry; 462 463 /** 464 * @brief The Event object this class uses 465 */ 466 sdeventplus::Event _event; 467 468 /** 469 * @brief The API the PEL sections use to gather data 470 */ 471 std::unique_ptr<DataInterfaceBase> _dataIface; 472 473 /** 474 * @brief The map used to keep track of PEL entry pointer associated with 475 * event log. 476 */ 477 std::map<std::string, 478 std::unique_ptr< 479 sdbusplus::org::open_power::Logging::PEL::server::Entry>> 480 _pelEntries; 481 482 /** 483 * @brief The HostNotifier object used for telling the 484 * host about new PELs 485 */ 486 std::unique_ptr<HostNotifier> _hostNotifier; 487 488 /** 489 * @brief The event source for closing a PEL file descriptor after 490 * it has been returned from the getPEL D-Bus method. 491 */ 492 std::unique_ptr<sdeventplus::source::Defer> _fdCloserEventSource; 493 494 /** 495 * @brief The even source for removing old PELs when the repo is 496 * running out of space to make room for new ones. 497 */ 498 std::unique_ptr<sdeventplus::source::Defer> _repoPrunerEventSource; 499 500 /** 501 * @brief The event source for deleting an OpenBMC event log. 502 * Used when its corresponding PEL is invalid. 503 */ 504 std::unique_ptr<sdeventplus::source::Defer> _obmcLogDeleteEventSource; 505 506 /** 507 * @brief The even source for watching for deleted PEL files. 508 */ 509 std::unique_ptr<sdeventplus::source::IO> _pelFileDeleteEventSource; 510 511 /** 512 * @brief The file descriptor returned by inotify_init1() used 513 * for watching for deleted PEL files. 514 */ 515 int _pelFileDeleteFD = -1; 516 517 /** 518 * @brief The file descriptor returned by inotify_add_watch(). 519 */ 520 int _pelFileDeleteWatchFD = -1; 521 }; 522 523 } // namespace pels 524 } // namespace openpower 525