blob: b6dae3cd3a1c71c14f77ae14fc86aa47c2508c3c [file] [log] [blame]
Matt Spinler5c350fd2019-12-12 13:53:53 -06001#pragma once
2
3#include "host_interface.hpp"
4
5#include <libpldm/pldm.h>
6
Matt Spinler5c350fd2019-12-12 13:53:53 -06007#include <sdeventplus/clock.hpp>
8#include <sdeventplus/source/io.hpp>
9#include <sdeventplus/utility/timer.hpp>
10
Patrick Williams2544b412022-10-04 08:41:06 -050011#include <chrono>
12#include <memory>
13
Matt Spinler5c350fd2019-12-12 13:53:53 -060014namespace openpower::pels
15{
16
17/**
18 * @class PLDMInterface
19 *
20 * This class handles sending the 'new file available' PLDM
21 * command to the host to notify it of a new PEL's ID and size.
22 *
23 * The command response is asynchronous.
24 */
25class PLDMInterface : public HostInterface
26{
27 public:
28 PLDMInterface() = delete;
29 PLDMInterface(const PLDMInterface&) = default;
30 PLDMInterface& operator=(const PLDMInterface&) = default;
31 PLDMInterface(PLDMInterface&&) = default;
32 PLDMInterface& operator=(PLDMInterface&&) = default;
33
34 /**
35 * @brief Constructor
36 *
37 * @param[in] event - The sd_event object pointer
38 * @param[in] dataIface - The DataInterface object
39 */
40 PLDMInterface(sd_event* event, DataInterfaceBase& dataIface) :
41 HostInterface(event, dataIface),
42 _receiveTimer(
43 event,
44 std::bind(std::mem_fn(&PLDMInterface::receiveTimerExpired), this))
45 {
Matt Spinler2843ba22020-03-03 16:36:32 -060046 sd_bus_default(&_bus);
47
Matt Spinler5c350fd2019-12-12 13:53:53 -060048 readEID();
49 }
50
51 /**
52 * @brief Destructor
53 */
54 ~PLDMInterface();
55
56 /**
57 * @brief Kicks off the send of the 'new file available' command
58 * to send up the ID and size of the new PEL.
59 *
Matt Spinler2843ba22020-03-03 16:36:32 -060060 * It starts by issuing the async D-Bus method call to read the
61 * instance ID.
62 *
Matt Spinler5c350fd2019-12-12 13:53:53 -060063 * @param[in] id - The PEL ID
64 * @param[in] size - The PEL size in bytes
65 *
66 * @return CmdStatus - the success/fail status of the send
67 */
68 CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) override;
69
70 /**
71 * @brief Cancels waiting for a command response
Matt Spinler2843ba22020-03-03 16:36:32 -060072 *
73 * This will clear the instance ID so the next command
74 * will request a new one.
Matt Spinler5c350fd2019-12-12 13:53:53 -060075 */
76 void cancelCmd() override;
77
Matt Spinler2843ba22020-03-03 16:36:32 -060078 /**
79 * @brief Cleans up so that a new command is ready to be sent.
80 *
81 * Does not clear the instance ID.
82 */
83 void cleanupCmd();
84
85 /**
86 * @brief Gets called on the async D-Bus method response to
87 * getting the PLDM instance ID.
88 *
89 * It will read the instance ID out of the message and then
90 * continue on with sending the new log command to the host.
91 *
92 * @param[in] msg - The message containing the instance ID.
93 */
94 void instanceIDCallback(sd_bus_message* msg);
95
Matt Spinler5c350fd2019-12-12 13:53:53 -060096 private:
97 /**
98 * @brief The asynchronous callback for getting the response
99 * of the 'new file available' command.
100 *
101 * Calls the response callback that is registered.
102 *
103 * @param[in] io - The event source object
104 * @param[in] fd - The FD used
105 * @param[in] revents - The event bits
106 */
107 void receive(sdeventplus::source::IO& io, int fd,
108 uint32_t revents) override;
109
110 /**
111 * @brief Function called when the receive timer expires.
112 *
113 * This is considered a failure and so will invoke the
114 * registered response callback function with a failure
115 * indication.
116 */
117 void receiveTimerExpired();
118
119 /**
120 * @brief Configures the sdeventplus::source::IO object to
121 * call receive() on EPOLLIN activity on the PLDM FD
122 * which is used for command responses.
123 */
124 void registerReceiveCallback();
125
126 /**
127 * @brief Reads the MCTP endpoint ID out of a file
128 */
129 void readEID();
130
131 /**
132 * @brief Opens the PLDM file descriptor
133 */
134 void open();
135
136 /**
Matt Spinler2843ba22020-03-03 16:36:32 -0600137 * @brief Makes the async D-Bus method call to read the PLDM instance
138 * ID needed to send PLDM commands.
Matt Spinler5c350fd2019-12-12 13:53:53 -0600139 */
Matt Spinler2843ba22020-03-03 16:36:32 -0600140 void startReadInstanceID();
Matt Spinler5c350fd2019-12-12 13:53:53 -0600141
142 /**
143 * @brief Encodes and sends the PLDM 'new file available' cmd
Matt Spinler5c350fd2019-12-12 13:53:53 -0600144 */
Matt Spinler2843ba22020-03-03 16:36:32 -0600145 void doSend();
Matt Spinler5c350fd2019-12-12 13:53:53 -0600146
147 /**
148 * @brief Closes the PLDM file descriptor
149 */
150 void closeFD();
151
152 /**
Matt Spinler2843ba22020-03-03 16:36:32 -0600153 * @brief Kicks off the send of the 'new file available' command
154 * to send the ID and size of a PEL after the instance ID
155 * has been retrieved.
156 */
157 void startCommand();
158
159 /**
Matt Spinler5c350fd2019-12-12 13:53:53 -0600160 * @brief The MCTP endpoint ID
161 */
162 mctp_eid_t _eid;
163
164 /**
165 * @brief The PLDM instance ID of the current command
Matt Spinler2843ba22020-03-03 16:36:32 -0600166 *
167 * A new ID will be used for every command.
168 *
169 * If there are command failures, the same instance ID can be
170 * used on retries only if the host didn't respond.
Matt Spinler5c350fd2019-12-12 13:53:53 -0600171 */
Matt Spinler2843ba22020-03-03 16:36:32 -0600172 std::optional<uint8_t> _instanceID;
Matt Spinler5c350fd2019-12-12 13:53:53 -0600173
174 /**
175 * @brief The PLDM command file descriptor for the current command
176 */
177 int _fd = -1;
178
179 /**
180 * @brief The event object for handling callbacks on the PLDM FD
181 */
182 std::unique_ptr<sdeventplus::source::IO> _source;
183
184 /**
185 * @brief A timer to only allow a certain amount of time for the
186 * async PLDM receive before it is considered a failure.
187 */
188 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _receiveTimer;
189
190 /**
191 * @brief The command timeout value
192 */
193 const std::chrono::milliseconds _receiveTimeout{10000};
Matt Spinler2843ba22020-03-03 16:36:32 -0600194
195 /**
196 * @brief The D-Bus connection needed for the async method call.
197 */
198 sd_bus* _bus = nullptr;
199
200 /**
201 * @brief The ID of the PEL to notify the host of.
202 */
203 uint32_t _pelID = 0;
204
205 /**
206 * @brief The size of the PEL to notify the host of.
207 */
208 uint32_t _pelSize = 0;
Matt Spinler5c350fd2019-12-12 13:53:53 -0600209};
210
211} // namespace openpower::pels