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