1 #pragma once
2 
3 #include "config.h"
4 
5 #include "data_interface.hpp"
6 #include "event_logger.hpp"
7 #include "host_notifier.hpp"
8 #include "log_manager.hpp"
9 #include "paths.hpp"
10 #include "pel.hpp"
11 #include "registry.hpp"
12 #include "repository.hpp"
13 
14 #include <org/open_power/Logging/PEL/server.hpp>
15 #include <sdbusplus/server.hpp>
16 #include <sdeventplus/event.hpp>
17 #include <sdeventplus/source/event.hpp>
18 
19 namespace openpower
20 {
21 namespace pels
22 {
23 
24 using PELInterface = sdbusplus::server::object::object<
25     sdbusplus::org::open_power::Logging::server::PEL>;
26 
27 /**
28  * @brief PEL manager object
29  */
30 class Manager : public PELInterface
31 {
32   public:
33     Manager() = delete;
34     ~Manager() = default;
35     Manager(const Manager&) = default;
36     Manager& operator=(const Manager&) = default;
37     Manager(Manager&&) = default;
38     Manager& operator=(Manager&&) = default;
39 
40     /**
41      * @brief constructor
42      *
43      * @param[in] logManager - internal::Manager object
44      * @param[in] dataIface - The data interface object
45      * @param[in] creatorFunc - The function that EventLogger will
46      *                          use for creating event logs
47      */
48     Manager(phosphor::logging::internal::Manager& logManager,
49             std::unique_ptr<DataInterfaceBase> dataIface,
50             EventLogger::LogFunction creatorFunc) :
51         PELInterface(logManager.getBus(), OBJ_LOGGING),
52         _logManager(logManager), _eventLogger(std::move(creatorFunc)),
53         _repo(getPELRepoPath()),
54         _registry(getMessageRegistryPath() / message::registryFileName),
55         _dataIface(std::move(dataIface))
56     {
57     }
58 
59     /**
60      * @brief constructor that enables host notification
61      *
62      * @param[in] logManager - internal::Manager object
63      * @param[in] dataIface - The data interface object
64      * @param[in] creatorFunc - The function that EventLogger will
65      *                          use for creating event logs
66      * @param[in] hostIface - The hostInterface object
67      */
68     Manager(phosphor::logging::internal::Manager& logManager,
69             std::unique_ptr<DataInterfaceBase> dataIface,
70             EventLogger::LogFunction creatorFunc,
71             std::unique_ptr<HostInterface> hostIface) :
72         Manager(logManager, std::move(dataIface), std::move(creatorFunc))
73     {
74         _hostNotifier = std::make_unique<HostNotifier>(
75             _repo, *(_dataIface.get()), std::move(hostIface));
76     }
77 
78     /**
79      * @brief Creates a PEL based on the OpenBMC event log contents.  If
80      *        a PEL was passed in via the RAWPEL specifier in the
81      *        additionalData parameter, use that instead.
82      *
83      * @param[in] message - the event log message property
84      * @param[in] obmcLogID - the corresponding OpenBMC event log id
85      * @param[in] timestamp - the Timestamp property
86      * @param[in] severity - the event log severity
87      * @param[in] additionalData - the AdditionalData property
88      * @param[in] associations - the Associations property
89      * @param[in] ffdc - A vector of FFDC file information
90      */
91     void create(const std::string& message, uint32_t obmcLogID,
92                 uint64_t timestamp, phosphor::logging::Entry::Level severity,
93                 const std::vector<std::string>& additionalData,
94                 const std::vector<std::string>& associations,
95                 const phosphor::logging::FFDCEntries& ffdc =
96                     phosphor::logging::FFDCEntries{});
97 
98     /**
99      * @brief Erase a PEL based on its OpenBMC event log ID
100      *
101      * @param[in] obmcLogID - the corresponding OpenBMC event log id
102      */
103     void erase(uint32_t obmcLogID);
104 
105     /** @brief Says if an OpenBMC event log may not be manually deleted at this
106      *         time because its corresponding PEL cannot be.
107      *
108      * There are PEL retention policies that can prohibit the manual deletion
109      * of PELs (and therefore OpenBMC event logs).
110      *
111      * @param[in] obmcLogID - the OpenBMC event log ID
112      * @return bool - true if prohibited
113      */
114     bool isDeleteProhibited(uint32_t obmcLogID);
115 
116     /**
117      * @brief Return a file descriptor to the raw PEL data
118      *
119      * Throws InvalidArgument if the PEL ID isn't found,
120      * and InternalFailure if anything else fails.
121      *
122      * @param[in] pelID - The PEL ID to get the data for
123      *
124      * @return unix_fd - File descriptor to the file that contains the PEL
125      */
126     sdbusplus::message::unix_fd getPEL(uint32_t pelID) override;
127 
128     /**
129      * @brief Returns data for the PEL corresponding to an OpenBMC
130      *        event log.
131      *
132      * @param[in] obmcLogID - The OpenBMC event log ID
133      *
134      * @return vector<uint8_t> - The raw PEL data
135      */
136     std::vector<uint8_t> getPELFromOBMCID(uint32_t obmcLogID) override;
137 
138     /**
139      * @brief The D-Bus method called when a host successfully processes
140      *        a PEL.
141      *
142      * This D-Bus method is called from the PLDM daemon when they get an
143      * 'Ack PEL' PLDM message from the host, which indicates the host
144      * firmware successfully sent it to the OS and this code doesn't need
145      * to send it to the host again.
146      *
147      * @param[in] pelID - The PEL ID
148      */
149     void hostAck(uint32_t pelID) override;
150 
151     /**
152      * @brief D-Bus method called when the host rejects a PEL.
153      *
154      * This D-Bus method is called from the PLDM daemon when they get an
155      * 'Ack PEL' PLDM message from the host with a payload that says
156      * something when wrong.
157      *
158      * The choices are either:
159      *  * Host Full - The host's staging area is full - try again later
160      *  * Malrformed PEL - The host received an invalid PEL
161      *
162      * @param[in] pelID - The PEL ID
163      * @param[in] reason - One of the above two reasons
164      */
165     void hostReject(uint32_t pelID, RejectionReason reason) override;
166 
167     /**
168      * @brief Converts the ESEL field in an OpenBMC event log to a
169      *        vector of uint8_ts that just contains the PEL data.
170      *
171      * That data string looks like: "50 48 00 ab ..."
172      *
173      * Throws an exception on any failures.
174      *
175      * @param[in] esel - The ESEL string
176      *
177      * @return std::vector<uint8_t> - The contained PEL data
178      */
179     static std::vector<uint8_t> eselToRawData(const std::string& esel);
180 
181   private:
182     /**
183      * @brief Adds a received raw PEL to the PEL repository
184      *
185      * @param[in] rawPelPath - The path to the file that contains the
186      *                         raw PEL.
187      * @param[in] obmcLogID - the corresponding OpenBMC event log id
188      */
189     void addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID);
190 
191     /**
192      * @brief Creates a PEL based on the OpenBMC event log contents.
193      *
194      * @param[in] message - The event log message property
195      * @param[in] obmcLogID - the corresponding OpenBMC event log id
196      * @param[in] timestamp - The timestamp property
197      * @param[in] severity - The event log severity
198      * @param[in] additionalData - The AdditionalData property
199      * @param[in] associations - The associations property
200      * @param[in] ffdc - A vector of FFDC file information
201      */
202     void createPEL(const std::string& message, uint32_t obmcLogID,
203                    uint64_t timestamp, phosphor::logging::Entry::Level severity,
204                    const std::vector<std::string>& additionalData,
205                    const std::vector<std::string>& associations,
206                    const phosphor::logging::FFDCEntries& ffdc);
207 
208     /**
209      * @brief Schedules a close of the file descriptor to occur from
210      *        the event loop.
211      *
212      * Uses sd_event_add_defer
213      *
214      * @param[in] fd - The file descriptor to close
215      */
216     void scheduleFDClose(int fd);
217 
218     /**
219      * @brief Closes the file descriptor passed in.
220      *
221      * This is called from the event loop to close FDs returned
222      * from getPEL().
223      *
224      * @param[in] fd - The file descriptor to close
225      * @param[in] source - The event source object used
226      */
227     void closeFD(int fd, sdeventplus::source::EventBase& source);
228 
229     /**
230      * @brief Adds a PEL to the repository given its data
231      *
232      * @param[in] pelData - The PEL to add as a vector of uint8_ts
233      * @param[in] obmcLogID - the OpenBMC event log ID
234      */
235     void addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID);
236 
237     /**
238      * @brief Adds the PEL stored in the ESEL field of the AdditionalData
239      *        property of an OpenBMC event log to the repository.
240      *
241      * @param[in] esel - The ESEL AdditionalData contents
242      * @param[in] obmcLogID - The OpenBMC event log ID
243      */
244     void addESELPEL(const std::string& esel, uint32_t obmcLogID);
245 
246     /**
247      * @brief Converts the D-Bus FFDC method argument into a data
248      *        structure understood by the PEL code.
249      *
250      * @param[in] ffdc - A vector of FFDC file information
251      *
252      * @return PelFFDC - The PEL FFDC data structure
253      */
254     PelFFDC convertToPelFFDC(const phosphor::logging::FFDCEntries& ffdc);
255 
256     /**
257      * @brief Reference to phosphor-logging's Manager class
258      */
259     phosphor::logging::internal::Manager& _logManager;
260 
261     /**
262      * @brief Handles creating event logs/PELs from within
263      *        the PEL extension code
264      */
265     EventLogger _eventLogger;
266 
267     /**
268      * @brief The PEL repository object
269      */
270     Repository _repo;
271 
272     /**
273      * @brief The PEL message registry object
274      */
275     message::Registry _registry;
276 
277     /**
278      * @brief The API the PEL sections use to gather data
279      */
280     std::unique_ptr<DataInterfaceBase> _dataIface;
281 
282     /**
283      * @brief The HostNotifier object used for telling the
284      *        host about new PELs
285      */
286     std::unique_ptr<HostNotifier> _hostNotifier;
287 
288     /**
289      * @brief The event source for closing a PEL file descriptor after
290      *        it has been returned from the getPEL D-Bus method.
291      */
292     std::unique_ptr<sdeventplus::source::Defer> _fdCloserEventSource;
293 };
294 
295 } // namespace pels
296 } // namespace openpower
297