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