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