1 #pragma once 2 3 #include "elog_entry.hpp" 4 #include "xyz/openbmc_project/Collection/DeleteAll/server.hpp" 5 #include "xyz/openbmc_project/Logging/Create/server.hpp" 6 #include "xyz/openbmc_project/Logging/Entry/server.hpp" 7 #include "xyz/openbmc_project/Logging/Internal/Manager/server.hpp" 8 9 #include <list> 10 #include <phosphor-logging/log.hpp> 11 #include <sdbusplus/bus.hpp> 12 13 namespace phosphor 14 { 15 namespace logging 16 { 17 18 extern const std::map<std::string, std::vector<std::string>> g_errMetaMap; 19 extern const std::map<std::string, level> g_errLevelMap; 20 21 using CreateIface = sdbusplus::xyz::openbmc_project::Logging::server::Create; 22 using DeleteAllIface = 23 sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll; 24 25 namespace details 26 { 27 template <typename... T> 28 using ServerObject = typename sdbusplus::server::object::object<T...>; 29 30 using ManagerIface = 31 sdbusplus::xyz::openbmc_project::Logging::Internal::server::Manager; 32 33 } // namespace details 34 35 constexpr size_t ffdcFormatPos = 0; 36 constexpr size_t ffdcSubtypePos = 1; 37 constexpr size_t ffdcVersionPos = 2; 38 constexpr size_t ffdcFDPos = 3; 39 40 using FFDCEntry = std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t, 41 sdbusplus::message::unix_fd>; 42 43 using FFDCEntries = std::vector<FFDCEntry>; 44 45 namespace internal 46 { 47 48 /** @class Manager 49 * @brief OpenBMC logging manager implementation. 50 * @details A concrete implementation for the 51 * xyz.openbmc_project.Logging.Internal.Manager DBus API. 52 */ 53 class Manager : public details::ServerObject<details::ManagerIface> 54 { 55 public: 56 Manager() = delete; 57 Manager(const Manager&) = delete; 58 Manager& operator=(const Manager&) = delete; 59 Manager(Manager&&) = delete; 60 Manager& operator=(Manager&&) = delete; 61 virtual ~Manager() = default; 62 63 /** @brief Constructor to put object onto bus at a dbus path. 64 * @param[in] bus - Bus to attach to. 65 * @param[in] path - Path to attach at. 66 */ 67 Manager(sdbusplus::bus::bus& bus, const char* objPath) : 68 details::ServerObject<details::ManagerIface>(bus, objPath), busLog(bus), 69 entryId(0), fwVersion(readFWVersion()){}; 70 71 /* 72 * @fn commit() 73 * @brief sd_bus Commit method implementation callback. 74 * @details Create an error/event log based on transaction id and 75 * error message. 76 * @param[in] transactionId - Unique identifier of the journal entries 77 * to be committed. 78 * @param[in] errMsg - The error exception message associated with the 79 * error log to be committed. 80 */ 81 void commit(uint64_t transactionId, std::string errMsg) override; 82 83 /* 84 * @fn commit() 85 * @brief sd_bus CommitWithLvl method implementation callback. 86 * @details Create an error/event log based on transaction id and 87 * error message. 88 * @param[in] transactionId - Unique identifier of the journal entries 89 * to be committed. 90 * @param[in] errMsg - The error exception message associated with the 91 * error log to be committed. 92 * @param[in] errLvl - level of the error 93 */ 94 void commitWithLvl(uint64_t transactionId, std::string errMsg, 95 uint32_t errLvl) override; 96 97 /** @brief Erase specified entry d-bus object 98 * 99 * @param[in] entryId - unique identifier of the entry 100 */ 101 void erase(uint32_t entryId); 102 103 /** @brief Construct error d-bus objects from their persisted 104 * representations. 105 */ 106 void restore(); 107 108 /** @brief Erase all error log entries 109 * 110 */ 111 void eraseAll() 112 { 113 auto iter = entries.begin(); 114 while (iter != entries.end()) 115 { 116 auto e = iter->first; 117 ++iter; 118 erase(e); 119 } 120 } 121 122 /** @brief Returns the count of high severity errors 123 * 124 * @return int - count of real errors 125 */ 126 int getRealErrSize(); 127 128 /** @brief Returns the count of Info errors 129 * 130 * @return int - count of info errors 131 */ 132 int getInfoErrSize(); 133 134 sdbusplus::bus::bus& getBus() 135 { 136 return busLog; 137 } 138 139 /** @brief Creates an event log 140 * 141 * This is an alternative to the _commit() API. It doesn't use 142 * the journal to look up event log metadata like _commit does. 143 * 144 * @param[in] errMsg - The error exception message associated with the 145 * error log to be committed. 146 * @param[in] severity - level of the error 147 * @param[in] additionalData - The AdditionalData property for the error 148 */ 149 void create( 150 const std::string& message, 151 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 152 const std::map<std::string, std::string>& additionalData); 153 154 /** @brief Creates an event log, and accepts FFDC files 155 * 156 * This is the same as create(), but also takes an FFDC argument. 157 * 158 * The FFDC argument is a vector of tuples that allows one to pass in file 159 * descriptors for files that contain FFDC (First Failure Data Capture). 160 * These will be passed to any event logging extensions. 161 * 162 * @param[in] errMsg - The error exception message associated with the 163 * error log to be committed. 164 * @param[in] severity - level of the error 165 * @param[in] additionalData - The AdditionalData property for the error 166 * @param[in] ffdc - A vector of FFDC file info 167 */ 168 void createWithFFDC( 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 const FFDCEntries& ffdc); 173 174 /** @brief Common wrapper for creating an Entry object 175 * 176 * @return true if quiesce on error setting is enabled, false otherwise 177 */ 178 bool isQuiesceOnErrorEnabled(); 179 180 /** @brief Check if error has callout and if so, block boot 181 * 182 * @param[in] entry - The error to check for callouts 183 */ 184 void checkQuiesceOnError(const Entry& entry); 185 186 private: 187 /* 188 * @fn _commit() 189 * @brief commit() helper 190 * @param[in] transactionId - Unique identifier of the journal entries 191 * to be committed. 192 * @param[in] errMsg - The error exception message associated with the 193 * error log to be committed. 194 * @param[in] errLvl - level of the error 195 */ 196 void _commit(uint64_t transactionId, std::string&& errMsg, 197 Entry::Level errLvl); 198 199 /** @brief Call metadata handler(s), if any. Handlers may create 200 * associations. 201 * @param[in] errorName - name of the error 202 * @param[in] additionalData - list of metadata (in key=value format) 203 * @param[out] objects - list of error's association objects 204 */ 205 void processMetadata(const std::string& errorName, 206 const std::vector<std::string>& additionalData, 207 AssociationList& objects) const; 208 209 /** @brief Synchronize unwritten journal messages to disk. 210 * @details This is the same implementation as the systemd command 211 * "journalctl --sync". 212 */ 213 void journalSync(); 214 215 /** @brief Reads the BMC code level 216 * 217 * @return std::string - the version string 218 */ 219 static std::string readFWVersion(); 220 221 /** @brief Call any create() functions provided by any extensions. 222 * This is called right after an event log is created to allow 223 * extensions to create their own log based on this one. 224 * 225 * @param[in] entry - the new event log entry 226 * @param[in] ffdc - A vector of FFDC file info 227 */ 228 void doExtensionLogCreate(const Entry& entry, const FFDCEntries& ffdc); 229 230 /** @brief Common wrapper for creating an Entry object 231 * 232 * @param[in] errMsg - The error exception message associated with the 233 * error log to be committed. 234 * @param[in] errLvl - level of the error 235 * @param[in] additionalData - The AdditionalData property for the error 236 * @param[in] ffdc - A vector of FFDC file info. Defaults to an empty 237 * vector. 238 */ 239 void createEntry(std::string errMsg, Entry::Level errLvl, 240 std::vector<std::string> additionalData, 241 const FFDCEntries& ffdc = FFDCEntries{}); 242 243 /** @brief Persistent sdbusplus DBus bus connection. */ 244 sdbusplus::bus::bus& busLog; 245 246 /** @brief Persistent map of Entry dbus objects and their ID */ 247 std::map<uint32_t, std::unique_ptr<Entry>> entries; 248 249 /** @brief List of error ids for high severity errors */ 250 std::list<uint32_t> realErrors; 251 252 /** @brief List of error ids for Info(and below) severity */ 253 std::list<uint32_t> infoErrors; 254 255 /** @brief Id of last error log entry */ 256 uint32_t entryId; 257 258 /** @brief The BMC firmware version */ 259 const std::string fwVersion; 260 }; 261 262 } // namespace internal 263 264 /** @class Manager 265 * @brief Implementation for deleting all error log entries and 266 * creating new logs. 267 * @details A concrete implementation for the 268 * xyz.openbmc_project.Collection.DeleteAll and 269 * xyz.openbmc_project.Logging.Create interfaces. 270 */ 271 class Manager : public details::ServerObject<DeleteAllIface, CreateIface> 272 { 273 public: 274 Manager() = delete; 275 Manager(const Manager&) = delete; 276 Manager& operator=(const Manager&) = delete; 277 Manager(Manager&&) = delete; 278 Manager& operator=(Manager&&) = delete; 279 virtual ~Manager() = default; 280 281 /** @brief Constructor to put object onto bus at a dbus path. 282 * Defer signal registration (pass true for deferSignal to the 283 * base class) until after the properties are set. 284 * @param[in] bus - Bus to attach to. 285 * @param[in] path - Path to attach at. 286 * @param[in] manager - Reference to internal manager object. 287 */ 288 Manager(sdbusplus::bus::bus& bus, const std::string& path, 289 internal::Manager& manager) : 290 details::ServerObject<DeleteAllIface, CreateIface>(bus, path.c_str(), 291 true), 292 manager(manager){}; 293 294 /** @brief Delete all d-bus objects. 295 */ 296 void deleteAll() 297 { 298 manager.eraseAll(); 299 } 300 301 /** @brief D-Bus method call implementation to create an event log. 302 * 303 * @param[in] errMsg - The error exception message associated with the 304 * error log to be committed. 305 * @param[in] severity - Level of the error 306 * @param[in] additionalData - The AdditionalData property for the error 307 */ 308 void create( 309 std::string message, 310 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 311 std::map<std::string, std::string> additionalData) override 312 { 313 manager.create(message, severity, additionalData); 314 } 315 316 /** @brief D-Bus method call implementation to create an event log with FFDC 317 * 318 * The same as create(), but takes an extra FFDC argument. 319 * 320 * @param[in] errMsg - The error exception message associated with the 321 * error log to be committed. 322 * @param[in] severity - Level of the error 323 * @param[in] additionalData - The AdditionalData property for the error 324 * @param[in] ffdc - A vector of FFDC file info 325 */ 326 void createWithFFDCFiles( 327 std::string message, 328 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity, 329 std::map<std::string, std::string> additionalData, 330 std::vector<std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t, 331 sdbusplus::message::unix_fd>> 332 ffdc) override 333 { 334 manager.createWithFFDC(message, severity, additionalData, ffdc); 335 } 336 337 private: 338 /** @brief This is a reference to manager object */ 339 internal::Manager& manager; 340 }; 341 342 } // namespace logging 343 } // namespace phosphor 344