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