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