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