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     /** @brief Returns the count of high severity errors
122      *
123      *  @return int - count of real errors
124      */
125     int getRealErrSize();
126 
127     /** @brief Returns the count of Info errors
128      *
129      *  @return int - count of info errors
130      */
131     int getInfoErrSize();
132 
133     /** @brief Returns the number of blocking errors
134      *
135      *  @return int - count of blocking errors
136      */
137     int getBlockingErrSize()
138     {
139         return blockingErrors.size();
140     }
141 
142     /** @brief Returns the number of property change callback objects
143      *
144      *  @return int - count of property callback entries
145      */
146     int getEntryCallbackSize()
147     {
148         return propChangedEntryCallback.size();
149     }
150 
151     /**
152      * @brief Returns the sdbusplus bus object
153      *
154      * @return sdbusplus::bus_t&
155      */
156     sdbusplus::bus_t& getBus()
157     {
158         return busLog;
159     }
160 
161     /**
162      * @brief Returns the ID of the last created entry
163      *
164      * @return uint32_t - The ID
165      */
166     uint32_t lastEntryID() const
167     {
168         return entryId;
169     }
170 
171     /** @brief Creates an event log
172      *
173      *  This is an alternative to the _commit() API.  It doesn't use
174      *  the journal to look up event log metadata like _commit does.
175      *
176      * @param[in] errMsg - The error exception message associated with the
177      *                     error log to be committed.
178      * @param[in] severity - level of the error
179      * @param[in] additionalData - The AdditionalData property for the error
180      * @param[in] ffdc - A vector of tuples that allows one to pass in file
181      *                   descriptors for files that contain FFDC (First
182      *                   Failure Data Capture). These will be passed to any
183      *                   event logging extensions.
184      */
185     void create(const std::string& message, Severity severity,
186                 const std::map<std::string, std::string>& additionalData,
187                 const FFDCEntries& ffdc = FFDCEntries{});
188 
189     /** @brief Common wrapper for creating an Entry object
190      *
191      * @return true if quiesce on error setting is enabled, false otherwise
192      */
193     bool isQuiesceOnErrorEnabled();
194 
195     /** @brief Create boot block association and quiesce host if running
196      *
197      * @param[in] entryId - The ID of the phosphor logging error
198      */
199     void quiesceOnError(const uint32_t entryId);
200 
201     /** @brief Check if inventory callout present in input entry
202      *
203      * @param[in] entry - The error to check for callouts
204      *
205      * @return true if inventory item in associations, false otherwise
206      */
207     bool isCalloutPresent(const Entry& entry);
208 
209     /** @brief Check (and remove) entry being erased from blocking errors
210      *
211      * @param[in] entryId - The entry that is being erased
212      */
213     void checkAndRemoveBlockingError(uint32_t entryId);
214 
215     /** @brief Persistent map of Entry dbus objects and their ID */
216     std::map<uint32_t, std::unique_ptr<Entry>> entries;
217 
218   private:
219     /*
220      * @fn _commit()
221      * @brief commit() helper
222      * @param[in] transactionId - Unique identifier of the journal entries
223      *                            to be committed.
224      * @param[in] errMsg - The error exception message associated with the
225      *                     error log to be committed.
226      * @param[in] errLvl - level of the error
227      */
228     void _commit(uint64_t transactionId, std::string&& errMsg,
229                  Entry::Level errLvl);
230 
231     /** @brief Call metadata handler(s), if any. Handlers may create
232      *         associations.
233      *  @param[in] errorName - name of the error
234      *  @param[in] additionalData - list of metadata (in key=value format)
235      *  @param[out] objects - list of error's association objects
236      */
237     void processMetadata(const std::string& errorName,
238                          const std::vector<std::string>& additionalData,
239                          AssociationList& objects) const;
240 
241     /** @brief Reads the BMC code level
242      *
243      *  @return std::string - the version string
244      */
245     static std::string readFWVersion();
246 
247     /** @brief Call any create() functions provided by any extensions.
248      *  This is called right after an event log is created to allow
249      *  extensions to create their own log based on this one.
250      *
251      *  @param[in] entry - the new event log entry
252      *  @param[in] ffdc - A vector of FFDC file info
253      */
254     void doExtensionLogCreate(const Entry& entry, const FFDCEntries& ffdc);
255 
256     /** @brief Common wrapper for creating an Entry object
257      *
258      * @param[in] errMsg - The error exception message associated with the
259      *                     error log to be committed.
260      * @param[in] errLvl - level of the error
261      * @param[in] additionalData - The AdditionalData property for the error
262      * @param[in] ffdc - A vector of FFDC file info. Defaults to an empty
263      * vector.
264      */
265     void createEntry(std::string errMsg, Entry::Level errLvl,
266                      std::vector<std::string> additionalData,
267                      const FFDCEntries& ffdc = FFDCEntries{});
268 
269     /** @brief Notified on entry property changes
270      *
271      * If an entry is blocking, this callback will be registered to monitor for
272      * the entry having it's Resolved field set to true. If it is then remove
273      * the blocking object.
274      *
275      * @param[in] msg - sdbusplus dbusmessage
276      */
277     void onEntryResolve(sdbusplus::message_t& msg);
278 
279     /** @brief Remove block objects for any resolved entries  */
280     void findAndRemoveResolvedBlocks();
281 
282     /** @brief Quiesce host if it is running
283      *
284      * This is called when the user has requested the system be quiesced
285      * if a log with a callout is created
286      */
287     void checkAndQuiesceHost();
288 
289     /** @brief Persistent sdbusplus DBus bus connection. */
290     sdbusplus::bus_t& busLog;
291 
292     /** @brief List of error ids for high severity errors */
293     std::list<uint32_t> realErrors;
294 
295     /** @brief List of error ids for Info(and below) severity */
296     std::list<uint32_t> infoErrors;
297 
298     /** @brief Id of last error log entry */
299     uint32_t entryId;
300 
301     /** @brief The BMC firmware version */
302     const std::string fwVersion;
303 
304     /** @brief Array of blocking errors */
305     std::vector<std::unique_ptr<Block>> blockingErrors;
306 
307     /** @brief Map of entry id to call back object on properties changed */
308     std::map<uint32_t, std::unique_ptr<sdbusplus::bus::match_t>>
309         propChangedEntryCallback;
310 };
311 
312 } // namespace internal
313 
314 /** @class Manager
315  *  @brief Implementation for deleting all error log entries and
316  *         creating new logs.
317  *  @details A concrete implementation for the
318  *           xyz.openbmc_project.Collection.DeleteAll and
319  *           xyz.openbmc_project.Logging.Create interfaces.
320  */
321 class Manager : public details::ServerObject<DeleteAllIface, CreateIface>
322 {
323   public:
324     Manager() = delete;
325     Manager(const Manager&) = delete;
326     Manager& operator=(const Manager&) = delete;
327     Manager(Manager&&) = delete;
328     Manager& operator=(Manager&&) = delete;
329     virtual ~Manager() = default;
330 
331     /** @brief Constructor to put object onto bus at a dbus path.
332      *         Defer signal registration (pass true for deferSignal to the
333      *         base class) until after the properties are set.
334      *  @param[in] bus - Bus to attach to.
335      *  @param[in] path - Path to attach at.
336      *  @param[in] manager - Reference to internal manager object.
337      */
338     Manager(sdbusplus::bus_t& bus, const std::string& path,
339             internal::Manager& manager) :
340         details::ServerObject<DeleteAllIface, CreateIface>(
341             bus, path.c_str(),
342             details::ServerObject<DeleteAllIface,
343                                   CreateIface>::action::defer_emit),
344         manager(manager) {};
345 
346     /** @brief Delete all d-bus objects.
347      */
348     void deleteAll() override
349     {
350         log<level::INFO>("Deleting all log entries");
351         auto numbersOfLogs = manager.eraseAll();
352         std::map<std::string, std::string> additionalData;
353         additionalData.emplace("NUM_LOGS", std::to_string(numbersOfLogs));
354         manager.create(LogsCleared::errName, Severity::Informational,
355                        additionalData);
356     }
357 
358     /** @brief D-Bus method call implementation to create an event log.
359      *
360      * @param[in] errMsg - The error exception message associated with the
361      *                     error log to be committed.
362      * @param[in] severity - Level of the error
363      * @param[in] additionalData - The AdditionalData property for the error
364      */
365     void create(std::string message, Severity severity,
366                 std::map<std::string, std::string> additionalData) override
367     {
368         manager.create(message, severity, additionalData);
369     }
370 
371     /** @brief D-Bus method call implementation to create an event log with FFDC
372      *
373      * The same as create(), but takes an extra FFDC argument.
374      *
375      * @param[in] errMsg - The error exception message associated with the
376      *                     error log to be committed.
377      * @param[in] severity - Level of the error
378      * @param[in] additionalData - The AdditionalData property for the error
379      * @param[in] ffdc - A vector of FFDC file info
380      */
381     void createWithFFDCFiles(
382         std::string message, Severity severity,
383         std::map<std::string, std::string> additionalData,
384         std::vector<std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t,
385                                sdbusplus::message::unix_fd>>
386             ffdc) override
387     {
388         manager.create(message, severity, additionalData, ffdc);
389     }
390 
391   private:
392     /** @brief This is a reference to manager object */
393     internal::Manager& manager;
394 };
395 
396 } // namespace logging
397 } // namespace phosphor
398