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 namespace internal
36 {
37 
38 /** @class Manager
39  *  @brief OpenBMC logging manager implementation.
40  *  @details A concrete implementation for the
41  *  xyz.openbmc_project.Logging.Internal.Manager DBus API.
42  */
43 class Manager : public details::ServerObject<details::ManagerIface>
44 {
45   public:
46     Manager() = delete;
47     Manager(const Manager&) = delete;
48     Manager& operator=(const Manager&) = delete;
49     Manager(Manager&&) = delete;
50     Manager& operator=(Manager&&) = delete;
51     virtual ~Manager() = default;
52 
53     /** @brief Constructor to put object onto bus at a dbus path.
54      *  @param[in] bus - Bus to attach to.
55      *  @param[in] path - Path to attach at.
56      */
57     Manager(sdbusplus::bus::bus& bus, const char* objPath) :
58         details::ServerObject<details::ManagerIface>(bus, objPath), busLog(bus),
59         entryId(0), fwVersion(readFWVersion()){};
60 
61     /*
62      * @fn commit()
63      * @brief sd_bus Commit method implementation callback.
64      * @details Create an error/event log based on transaction id and
65      *          error message.
66      * @param[in] transactionId - Unique identifier of the journal entries
67      *                            to be committed.
68      * @param[in] errMsg - The error exception message associated with the
69      *                     error log to be committed.
70      */
71     void commit(uint64_t transactionId, std::string errMsg) override;
72 
73     /*
74      * @fn commit()
75      * @brief sd_bus CommitWithLvl method implementation callback.
76      * @details Create an error/event log based on transaction id and
77      *          error message.
78      * @param[in] transactionId - Unique identifier of the journal entries
79      *                            to be committed.
80      * @param[in] errMsg - The error exception message associated with the
81      *                     error log to be committed.
82      * @param[in] errLvl - level of the error
83      */
84     void commitWithLvl(uint64_t transactionId, std::string errMsg,
85                        uint32_t errLvl) override;
86 
87     /** @brief Erase specified entry d-bus object
88      *
89      * @param[in] entryId - unique identifier of the entry
90      */
91     void erase(uint32_t entryId);
92 
93     /** @brief Construct error d-bus objects from their persisted
94      *         representations.
95      */
96     void restore();
97 
98     /** @brief  Erase all error log entries
99      *
100      */
101     void eraseAll()
102     {
103         auto iter = entries.begin();
104         while (iter != entries.end())
105         {
106             auto e = iter->first;
107             ++iter;
108             erase(e);
109         }
110     }
111 
112     /** @brief Returns the count of high severity errors
113      *
114      *  @return int - count of real errors
115      */
116     int getRealErrSize();
117 
118     /** @brief Returns the count of Info errors
119      *
120      *  @return int - count of info errors
121      */
122     int getInfoErrSize();
123 
124     sdbusplus::bus::bus& getBus()
125     {
126         return busLog;
127     }
128 
129     /** @brief Creates an event log
130      *
131      *  This is an alternative to the _commit() API.  It doesn't use
132      *  the journal to look up event log metadata like _commit does.
133      *
134      * @param[in] errMsg - The error exception message associated with the
135      *                     error log to be committed.
136      * @param[in] severity - level of the error
137      * @param[in] additionalData - The AdditionalData property for the error
138      */
139     void create(
140         const std::string& message,
141         sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity,
142         const std::map<std::string, std::string>& additionalData);
143 
144   private:
145     /*
146      * @fn _commit()
147      * @brief commit() helper
148      * @param[in] transactionId - Unique identifier of the journal entries
149      *                            to be committed.
150      * @param[in] errMsg - The error exception message associated with the
151      *                     error log to be committed.
152      * @param[in] errLvl - level of the error
153      */
154     void _commit(uint64_t transactionId, std::string&& errMsg,
155                  Entry::Level errLvl);
156 
157     /** @brief Call metadata handler(s), if any. Handlers may create
158      *         associations.
159      *  @param[in] errorName - name of the error
160      *  @param[in] additionalData - list of metadata (in key=value format)
161      *  @param[out] objects - list of error's association objects
162      */
163     void processMetadata(const std::string& errorName,
164                          const std::vector<std::string>& additionalData,
165                          AssociationList& objects) const;
166 
167     /** @brief Synchronize unwritten journal messages to disk.
168      *  @details This is the same implementation as the systemd command
169      *  "journalctl --sync".
170      */
171     void journalSync();
172 
173     /** @brief Reads the BMC code level
174      *
175      *  @return std::string - the version string
176      */
177     static std::string readFWVersion();
178 
179     /** @brief Call any create() functions provided by any extensions.
180      *  This is called right after an event log is created to allow
181      *  extensions to create their own log based on this one.
182      *
183      *  @param[in] entry - the new event log entry
184      */
185     void doExtensionLogCreate(const Entry& entry);
186 
187     /** @brief Common wrapper for creating an Entry object
188      *
189      * @param[in] errMsg - The error exception message associated with the
190      *                     error log to be committed.
191      * @param[in] errLvl - level of the error
192      * @param[in] additionalData - The AdditionalData property for the error
193      */
194     void createEntry(std::string errMsg, Entry::Level errLvl,
195                      std::vector<std::string> additionalData);
196 
197     /** @brief Persistent sdbusplus DBus bus connection. */
198     sdbusplus::bus::bus& busLog;
199 
200     /** @brief Persistent map of Entry dbus objects and their ID */
201     std::map<uint32_t, std::unique_ptr<Entry>> entries;
202 
203     /** @brief List of error ids for high severity errors */
204     std::list<uint32_t> realErrors;
205 
206     /** @brief List of error ids for Info(and below) severity */
207     std::list<uint32_t> infoErrors;
208 
209     /** @brief Id of last error log entry */
210     uint32_t entryId;
211 
212     /** @brief The BMC firmware version */
213     const std::string fwVersion;
214 };
215 
216 } // namespace internal
217 
218 /** @class Manager
219  *  @brief Implementation for deleting all error log entries and
220  *         creating new logs.
221  *  @details A concrete implementation for the
222  *           xyz.openbmc_project.Collection.DeleteAll and
223  *           xyz.openbmc_project.Logging.Create interfaces.
224  */
225 class Manager : public details::ServerObject<DeleteAllIface, CreateIface>
226 {
227   public:
228     Manager() = delete;
229     Manager(const Manager&) = delete;
230     Manager& operator=(const Manager&) = delete;
231     Manager(Manager&&) = delete;
232     Manager& operator=(Manager&&) = delete;
233     virtual ~Manager() = default;
234 
235     /** @brief Constructor to put object onto bus at a dbus path.
236      *         Defer signal registration (pass true for deferSignal to the
237      *         base class) until after the properties are set.
238      *  @param[in] bus - Bus to attach to.
239      *  @param[in] path - Path to attach at.
240      *  @param[in] manager - Reference to internal manager object.
241      */
242     Manager(sdbusplus::bus::bus& bus, const std::string& path,
243             internal::Manager& manager) :
244         details::ServerObject<DeleteAllIface, CreateIface>(bus, path.c_str(),
245                                                            true),
246         manager(manager){};
247 
248     /** @brief Delete all d-bus objects.
249      */
250     void deleteAll()
251     {
252         manager.eraseAll();
253     }
254 
255     /** @brief D-Bus method call implementation to create an event log.
256      *
257      * @param[in] errMsg - The error exception message associated with the
258      *                     error log to be committed.
259      * @param[in] severity - Level of the error
260      * @param[in] additionalData - The AdditionalData property for the error
261      */
262     void create(
263         std::string message,
264         sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity,
265         std::map<std::string, std::string> additionalData) override
266     {
267         manager.create(message, severity, additionalData);
268     }
269 
270     void createWithFFDCFiles(
271         std::string message,
272         sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level severity,
273         std::map<std::string, std::string> additionalData,
274         std::vector<std::tuple<CreateIface::FFDCFormat, uint8_t, uint8_t,
275                                sdbusplus::message::unix_fd>>
276             ffdc) override
277     {
278     }
279 
280   private:
281     /** @brief This is a reference to manager object */
282     internal::Manager& manager;
283 };
284 
285 } // namespace logging
286 } // namespace phosphor
287