1 #pragma once 2 3 #include "elog_block.hpp" 4 #include "elog_entry.hpp" 5 #include "xyz/openbmc_project/Collection/DeleteAll/server.hpp" 6 #include "xyz/openbmc_project/Logging/Create/server.hpp" 7 #include "xyz/openbmc_project/Logging/Entry/server.hpp" 8 #include "xyz/openbmc_project/Logging/Internal/Manager/server.hpp" 9 10 #include <list> 11 #include <phosphor-logging/log.hpp> 12 #include <sdbusplus/bus.hpp> 13 14 namespace phosphor 15 { 16 namespace logging 17 { 18 19 extern const std::map<std::string, std::vector<std::string>> g_errMetaMap; 20 extern const std::map<std::string, level> g_errLevelMap; 21 22 using CreateIface = sdbusplus::xyz::openbmc_project::Logging::server::Create; 23 using DeleteAllIface = 24 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll; 25 26 namespace details 27 { 28 template <typename... T> 29 using ServerObject = typename sdbusplus::server::object::object<T...>; 30 31 using ManagerIface = 32 sdbusplus::xyz::openbmc_project::Logging::Internal::server::Manager; 33 34 } // namespace details 35 36 constexpr size_t ffdcFormatPos = 0; 37 constexpr size_t ffdcSubtypePos = 1; 38 constexpr size_t ffdcVersionPos = 2; 39 constexpr size_t ffdcFDPos = 3; 40 41 using FFDCEntry = std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t, 42 sdbusplus::message::unix_fd>; 43 44 using FFDCEntries = std::vector<FFDCEntry>; 45 46 namespace internal 47 { 48 49 /** @class Manager 50 * @brief OpenBMC logging manager implementation. 51 * @details A concrete implementation for the 52 * xyz.openbmc_project.Logging.Internal.Manager DBus API. 53 */ 54 class Manager : public details::ServerObject<details::ManagerIface> 55 { 56 public: 57 Manager() = delete; 58 Manager(const Manager&) = delete; 59 Manager& operator=(const Manager&) = delete; 60 Manager(Manager&&) = delete; 61 Manager& operator=(Manager&&) = delete; 62 virtual ~Manager() = default; 63 64 /** @brief Constructor to put object onto bus at a dbus path. 65 * @param[in] bus - Bus to attach to. 66 * @param[in] path - Path to attach at. 67 */ 68 Manager(sdbusplus::bus::bus& bus, const char* objPath) : 69 details::ServerObject<details::ManagerIface>(bus, objPath), busLog(bus), 70 entryId(0), fwVersion(readFWVersion()){}; 71 72 /* 73 * @fn commit() 74 * @brief sd_bus Commit method implementation callback. 75 * @details Create an error/event log based on transaction id and 76 * error message. 77 * @param[in] transactionId - Unique identifier of the journal entries 78 * to be committed. 79 * @param[in] errMsg - The error exception message associated with the 80 * error log to be committed. 81 */ 82 uint32_t commit(uint64_t transactionId, std::string errMsg) override; 83 84 /* 85 * @fn commit() 86 * @brief sd_bus CommitWithLvl method implementation callback. 87 * @details Create an error/event log based on transaction id and 88 * error message. 89 * @param[in] transactionId - Unique identifier of the journal entries 90 * to be committed. 91 * @param[in] errMsg - The error exception message associated with the 92 * error log to be committed. 93 * @param[in] errLvl - level of the error 94 */ 95 uint32_t commitWithLvl(uint64_t transactionId, std::string errMsg, 96 uint32_t errLvl) override; 97 98 /** @brief Erase specified entry d-bus object 99 * 100 * @param[in] entryId - unique identifier of the entry 101 */ 102 void erase(uint32_t entryId); 103 104 /** @brief Construct error d-bus objects from their persisted 105 * representations. 106 */ 107 void restore(); 108 109 /** @brief Erase all error log entries 110 * 111 */ 112 void eraseAll() 113 { 114 auto iter = entries.begin(); 115 while (iter != entries.end()) 116 { 117 auto e = iter->first; 118 ++iter; 119 erase(e); 120 } 121 } 122 123 /** @brief Returns the count of high severity errors 124 * 125 * @return int - count of real errors 126 */ 127 int getRealErrSize(); 128 129 /** @brief Returns the count of Info errors 130 * 131 * @return int - count of info errors 132 */ 133 int getInfoErrSize(); 134 135 /** @brief Returns the number of blocking errors 136 * 137 * @return int - count of blocking errors 138 */ 139 int getBlockingErrSize() 140 { 141 return blockingErrors.size(); 142 } 143 144 /** @brief Returns the number of property change callback objects 145 * 146 * @return int - count of property callback entries 147 */ 148 int getEntryCallbackSize() 149 { 150 return propChangedEntryCallback.size(); 151 } 152 153 /** 154 * @brief Returns the sdbusplus bus object 155 * 156 * @return sdbusplus::bus::bus& 157 */ 158 sdbusplus::bus::bus& getBus() 159 { 160 return busLog; 161 } 162 163 /** 164 * @brief Returns the ID of the last created entry 165 * 166 * @return uint32_t - The ID 167 */ 168 uint32_t lastEntryID() const 169 { 170 return entryId; 171 } 172 173 /** @brief Creates an event log 174 * 175 * This is an alternative to the _commit() API. It doesn't use 176 * the journal to look up event log metadata like _commit does. 177 * 178 * @param[in] errMsg - The error exception message associated with the 179 * error log to be committed. 180 * @param[in] severity - level of the error 181 * @param[in] additionalData - The AdditionalData property for the error 182 */ 183 void create( 184 const std::string& message, 185 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 186 const std::map<std::string, std::string>& additionalData); 187 188 /** @brief Creates an event log, and accepts FFDC files 189 * 190 * This is the same as create(), but also takes an FFDC argument. 191 * 192 * The FFDC argument is a vector of tuples that allows one to pass in file 193 * descriptors for files that contain FFDC (First Failure Data Capture). 194 * These will be passed to any event logging extensions. 195 * 196 * @param[in] errMsg - The error exception message associated with the 197 * error log to be committed. 198 * @param[in] severity - level of the error 199 * @param[in] additionalData - The AdditionalData property for the error 200 * @param[in] ffdc - A vector of FFDC file info 201 */ 202 void createWithFFDC( 203 const std::string& message, 204 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 205 const std::map<std::string, std::string>& additionalData, 206 const FFDCEntries& ffdc); 207 208 /** @brief Common wrapper for creating an Entry object 209 * 210 * @return true if quiesce on error setting is enabled, false otherwise 211 */ 212 bool isQuiesceOnErrorEnabled(); 213 214 /** @brief Create boot block association and quiesce host if running 215 * 216 * @param[in] entryId - The ID of the phosphor logging error 217 */ 218 void quiesceOnError(const uint32_t entryId); 219 220 /** @brief Check if inventory callout present in input entry 221 * 222 * @param[in] entry - The error to check for callouts 223 * 224 * @return true if inventory item in associations, false otherwise 225 */ 226 bool isCalloutPresent(const Entry& entry); 227 228 /** @brief Check (and remove) entry being erased from blocking errors 229 * 230 * @param[in] entryId - The entry that is being erased 231 */ 232 void checkAndRemoveBlockingError(uint32_t entryId); 233 234 /** @brief Persistent map of Entry dbus objects and their ID */ 235 std::map<uint32_t, std::unique_ptr<Entry>> entries; 236 237 private: 238 /* 239 * @fn _commit() 240 * @brief commit() helper 241 * @param[in] transactionId - Unique identifier of the journal entries 242 * to be committed. 243 * @param[in] errMsg - The error exception message associated with the 244 * error log to be committed. 245 * @param[in] errLvl - level of the error 246 */ 247 void _commit(uint64_t transactionId, std::string&& errMsg, 248 Entry::Level errLvl); 249 250 /** @brief Call metadata handler(s), if any. Handlers may create 251 * associations. 252 * @param[in] errorName - name of the error 253 * @param[in] additionalData - list of metadata (in key=value format) 254 * @param[out] objects - list of error's association objects 255 */ 256 void processMetadata(const std::string& errorName, 257 const std::vector<std::string>& additionalData, 258 AssociationList& objects) const; 259 260 /** @brief Synchronize unwritten journal messages to disk. 261 * @details This is the same implementation as the systemd command 262 * "journalctl --sync". 263 */ 264 void journalSync(); 265 266 /** @brief Reads the BMC code level 267 * 268 * @return std::string - the version string 269 */ 270 static std::string readFWVersion(); 271 272 /** @brief Call any create() functions provided by any extensions. 273 * This is called right after an event log is created to allow 274 * extensions to create their own log based on this one. 275 * 276 * @param[in] entry - the new event log entry 277 * @param[in] ffdc - A vector of FFDC file info 278 */ 279 void doExtensionLogCreate(const Entry& entry, const FFDCEntries& ffdc); 280 281 /** @brief Common wrapper for creating an Entry object 282 * 283 * @param[in] errMsg - The error exception message associated with the 284 * error log to be committed. 285 * @param[in] errLvl - level of the error 286 * @param[in] additionalData - The AdditionalData property for the error 287 * @param[in] ffdc - A vector of FFDC file info. Defaults to an empty 288 * vector. 289 */ 290 void createEntry(std::string errMsg, Entry::Level errLvl, 291 std::vector<std::string> additionalData, 292 const FFDCEntries& ffdc = FFDCEntries{}); 293 294 /** @brief Notified on entry property changes 295 * 296 * If an entry is blocking, this callback will be registered to monitor for 297 * the entry having it's Resolved field set to true. If it is then remove 298 * the blocking object. 299 * 300 * @param[in] msg - sdbusplus dbusmessage 301 */ 302 void onEntryResolve(sdbusplus::message::message& msg); 303 304 /** @brief Remove block objects for any resolved entries */ 305 void findAndRemoveResolvedBlocks(); 306 307 /** @brief Quiesce host if it is running 308 * 309 * This is called when the user has requested the system be quiesced 310 * if a log with a callout is created 311 */ 312 void checkAndQuiesceHost(); 313 314 /** @brief Persistent sdbusplus DBus bus connection. */ 315 sdbusplus::bus::bus& busLog; 316 317 /** @brief List of error ids for high severity errors */ 318 std::list<uint32_t> realErrors; 319 320 /** @brief List of error ids for Info(and below) severity */ 321 std::list<uint32_t> infoErrors; 322 323 /** @brief Id of last error log entry */ 324 uint32_t entryId; 325 326 /** @brief The BMC firmware version */ 327 const std::string fwVersion; 328 329 /** @brief Array of blocking errors */ 330 std::vector<std::unique_ptr<Block>> blockingErrors; 331 332 /** @brief Map of entry id to call back object on properties changed */ 333 std::map<uint32_t, std::unique_ptr<sdbusplus::bus::match::match>> 334 propChangedEntryCallback; 335 }; 336 337 } // namespace internal 338 339 /** @class Manager 340 * @brief Implementation for deleting all error log entries and 341 * creating new logs. 342 * @details A concrete implementation for the 343 * xyz.openbmc_project.Collection.DeleteAll and 344 * xyz.openbmc_project.Logging.Create interfaces. 345 */ 346 class Manager : public details::ServerObject<DeleteAllIface, CreateIface> 347 { 348 public: 349 Manager() = delete; 350 Manager(const Manager&) = delete; 351 Manager& operator=(const Manager&) = delete; 352 Manager(Manager&&) = delete; 353 Manager& operator=(Manager&&) = delete; 354 virtual ~Manager() = default; 355 356 /** @brief Constructor to put object onto bus at a dbus path. 357 * Defer signal registration (pass true for deferSignal to the 358 * base class) until after the properties are set. 359 * @param[in] bus - Bus to attach to. 360 * @param[in] path - Path to attach at. 361 * @param[in] manager - Reference to internal manager object. 362 */ 363 Manager(sdbusplus::bus::bus& bus, const std::string& path, 364 internal::Manager& manager) : 365 details::ServerObject<DeleteAllIface, CreateIface>(bus, path.c_str(), 366 true), 367 manager(manager){}; 368 369 /** @brief Delete all d-bus objects. 370 */ 371 void deleteAll() 372 { 373 manager.eraseAll(); 374 } 375 376 /** @brief D-Bus method call implementation to create an event log. 377 * 378 * @param[in] errMsg - The error exception message associated with the 379 * error log to be committed. 380 * @param[in] severity - Level of the error 381 * @param[in] additionalData - The AdditionalData property for the error 382 */ 383 void create( 384 std::string message, 385 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 386 std::map<std::string, std::string> additionalData) override 387 { 388 manager.create(message, severity, additionalData); 389 } 390 391 /** @brief D-Bus method call implementation to create an event log with FFDC 392 * 393 * The same as create(), but takes an extra FFDC argument. 394 * 395 * @param[in] errMsg - The error exception message associated with the 396 * error log to be committed. 397 * @param[in] severity - Level of the error 398 * @param[in] additionalData - The AdditionalData property for the error 399 * @param[in] ffdc - A vector of FFDC file info 400 */ 401 void createWithFFDCFiles( 402 std::string message, 403 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 404 std::map<std::string, std::string> additionalData, 405 std::vector<std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t, 406 sdbusplus::message::unix_fd>> 407 ffdc) override 408 { 409 manager.createWithFFDC(message, severity, additionalData, ffdc); 410 } 411 412 private: 413 /** @brief This is a reference to manager object */ 414 internal::Manager& manager; 415 }; 416 417 } // namespace logging 418 } // namespace phosphor 419