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 void 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 void 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 sdbusplus::bus::bus& getBus() 154 { 155 return busLog; 156 } 157 158 /** @brief Creates an event log 159 * 160 * This is an alternative to the _commit() API. It doesn't use 161 * the journal to look up event log metadata like _commit does. 162 * 163 * @param[in] errMsg - The error exception message associated with the 164 * error log to be committed. 165 * @param[in] severity - level of the error 166 * @param[in] additionalData - The AdditionalData property for the error 167 */ 168 void create( 169 const std::string& message, 170 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 171 const std::map<std::string, std::string>& additionalData); 172 173 /** @brief Creates an event log, and accepts FFDC files 174 * 175 * This is the same as create(), but also takes an FFDC argument. 176 * 177 * The FFDC argument is a vector of tuples that allows one to pass in file 178 * descriptors for files that contain FFDC (First Failure Data Capture). 179 * These will be passed to any event logging extensions. 180 * 181 * @param[in] errMsg - The error exception message associated with the 182 * error log to be committed. 183 * @param[in] severity - level of the error 184 * @param[in] additionalData - The AdditionalData property for the error 185 * @param[in] ffdc - A vector of FFDC file info 186 */ 187 void createWithFFDC( 188 const std::string& message, 189 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 190 const std::map<std::string, std::string>& additionalData, 191 const FFDCEntries& ffdc); 192 193 /** @brief Common wrapper for creating an Entry object 194 * 195 * @return true if quiesce on error setting is enabled, false otherwise 196 */ 197 bool isQuiesceOnErrorEnabled(); 198 199 /** @brief Create boot block association and quiesce host if running 200 * 201 * @param[in] entryId - The ID of the phosphor logging error 202 */ 203 void quiesceOnError(const uint32_t entryId); 204 205 /** @brief Check if inventory callout present in input entry 206 * 207 * @param[in] entry - The error to check for callouts 208 * 209 * @return true if inventory item in associations, false otherwise 210 */ 211 bool isCalloutPresent(const Entry& entry); 212 213 /** @brief Check (and remove) entry being erased from blocking errors 214 * 215 * @param[in] entryId - The entry that is being erased 216 */ 217 void checkAndRemoveBlockingError(uint32_t entryId); 218 219 private: 220 /* 221 * @fn _commit() 222 * @brief commit() helper 223 * @param[in] transactionId - Unique identifier of the journal entries 224 * to be committed. 225 * @param[in] errMsg - The error exception message associated with the 226 * error log to be committed. 227 * @param[in] errLvl - level of the error 228 */ 229 void _commit(uint64_t transactionId, std::string&& errMsg, 230 Entry::Level errLvl); 231 232 /** @brief Call metadata handler(s), if any. Handlers may create 233 * associations. 234 * @param[in] errorName - name of the error 235 * @param[in] additionalData - list of metadata (in key=value format) 236 * @param[out] objects - list of error's association objects 237 */ 238 void processMetadata(const std::string& errorName, 239 const std::vector<std::string>& additionalData, 240 AssociationList& objects) const; 241 242 /** @brief Synchronize unwritten journal messages to disk. 243 * @details This is the same implementation as the systemd command 244 * "journalctl --sync". 245 */ 246 void journalSync(); 247 248 /** @brief Reads the BMC code level 249 * 250 * @return std::string - the version string 251 */ 252 static std::string readFWVersion(); 253 254 /** @brief Call any create() functions provided by any extensions. 255 * This is called right after an event log is created to allow 256 * extensions to create their own log based on this one. 257 * 258 * @param[in] entry - the new event log entry 259 * @param[in] ffdc - A vector of FFDC file info 260 */ 261 void doExtensionLogCreate(const Entry& entry, const FFDCEntries& ffdc); 262 263 /** @brief Common wrapper for creating an Entry object 264 * 265 * @param[in] errMsg - The error exception message associated with the 266 * error log to be committed. 267 * @param[in] errLvl - level of the error 268 * @param[in] additionalData - The AdditionalData property for the error 269 * @param[in] ffdc - A vector of FFDC file info. Defaults to an empty 270 * vector. 271 */ 272 void createEntry(std::string errMsg, Entry::Level errLvl, 273 std::vector<std::string> additionalData, 274 const FFDCEntries& ffdc = FFDCEntries{}); 275 276 /** @brief Notified on entry property changes 277 * 278 * If an entry is blocking, this callback will be registered to monitor for 279 * the entry having it's Resolved field set to true. If it is then remove 280 * the blocking object. 281 * 282 * @param[in] msg - sdbusplus dbusmessage 283 */ 284 void onEntryResolve(sdbusplus::message::message& msg); 285 286 /** @brief Remove block objects for any resolved entries */ 287 void findAndRemoveResolvedBlocks(); 288 289 /** @brief Quiesce host if it is running 290 * 291 * This is called when the user has requested the system be quiesced 292 * if a log with a callout is created 293 */ 294 void checkAndQuiesceHost(); 295 296 /** @brief Persistent sdbusplus DBus bus connection. */ 297 sdbusplus::bus::bus& busLog; 298 299 /** @brief Persistent map of Entry dbus objects and their ID */ 300 std::map<uint32_t, std::unique_ptr<Entry>> entries; 301 302 /** @brief List of error ids for high severity errors */ 303 std::list<uint32_t> realErrors; 304 305 /** @brief List of error ids for Info(and below) severity */ 306 std::list<uint32_t> infoErrors; 307 308 /** @brief Id of last error log entry */ 309 uint32_t entryId; 310 311 /** @brief The BMC firmware version */ 312 const std::string fwVersion; 313 314 /** @brief Array of blocking errors */ 315 std::vector<std::unique_ptr<Block>> blockingErrors; 316 317 /** @brief Map of entry id to call back object on properties changed */ 318 std::map<uint32_t, std::unique_ptr<sdbusplus::bus::match::match>> 319 propChangedEntryCallback; 320 }; 321 322 } // namespace internal 323 324 /** @class Manager 325 * @brief Implementation for deleting all error log entries and 326 * creating new logs. 327 * @details A concrete implementation for the 328 * xyz.openbmc_project.Collection.DeleteAll and 329 * xyz.openbmc_project.Logging.Create interfaces. 330 */ 331 class Manager : public details::ServerObject<DeleteAllIface, CreateIface> 332 { 333 public: 334 Manager() = delete; 335 Manager(const Manager&) = delete; 336 Manager& operator=(const Manager&) = delete; 337 Manager(Manager&&) = delete; 338 Manager& operator=(Manager&&) = delete; 339 virtual ~Manager() = default; 340 341 /** @brief Constructor to put object onto bus at a dbus path. 342 * Defer signal registration (pass true for deferSignal to the 343 * base class) until after the properties are set. 344 * @param[in] bus - Bus to attach to. 345 * @param[in] path - Path to attach at. 346 * @param[in] manager - Reference to internal manager object. 347 */ 348 Manager(sdbusplus::bus::bus& bus, const std::string& path, 349 internal::Manager& manager) : 350 details::ServerObject<DeleteAllIface, CreateIface>(bus, path.c_str(), 351 true), 352 manager(manager){}; 353 354 /** @brief Delete all d-bus objects. 355 */ 356 void deleteAll() 357 { 358 manager.eraseAll(); 359 } 360 361 /** @brief D-Bus method call implementation to create an event log. 362 * 363 * @param[in] errMsg - The error exception message associated with the 364 * error log to be committed. 365 * @param[in] severity - Level of the error 366 * @param[in] additionalData - The AdditionalData property for the error 367 */ 368 void create( 369 std::string message, 370 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 371 std::map<std::string, std::string> additionalData) override 372 { 373 manager.create(message, severity, additionalData); 374 } 375 376 /** @brief D-Bus method call implementation to create an event log with FFDC 377 * 378 * The same as create(), but takes an extra FFDC argument. 379 * 380 * @param[in] errMsg - The error exception message associated with the 381 * error log to be committed. 382 * @param[in] severity - Level of the error 383 * @param[in] additionalData - The AdditionalData property for the error 384 * @param[in] ffdc - A vector of FFDC file info 385 */ 386 void createWithFFDCFiles( 387 std::string message, 388 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 389 std::map<std::string, std::string> additionalData, 390 std::vector<std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t, 391 sdbusplus::message::unix_fd>> 392 ffdc) override 393 { 394 manager.createWithFFDC(message, severity, additionalData, ffdc); 395 } 396 397 private: 398 /** @brief This is a reference to manager object */ 399 internal::Manager& manager; 400 }; 401 402 } // namespace logging 403 } // namespace phosphor 404