1 #pragma once 2 3 #include "host_interface.hpp" 4 5 #include <libpldm/pldm.h> 6 7 #include <sdeventplus/clock.hpp> 8 #include <sdeventplus/source/io.hpp> 9 #include <sdeventplus/utility/timer.hpp> 10 11 #include <chrono> 12 #include <memory> 13 14 namespace 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 */ 25 class 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 { 46 sd_bus_default(&_bus); 47 48 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 * 60 * It starts by issuing the async D-Bus method call to read the 61 * instance ID. 62 * 63 * @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 72 * 73 * This will clear the instance ID so the next command 74 * will request a new one. 75 */ 76 void cancelCmd() override; 77 78 /** 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 96 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 /** 137 * @brief Makes the async D-Bus method call to read the PLDM instance 138 * ID needed to send PLDM commands. 139 */ 140 void startReadInstanceID(); 141 142 /** 143 * @brief Encodes and sends the PLDM 'new file available' cmd 144 */ 145 void doSend(); 146 147 /** 148 * @brief Closes the PLDM file descriptor 149 */ 150 void closeFD(); 151 152 /** 153 * @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 /** 160 * @brief The MCTP endpoint ID 161 */ 162 mctp_eid_t _eid; 163 164 /** 165 * @brief The PLDM instance ID of the current command 166 * 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. 171 */ 172 std::optional<uint8_t> _instanceID; 173 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}; 194 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; 209 }; 210 211 } // namespace openpower::pels 212