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 Check if error has callout and if so, block boot 200 * 201 * @param[in] entry - The error to check for callouts 202 */ 203 void checkQuiesceOnError(const Entry& entry); 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 Persistent sdbusplus DBus bus connection. */ 290 sdbusplus::bus::bus& busLog; 291 292 /** @brief Persistent map of Entry dbus objects and their ID */ 293 std::map<uint32_t, std::unique_ptr<Entry>> entries; 294 295 /** @brief List of error ids for high severity errors */ 296 std::list<uint32_t> realErrors; 297 298 /** @brief List of error ids for Info(and below) severity */ 299 std::list<uint32_t> infoErrors; 300 301 /** @brief Id of last error log entry */ 302 uint32_t entryId; 303 304 /** @brief The BMC firmware version */ 305 const std::string fwVersion; 306 307 /** @brief Array of blocking errors */ 308 std::vector<std::unique_ptr<Block>> blockingErrors; 309 310 /** @brief Map of entry id to call back object on properties changed */ 311 std::map<uint32_t, std::unique_ptr<sdbusplus::bus::match::match>> 312 propChangedEntryCallback; 313 }; 314 315 } // namespace internal 316 317 /** @class Manager 318 * @brief Implementation for deleting all error log entries and 319 * creating new logs. 320 * @details A concrete implementation for the 321 * xyz.openbmc_project.Collection.DeleteAll and 322 * xyz.openbmc_project.Logging.Create interfaces. 323 */ 324 class Manager : public details::ServerObject<DeleteAllIface, CreateIface> 325 { 326 public: 327 Manager() = delete; 328 Manager(const Manager&) = delete; 329 Manager& operator=(const Manager&) = delete; 330 Manager(Manager&&) = delete; 331 Manager& operator=(Manager&&) = delete; 332 virtual ~Manager() = default; 333 334 /** @brief Constructor to put object onto bus at a dbus path. 335 * Defer signal registration (pass true for deferSignal to the 336 * base class) until after the properties are set. 337 * @param[in] bus - Bus to attach to. 338 * @param[in] path - Path to attach at. 339 * @param[in] manager - Reference to internal manager object. 340 */ 341 Manager(sdbusplus::bus::bus& bus, const std::string& path, 342 internal::Manager& manager) : 343 details::ServerObject<DeleteAllIface, CreateIface>(bus, path.c_str(), 344 true), 345 manager(manager){}; 346 347 /** @brief Delete all d-bus objects. 348 */ 349 void deleteAll() 350 { 351 manager.eraseAll(); 352 } 353 354 /** @brief D-Bus method call implementation to create an event log. 355 * 356 * @param[in] errMsg - The error exception message associated with the 357 * error log to be committed. 358 * @param[in] severity - Level of the error 359 * @param[in] additionalData - The AdditionalData property for the error 360 */ 361 void create( 362 std::string message, 363 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 364 std::map<std::string, std::string> additionalData) override 365 { 366 manager.create(message, severity, additionalData); 367 } 368 369 /** @brief D-Bus method call implementation to create an event log with FFDC 370 * 371 * The same as create(), but takes an extra FFDC argument. 372 * 373 * @param[in] errMsg - The error exception message associated with the 374 * error log to be committed. 375 * @param[in] severity - Level of the error 376 * @param[in] additionalData - The AdditionalData property for the error 377 * @param[in] ffdc - A vector of FFDC file info 378 */ 379 void createWithFFDCFiles( 380 std::string message, 381 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 382 std::map<std::string, std::string> additionalData, 383 std::vector<std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t, 384 sdbusplus::message::unix_fd>> 385 ffdc) override 386 { 387 manager.createWithFFDC(message, severity, additionalData, ffdc); 388 } 389 390 private: 391 /** @brief This is a reference to manager object */ 392 internal::Manager& manager; 393 }; 394 395 } // namespace logging 396 } // namespace phosphor 397