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