1 #pragma once 2 #include "libpldm/entity.h" 3 #include "libpldm/platform.h" 4 #include "oem/ibm/libpldm/state_set.h" 5 6 #include "inband_code_update.hpp" 7 #include "libpldmresponder/oem_handler.hpp" 8 #include "libpldmresponder/pdr_utils.hpp" 9 #include "libpldmresponder/platform.hpp" 10 #include "requester/handler.hpp" 11 12 typedef ibm_oem_pldm_state_set_firmware_update_state_values CodeUpdateState; 13 14 namespace pldm 15 { 16 namespace responder 17 { 18 namespace oem_ibm_platform 19 { 20 static constexpr auto PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE = 24577; 21 constexpr uint16_t ENTITY_INSTANCE_0 = 0; 22 constexpr uint16_t ENTITY_INSTANCE_1 = 1; 23 24 enum SetEventReceiverCount 25 { 26 SET_EVENT_RECEIVER_SENT = 0x2, 27 }; 28 29 class Handler : public oem_platform::Handler 30 { 31 public: 32 Handler(const pldm::utils::DBusHandler* dBusIntf, 33 pldm::responder::CodeUpdate* codeUpdate, int mctp_fd, 34 uint8_t mctp_eid, pldm::dbus_api::Requester& requester, 35 sdeventplus::Event& event, 36 pldm::requester::Handler<pldm::requester::Request>* handler) : 37 oem_platform::Handler(dBusIntf), 38 codeUpdate(codeUpdate), platformHandler(nullptr), mctp_fd(mctp_fd), 39 mctp_eid(mctp_eid), requester(requester), event(event), handler(handler) 40 { 41 codeUpdate->setVersions(); 42 setEventReceiverCnt = 0; 43 44 using namespace sdbusplus::bus::match::rules; 45 hostOffMatch = std::make_unique<sdbusplus::bus::match::match>( 46 pldm::utils::DBusHandler::getBus(), 47 propertiesChanged("/xyz/openbmc_project/state/host0", 48 "xyz.openbmc_project.State.Host"), 49 [this](sdbusplus::message::message& msg) { 50 pldm::utils::DbusChangedProps props{}; 51 std::string intf; 52 msg.read(intf, props); 53 const auto itr = props.find("CurrentHostState"); 54 if (itr != props.end()) 55 { 56 pldm::utils::PropertyValue value = itr->second; 57 auto propVal = std::get<std::string>(value); 58 if (propVal == 59 "xyz.openbmc_project.State.Host.HostState.Off") 60 { 61 hostOff = true; 62 setEventReceiverCnt = 0; 63 disableWatchDogTimer(); 64 } 65 else if (propVal == 66 "xyz.openbmc_project.State.Host.HostState.Running") 67 { 68 hostOff = false; 69 } 70 } 71 }); 72 } 73 74 int getOemStateSensorReadingsHandler( 75 EntityType entityType, pldm::pdr::EntityInstance entityInstance, 76 pldm::pdr::StateSetId stateSetId, 77 pldm::pdr::CompositeCount compSensorCnt, 78 std::vector<get_sensor_state_field>& stateField); 79 80 int oemSetStateEffecterStatesHandler( 81 uint16_t entityType, uint16_t entityInstance, uint16_t stateSetId, 82 uint8_t compEffecterCnt, 83 std::vector<set_effecter_state_field>& stateField, uint16_t effecterId); 84 85 /** @brief Method to set the platform handler in the 86 * oem_ibm_handler class 87 * @param[in] handler - pointer to PLDM platform handler 88 */ 89 void setPlatformHandler(pldm::responder::platform::Handler* handler); 90 91 /** @brief Method to fetch the effecter ID of the code update PDRs 92 * 93 * @return platformHandler->getNextEffecterId() - returns the 94 * effecter ID from the platform handler 95 */ 96 virtual uint16_t getNextEffecterId() 97 { 98 return platformHandler->getNextEffecterId(); 99 } 100 101 /** @brief Method to fetch the sensor ID of the code update PDRs 102 * 103 * @return platformHandler->getNextSensorId() - returns the 104 * Sensor ID from the platform handler 105 */ 106 virtual uint16_t getNextSensorId() 107 { 108 return platformHandler->getNextSensorId(); 109 } 110 111 /** @brief Method to Generate the OEM PDRs 112 * 113 * @param[in] repo - instance of concrete implementation of Repo 114 */ 115 void buildOEMPDR(pdr_utils::Repo& repo); 116 117 /** @brief Method to send code update event to host 118 * @param[in] sensorId - sendor ID 119 * @param[in] sensorEventClass - event class of sensor 120 * @param[in] sensorOffset - sensor offset 121 * @param[in] eventState - new code update event state 122 * @param[in] prevEventState - previous code update event state 123 * @return none 124 */ 125 void sendStateSensorEvent(uint16_t sensorId, 126 enum sensor_event_class_states sensorEventClass, 127 uint8_t sensorOffset, uint8_t eventState, 128 uint8_t prevEventState); 129 130 /** @brief Method to send encoded request msg of code update event to host 131 * @param[in] requestMsg - encoded request msg 132 * @param[in] instanceId - instance id of the message 133 * @return PLDM status code 134 */ 135 int sendEventToHost(std::vector<uint8_t>& requestMsg, uint8_t instanceId); 136 137 /** @brief _processEndUpdate processes the actual work that needs 138 * to be carried out after EndUpdate effecter is set. This is done async 139 * after sending response for EndUpdate set effecter 140 * @param[in] source - sdeventplus event source 141 */ 142 void _processEndUpdate(sdeventplus::source::EventBase& source); 143 144 /** @brief _processStartUpdate processes the actual work that needs 145 * to be carried out after StartUpdate effecter is set. This is done async 146 * after sending response for StartUpdate set effecter 147 * @param[in] source - sdeventplus event source 148 */ 149 void _processStartUpdate(sdeventplus::source::EventBase& source); 150 151 /** @brief _processSystemReboot processes the actual work that needs to be 152 * carried out after the System Power State effecter is set to reboot 153 * the system 154 * @param[in] source - sdeventplus event source 155 */ 156 void _processSystemReboot(sdeventplus::source::EventBase& source); 157 158 /*keeps track how many times setEventReceiver is sent */ 159 void countSetEventReceiver() 160 { 161 setEventReceiverCnt++; 162 } 163 164 /* disables watchdog if running and Host is up */ 165 void checkAndDisableWatchDog(); 166 167 /** @brief To check if the watchdog app is running 168 * 169 * @return the running status of watchdog app 170 */ 171 bool watchDogRunning(); 172 173 /** @brief Method to reset the Watchdog timer on receiving platform Event 174 * Message for heartbeat elapsed time from Hostboot 175 */ 176 void resetWatchDogTimer(); 177 178 /** @brief To disable to the watchdog timer on host poweron completion*/ 179 void disableWatchDogTimer(); 180 181 /** @brief to check the BMC state*/ 182 int checkBMCState(); 183 184 ~Handler() = default; 185 186 pldm::responder::CodeUpdate* codeUpdate; //!< pointer to CodeUpdate object 187 pldm::responder::platform::Handler* 188 platformHandler; //!< pointer to PLDM platform handler 189 190 /** @brief fd of MCTP communications socket */ 191 int mctp_fd; 192 193 /** @brief MCTP EID of host firmware */ 194 uint8_t mctp_eid; 195 196 /** @brief reference to Requester object, primarily used to access API to 197 * obtain PLDM instance id. 198 */ 199 pldm::dbus_api::Requester& requester; 200 /** @brief sdeventplus event source */ 201 std::unique_ptr<sdeventplus::source::Defer> assembleImageEvent; 202 std::unique_ptr<sdeventplus::source::Defer> startUpdateEvent; 203 std::unique_ptr<sdeventplus::source::Defer> systemRebootEvent; 204 205 /** @brief reference of main event loop of pldmd, primarily used to schedule 206 * work 207 */ 208 sdeventplus::Event& event; 209 210 private: 211 /** @brief D-Bus property changed signal match for CurrentPowerState*/ 212 std::unique_ptr<sdbusplus::bus::match::match> chassisOffMatch; 213 214 /** @brief PLDM request handler */ 215 pldm::requester::Handler<pldm::requester::Request>* handler; 216 217 /** @brief D-Bus property changed signal match */ 218 std::unique_ptr<sdbusplus::bus::match::match> hostOffMatch; 219 220 bool hostOff = true; 221 222 int setEventReceiverCnt = 0; 223 }; 224 225 /** @brief Method to encode code update event msg 226 * @param[in] eventType - type of event 227 * @param[in] eventDataVec - vector of event data to be sent to host 228 * @param[in/out] requestMsg - request msg to be encoded 229 * @param[in] instanceId - instance ID 230 * @return PLDM status code 231 */ 232 int encodeEventMsg(uint8_t eventType, const std::vector<uint8_t>& eventDataVec, 233 std::vector<uint8_t>& requestMsg, uint8_t instanceId); 234 235 } // namespace oem_ibm_platform 236 237 } // namespace responder 238 239 } // namespace pldm 240