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/server.hpp> 15 #include <sdbusplus/server.hpp> 16 #include <sdeventplus/event.hpp> 17 #include <sdeventplus/source/event.hpp> 18 #include <xyz/openbmc_project/Logging/Create/server.hpp> 19 20 namespace openpower 21 { 22 namespace pels 23 { 24 25 using PELInterface = sdbusplus::server::object::object< 26 sdbusplus::org::open_power::Logging::server::PEL>; 27 28 /** 29 * @brief PEL manager object 30 */ 31 class Manager : public PELInterface 32 { 33 public: 34 Manager() = delete; 35 Manager(const Manager&) = default; 36 Manager& operator=(const Manager&) = default; 37 Manager(Manager&&) = default; 38 Manager& operator=(Manager&&) = default; 39 40 /** 41 * @brief constructor 42 * 43 * @param[in] logManager - internal::Manager object 44 * @param[in] dataIface - The data interface object 45 * @param[in] creatorFunc - The function that EventLogger will 46 * use for creating event logs 47 */ 48 Manager(phosphor::logging::internal::Manager& logManager, 49 std::unique_ptr<DataInterfaceBase> dataIface, 50 EventLogger::LogFunction creatorFunc) : 51 PELInterface(logManager.getBus(), OBJ_LOGGING), 52 _logManager(logManager), _eventLogger(std::move(creatorFunc)), 53 _repo(getPELRepoPath()), 54 _registry(getPELReadOnlyDataPath() / message::registryFileName), 55 _event(sdeventplus::Event::get_default()), 56 _dataIface(std::move(dataIface)) 57 { 58 for (const auto& entry : _logManager.entries) 59 { 60 setEntryPath(entry.first); 61 setServiceProviderNotifyFlag(entry.first); 62 } 63 setupPELDeleteWatch(); 64 } 65 66 /** 67 * @brief constructor that enables host notification 68 * 69 * @param[in] logManager - internal::Manager object 70 * @param[in] dataIface - The data interface object 71 * @param[in] creatorFunc - The function that EventLogger will 72 * use for creating event logs 73 * @param[in] hostIface - The hostInterface object 74 */ 75 Manager(phosphor::logging::internal::Manager& logManager, 76 std::unique_ptr<DataInterfaceBase> dataIface, 77 EventLogger::LogFunction creatorFunc, 78 std::unique_ptr<HostInterface> hostIface) : 79 Manager(logManager, std::move(dataIface), std::move(creatorFunc)) 80 { 81 _hostNotifier = std::make_unique<HostNotifier>( 82 _repo, *(_dataIface.get()), std::move(hostIface)); 83 } 84 85 /** 86 * @brief Destructor 87 */ 88 ~Manager(); 89 90 /** 91 * @brief Creates a PEL based on the OpenBMC event log contents. If 92 * a PEL was passed in via the RAWPEL specifier in the 93 * additionalData parameter, use that instead. 94 * 95 * @param[in] message - the event log message property 96 * @param[in] obmcLogID - the corresponding OpenBMC event log id 97 * @param[in] timestamp - the Timestamp property 98 * @param[in] severity - the event log severity 99 * @param[in] additionalData - the AdditionalData property 100 * @param[in] associations - the Associations property 101 * @param[in] ffdc - A vector of FFDC file information 102 */ 103 void create(const std::string& message, uint32_t obmcLogID, 104 uint64_t timestamp, phosphor::logging::Entry::Level severity, 105 const std::vector<std::string>& additionalData, 106 const std::vector<std::string>& associations, 107 const phosphor::logging::FFDCEntries& ffdc = 108 phosphor::logging::FFDCEntries{}); 109 110 /** 111 * @brief Erase a PEL based on its OpenBMC event log ID 112 * 113 * @param[in] obmcLogID - the corresponding OpenBMC event log id 114 */ 115 void erase(uint32_t obmcLogID); 116 117 /** @brief Says if an OpenBMC event log may not be manually deleted at this 118 * time because its corresponding PEL cannot be. 119 * 120 * There are PEL retention policies that can prohibit the manual deletion 121 * of PELs (and therefore OpenBMC event logs). 122 * 123 * @param[in] obmcLogID - the OpenBMC event log ID 124 * @return bool - true if prohibited 125 */ 126 bool isDeleteProhibited(uint32_t obmcLogID); 127 128 /** 129 * @brief Return a file descriptor to the raw PEL data 130 * 131 * Throws InvalidArgument if the PEL ID isn't found, 132 * and InternalFailure if anything else fails. 133 * 134 * @param[in] pelID - The PEL ID to get the data for 135 * 136 * @return unix_fd - File descriptor to the file that contains the PEL 137 */ 138 sdbusplus::message::unix_fd getPEL(uint32_t pelID) override; 139 140 /** 141 * @brief Returns data for the PEL corresponding to an OpenBMC 142 * event log. 143 * 144 * @param[in] obmcLogID - The OpenBMC event log ID 145 * 146 * @return vector<uint8_t> - The raw PEL data 147 */ 148 std::vector<uint8_t> getPELFromOBMCID(uint32_t obmcLogID) override; 149 150 /** 151 * @brief The D-Bus method called when a host successfully processes 152 * a PEL. 153 * 154 * This D-Bus method is called from the PLDM daemon when they get an 155 * 'Ack PEL' PLDM message from the host, which indicates the host 156 * firmware successfully sent it to the OS and this code doesn't need 157 * to send it to the host again. 158 * 159 * @param[in] pelID - The PEL ID 160 */ 161 void hostAck(uint32_t pelID) override; 162 163 /** 164 * @brief D-Bus method called when the host rejects a PEL. 165 * 166 * This D-Bus method is called from the PLDM daemon when they get an 167 * 'Ack PEL' PLDM message from the host with a payload that says 168 * something when wrong. 169 * 170 * The choices are either: 171 * * Host Full - The host's staging area is full - try again later 172 * * Malrformed PEL - The host received an invalid PEL 173 * 174 * @param[in] pelID - The PEL ID 175 * @param[in] reason - One of the above two reasons 176 */ 177 void hostReject(uint32_t pelID, RejectionReason reason) override; 178 179 /** 180 * @brief D-Bus method to create a PEL/OpenBMC event log and 181 * return the created OpenBMC and PEL log IDs. 182 * 183 * The same as the CreateWithFFDCFiles method on the 184 * xyz.openbmc_project.Logging.Create interface, except for 185 * the return values. 186 * 187 * @param[in] message - The event log message property 188 * @param[in] severity - The event log severity 189 * @param[in] additionalData - The AdditionalData property 190 * @param[in] ffdc - A vector of FFDC file information 191 */ 192 std::tuple<uint32_t, uint32_t> createPELWithFFDCFiles( 193 std::string message, phosphor::logging::Entry::Level severity, 194 std::map<std::string, std::string> additionalData, 195 std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging:: 196 server::Create::FFDCFormat, 197 uint8_t, uint8_t, sdbusplus::message::unix_fd>> 198 fFDC) override; 199 200 /** 201 * @brief Converts the ESEL field in an OpenBMC event log to a 202 * vector of uint8_ts that just contains the PEL data. 203 * 204 * That data string looks like: "50 48 00 ab ..." 205 * 206 * Throws an exception on any failures. 207 * 208 * @param[in] esel - The ESEL string 209 * 210 * @return std::vector<uint8_t> - The contained PEL data 211 */ 212 static std::vector<uint8_t> eselToRawData(const std::string& esel); 213 214 /** 215 * @brief Generate resolution string from the PEL 216 * 217 * @param[in] pel - The PEL to use 218 */ 219 std::string getResolution(const openpower::pels::PEL& pel) const; 220 221 /** 222 * @brief Generate event ID from the PEL 223 * 224 * @param[in] pel - The PEL to use 225 */ 226 std::string getEventId(const openpower::pels::PEL& pel) const; 227 228 /** @brief Implementation for GetPELIdFromBMCLogId 229 * 230 * Returns the PEL Id (aka Entry ID (EID)) based on the given 231 * BMC event log id. 232 * 233 * @param[in] bmcLogId - The BMC event log id of the PEL to retrieve 234 * the PEL id. 235 * 236 * @return uint32_t - The Id of the PEL. 237 * Throw "InvalidArgument" if not found. 238 */ 239 uint32_t getPELIdFromBMCLogId(uint32_t bmcLogId) override; 240 241 /** @brief Implementation for GetBMCLogIdFromPELId 242 * 243 * Returns the BMC event log id based on the given PEL id 244 * (aka Entry ID (EID)). 245 * 246 * @param[in] pelId - The PEL id to retrieve the BMC event log id. 247 * 248 * @return uint32_t - The BMC event log id of the PEL. 249 * Throw "InvalidArgument" if not found. 250 */ 251 uint32_t getBMCLogIdFromPELId(uint32_t pelId) override; 252 253 private: 254 /** 255 * @brief Adds a received raw PEL to the PEL repository 256 * 257 * @param[in] rawPelPath - The path to the file that contains the 258 * raw PEL. 259 * @param[in] obmcLogID - the corresponding OpenBMC event log id 260 */ 261 void addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID); 262 263 /** 264 * @brief Creates a PEL based on the OpenBMC event log contents. 265 * 266 * @param[in] message - The event log message property 267 * @param[in] obmcLogID - the corresponding OpenBMC event log id 268 * @param[in] timestamp - The timestamp property 269 * @param[in] severity - The event log severity 270 * @param[in] additionalData - The AdditionalData property 271 * @param[in] associations - The associations property 272 * @param[in] ffdc - A vector of FFDC file information 273 */ 274 void createPEL(const std::string& message, uint32_t obmcLogID, 275 uint64_t timestamp, phosphor::logging::Entry::Level severity, 276 const std::vector<std::string>& additionalData, 277 const std::vector<std::string>& associations, 278 const phosphor::logging::FFDCEntries& ffdc); 279 280 /** 281 * @brief Schedules a close of the file descriptor to occur from 282 * the event loop. 283 * 284 * Uses sd_event_add_defer 285 * 286 * @param[in] fd - The file descriptor to close 287 */ 288 void scheduleFDClose(int fd); 289 290 /** 291 * @brief Closes the file descriptor passed in. 292 * 293 * This is called from the event loop to close FDs returned 294 * from getPEL(). 295 * 296 * @param[in] fd - The file descriptor to close 297 * @param[in] source - The event source object used 298 */ 299 void closeFD(int fd, sdeventplus::source::EventBase& source); 300 301 /** 302 * @brief Adds a PEL to the repository given its data 303 * 304 * @param[in] pelData - The PEL to add as a vector of uint8_ts 305 * @param[in] obmcLogID - the OpenBMC event log ID 306 */ 307 void addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID); 308 309 /** 310 * @brief Adds the PEL stored in the ESEL field of the AdditionalData 311 * property of an OpenBMC event log to the repository. 312 * 313 * @param[in] esel - The ESEL AdditionalData contents 314 * @param[in] obmcLogID - The OpenBMC event log ID 315 */ 316 void addESELPEL(const std::string& esel, uint32_t obmcLogID); 317 318 /** 319 * @brief Converts the D-Bus FFDC method argument into a data 320 * structure understood by the PEL code. 321 * 322 * @param[in] ffdc - A vector of FFDC file information 323 * 324 * @return PelFFDC - The PEL FFDC data structure 325 */ 326 PelFFDC convertToPelFFDC(const phosphor::logging::FFDCEntries& ffdc); 327 328 /** 329 * @brief Schedules a PEL repository prune to occur from 330 * the event loop. 331 * 332 * Uses sd_event_add_defer 333 */ 334 void scheduleRepoPrune(); 335 336 /** 337 * @brief Prunes old PELs out of the repository to save space. 338 * 339 * This is called from the event loop. 340 * 341 * @param[in] source - The event source object used 342 */ 343 void pruneRepo(sdeventplus::source::EventBase& source); 344 345 /** 346 * @brief Sets up an inotify watch to watch for deleted PEL 347 * files. Calls pelFileDeleted() when that occurs. 348 */ 349 void setupPELDeleteWatch(); 350 351 /** 352 * @brief Called when the inotify watch put on the repository directory 353 * detects a PEL file was deleted. 354 * 355 * Will tell the Repository class about the deleted PEL, and then tell 356 * the log manager class to delete the corresponding OpenBMC event log. 357 */ 358 void pelFileDeleted(sdeventplus::source::IO& io, int fd, uint32_t revents); 359 360 /** 361 * @brief Check if the input PEL should cause a quiesce of the system 362 * 363 * If QuiesceOnHwError is enabled within phosphor-settings and the PEL 364 * from the host has a severity which is not SeverityType::nonError or 365 * recovered then execute the quiesce and boot block logic. 366 * 367 * @param[in] pel - The PEL to check 368 */ 369 void checkPelAndQuiesce(std::unique_ptr<openpower::pels::PEL>& pel); 370 371 /** 372 * @brief Update eventId D-bus property for this error log 373 * 374 * Update the eventId property of D-bus with SRC and hexwords from the 375 * PEL created 376 * 377 * @param[in] pel - The PEL to use 378 */ 379 void updateEventId(std::unique_ptr<openpower::pels::PEL>& pel); 380 381 /** 382 * @brief Sets the FilePath of the specified error log entry to the PEL file 383 * path. 384 * 385 * @param[in] obmcLogID - The OpenBMC entry log ID 386 */ 387 void setEntryPath(uint32_t obmcLogID); 388 389 /** 390 * @brief Sets the serviceProviderNotify D-bus property of PEL. 391 * 392 * @param[in] obmcLogID - The OpenBMC entry log ID 393 */ 394 void setServiceProviderNotifyFlag(uint32_t obmcLogID); 395 396 /** 397 * @brief Update resolution D-bus property for this error log 398 * 399 * Update the resolution property of D-bus with callouts extracted from PEL 400 * 401 * @param[in] pel - The PEL to use 402 */ 403 void updateResolution(std::unique_ptr<openpower::pels::PEL>& pel); 404 405 /** 406 * @brief Reference to phosphor-logging's Manager class 407 */ 408 phosphor::logging::internal::Manager& _logManager; 409 410 /** 411 * @brief Handles creating event logs/PELs from within 412 * the PEL extension code 413 */ 414 EventLogger _eventLogger; 415 416 /** 417 * @brief The PEL repository object 418 */ 419 Repository _repo; 420 421 /** 422 * @brief The PEL message registry object 423 */ 424 message::Registry _registry; 425 426 /** 427 * @brief The Event object this class uses 428 */ 429 sdeventplus::Event _event; 430 431 /** 432 * @brief The API the PEL sections use to gather data 433 */ 434 std::unique_ptr<DataInterfaceBase> _dataIface; 435 436 /** 437 * @brief The HostNotifier object used for telling the 438 * host about new PELs 439 */ 440 std::unique_ptr<HostNotifier> _hostNotifier; 441 442 /** 443 * @brief The event source for closing a PEL file descriptor after 444 * it has been returned from the getPEL D-Bus method. 445 */ 446 std::unique_ptr<sdeventplus::source::Defer> _fdCloserEventSource; 447 448 /** 449 * @brief The even source for removing old PELs when the repo is 450 * running out of space to make room for new ones. 451 */ 452 std::unique_ptr<sdeventplus::source::Defer> _repoPrunerEventSource; 453 454 /** 455 * @brief The even source for watching for deleted PEL files. 456 */ 457 std::unique_ptr<sdeventplus::source::IO> _pelFileDeleteEventSource; 458 459 /** 460 * @brief The file descriptor returned by inotify_init1() used 461 * for watching for deleted PEL files. 462 */ 463 int _pelFileDeleteFD = -1; 464 465 /** 466 * @brief The file descriptor returned by inotify_add_watch(). 467 */ 468 int _pelFileDeleteWatchFD = -1; 469 }; 470 471 } // namespace pels 472 } // namespace openpower 473