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