1 #pragma once 2 3 #include "inband_code_update.hpp" 4 #include "libpldmresponder/oem_handler.hpp" 5 #include "libpldmresponder/pdr_utils.hpp" 6 #include "libpldmresponder/platform.hpp" 7 #include "requester/handler.hpp" 8 9 #include <libpldm/entity.h> 10 #include <libpldm/oem/ibm/state_set.h> 11 #include <libpldm/platform.h> 12 13 #include <sdbusplus/bus/match.hpp> 14 #include <sdeventplus/event.hpp> 15 #include <sdeventplus/utility/timer.hpp> 16 17 typedef ibm_oem_pldm_state_set_firmware_update_state_values CodeUpdateState; 18 19 namespace pldm 20 { 21 namespace responder 22 { 23 namespace oem_ibm_platform 24 { 25 constexpr uint16_t ENTITY_INSTANCE_0 = 0; 26 constexpr uint16_t ENTITY_INSTANCE_1 = 1; 27 28 constexpr uint32_t BMC_PDR_START_RANGE = 0x00000000; 29 constexpr uint32_t BMC_PDR_END_RANGE = 0x00FFFFFF; 30 constexpr uint32_t HOST_PDR_START_RANGE = 0x01000000; 31 constexpr uint32_t HOST_PDR_END_RANGE = 0x01FFFFFF; 32 33 const pldm::pdr::TerminusID HYPERVISOR_TID = 208; 34 35 static constexpr uint8_t HEARTBEAT_TIMEOUT_DELTA = 10; 36 37 enum SetEventReceiverCount 38 { 39 SET_EVENT_RECEIVER_SENT = 0x2, 40 }; 41 42 class Handler : public oem_platform::Handler 43 { 44 public: 45 Handler(const pldm::utils::DBusHandler* dBusIntf, 46 pldm::responder::CodeUpdate* codeUpdate, int mctp_fd, 47 uint8_t mctp_eid, pldm::InstanceIdDb& instanceIdDb, 48 sdeventplus::Event& event, 49 pldm::requester::Handler<pldm::requester::Request>* handler) : 50 oem_platform::Handler(dBusIntf), 51 codeUpdate(codeUpdate), platformHandler(nullptr), mctp_fd(mctp_fd), 52 mctp_eid(mctp_eid), instanceIdDb(instanceIdDb), event(event), 53 handler(handler), 54 timer(event, std::bind(std::mem_fn(&Handler::setSurvTimer), this, 55 HYPERVISOR_TID, false)), 56 hostTransitioningToOff(true) 57 { 58 codeUpdate->setVersions(); 59 setEventReceiverCnt = 0; 60 61 using namespace sdbusplus::bus::match::rules; 62 hostOffMatch = std::make_unique<sdbusplus::bus::match_t>( 63 pldm::utils::DBusHandler::getBus(), 64 propertiesChanged("/xyz/openbmc_project/state/host0", 65 "xyz.openbmc_project.State.Host"), 66 [this](sdbusplus::message_t& msg) { 67 pldm::utils::DbusChangedProps props{}; 68 std::string intf; 69 msg.read(intf, props); 70 const auto itr = props.find("CurrentHostState"); 71 if (itr != props.end()) 72 { 73 pldm::utils::PropertyValue value = itr->second; 74 auto propVal = std::get<std::string>(value); 75 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off") 76 { 77 hostOff = true; 78 setEventReceiverCnt = 0; 79 disableWatchDogTimer(); 80 startStopTimer(false); 81 } 82 else if (propVal == 83 "xyz.openbmc_project.State.Host.HostState.Running") 84 { 85 hostOff = false; 86 hostTransitioningToOff = false; 87 } 88 else if ( 89 propVal == 90 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff") 91 { 92 hostTransitioningToOff = true; 93 } 94 } 95 }); 96 } 97 98 int getOemStateSensorReadingsHandler( 99 EntityType entityType, pldm::pdr::EntityInstance entityInstance, 100 pldm::pdr::StateSetId stateSetId, 101 pldm::pdr::CompositeCount compSensorCnt, 102 std::vector<get_sensor_state_field>& stateField); 103 104 int oemSetStateEffecterStatesHandler( 105 uint16_t entityType, uint16_t entityInstance, uint16_t stateSetId, 106 uint8_t compEffecterCnt, 107 std::vector<set_effecter_state_field>& stateField, uint16_t effecterId); 108 109 /** @brief Method to set the platform handler in the 110 * oem_ibm_handler class 111 * @param[in] handler - pointer to PLDM platform handler 112 */ 113 void setPlatformHandler(pldm::responder::platform::Handler* handler); 114 115 /** @brief Method to fetch the effecter ID of the code update PDRs 116 * 117 * @return platformHandler->getNextEffecterId() - returns the 118 * effecter ID from the platform handler 119 */ 120 virtual uint16_t getNextEffecterId() 121 { 122 return platformHandler->getNextEffecterId(); 123 } 124 125 /** @brief Method to fetch the sensor ID of the code update PDRs 126 * 127 * @return platformHandler->getNextSensorId() - returns the 128 * Sensor ID from the platform handler 129 */ 130 virtual uint16_t getNextSensorId() 131 { 132 return platformHandler->getNextSensorId(); 133 } 134 135 /** @brief Method to Generate the OEM PDRs 136 * 137 * @param[in] repo - instance of concrete implementation of Repo 138 */ 139 void buildOEMPDR(pdr_utils::Repo& repo); 140 141 /** @brief Method to send code update event to host 142 * @param[in] sensorId - sendor ID 143 * @param[in] sensorEventClass - event class of sensor 144 * @param[in] sensorOffset - sensor offset 145 * @param[in] eventState - new code update event state 146 * @param[in] prevEventState - previous code update event state 147 * @return none 148 */ 149 void sendStateSensorEvent(uint16_t sensorId, 150 enum sensor_event_class_states sensorEventClass, 151 uint8_t sensorOffset, uint8_t eventState, 152 uint8_t prevEventState); 153 154 /** @brief Method to send encoded request msg of code update event to host 155 * @param[in] requestMsg - encoded request msg 156 * @param[in] instanceId - instance id of the message 157 * @return PLDM status code 158 */ 159 int sendEventToHost(std::vector<uint8_t>& requestMsg, uint8_t instanceId); 160 161 /** @brief _processEndUpdate processes the actual work that needs 162 * to be carried out after EndUpdate effecter is set. This is done async 163 * after sending response for EndUpdate set effecter 164 * @param[in] source - sdeventplus event source 165 */ 166 void _processEndUpdate(sdeventplus::source::EventBase& source); 167 168 /** @brief _processStartUpdate processes the actual work that needs 169 * to be carried out after StartUpdate effecter is set. This is done async 170 * after sending response for StartUpdate set effecter 171 * @param[in] source - sdeventplus event source 172 */ 173 void _processStartUpdate(sdeventplus::source::EventBase& source); 174 175 /** @brief _processSystemReboot processes the actual work that needs to be 176 * carried out after the System Power State effecter is set to reboot 177 * the system 178 * @param[in] source - sdeventplus event source 179 */ 180 void _processSystemReboot(sdeventplus::source::EventBase& source); 181 182 /*keeps track how many times setEventReceiver is sent */ 183 void countSetEventReceiver() 184 { 185 setEventReceiverCnt++; 186 } 187 188 /* disables watchdog if running and Host is up */ 189 void checkAndDisableWatchDog(); 190 191 /** @brief To check if the watchdog app is running 192 * 193 * @return the running status of watchdog app 194 */ 195 bool watchDogRunning(); 196 197 /** @brief Method to reset the Watchdog timer on receiving platform Event 198 * Message for heartbeat elapsed time from Hostboot 199 */ 200 void resetWatchDogTimer(); 201 202 /** @brief To disable to the watchdog timer on host poweron completion*/ 203 void disableWatchDogTimer(); 204 205 /** @brief to check the BMC state*/ 206 int checkBMCState(); 207 208 /** @brief update the dbus object paths */ 209 void updateOemDbusPaths(std::string& dbusPath); 210 211 /** @brief Method to fetch the last BMC record from the PDR repo 212 * 213 * @param[in] repo - pointer to BMC's primary PDR repo 214 * 215 * @return the last BMC record from the repo 216 */ 217 const pldm_pdr_record* fetchLastBMCRecord(const pldm_pdr* repo); 218 219 /** @brief Method to check if the record handle passed is in remote PDR 220 * record handle range 221 * 222 * @param[in] record_handle - record handle of the PDR 223 * 224 * @return true if record handle passed is in host PDR record handle range 225 */ 226 bool checkRecordHandleInRange(const uint32_t& record_handle); 227 228 /** *brief Method to call the setEventReceiver command*/ 229 void processSetEventReceiver(); 230 231 /** @brief Method to call the setEventReceiver through the platform 232 * handler 233 */ 234 virtual void setEventReceiver() 235 { 236 platformHandler->setEventReceiver(); 237 } 238 239 /** @brief Method to Enable/Disable timer to see if remote terminus sends 240 * the surveillance ping and logs informational error if remote terminus 241 * fails to send the surveillance pings 242 * 243 * @param[in] tid - TID of the remote terminus 244 * @param[in] value - true or false, to indicate if the timer is 245 * running or not 246 */ 247 void setSurvTimer(uint8_t tid, bool value); 248 249 ~Handler() = default; 250 251 pldm::responder::CodeUpdate* codeUpdate; //!< pointer to CodeUpdate object 252 pldm::responder::platform::Handler* 253 platformHandler; //!< pointer to PLDM platform handler 254 255 /** @brief fd of MCTP communications socket */ 256 int mctp_fd; 257 258 /** @brief MCTP EID of host firmware */ 259 uint8_t mctp_eid; 260 261 /** @brief reference to an InstanceIdDb object, used to obtain a PLDM 262 * instance id. */ 263 pldm::InstanceIdDb& instanceIdDb; 264 /** @brief sdeventplus event source */ 265 std::unique_ptr<sdeventplus::source::Defer> assembleImageEvent; 266 std::unique_ptr<sdeventplus::source::Defer> startUpdateEvent; 267 std::unique_ptr<sdeventplus::source::Defer> systemRebootEvent; 268 269 /** @brief reference of main event loop of pldmd, primarily used to schedule 270 * work 271 */ 272 sdeventplus::Event& event; 273 274 private: 275 /** @brief Method to reset or stop the surveillance timer 276 * 277 * @param[in] value - true or false, to indicate if the timer 278 * should be reset or turned off 279 */ 280 void startStopTimer(bool value); 281 282 /** @brief D-Bus property changed signal match for CurrentPowerState*/ 283 std::unique_ptr<sdbusplus::bus::match_t> chassisOffMatch; 284 285 /** @brief PLDM request handler */ 286 pldm::requester::Handler<pldm::requester::Request>* handler; 287 288 /** @brief D-Bus property changed signal match */ 289 std::unique_ptr<sdbusplus::bus::match_t> hostOffMatch; 290 291 /** @brief Timer used for monitoring surveillance pings from host */ 292 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer; 293 294 bool hostOff = true; 295 296 bool hostTransitioningToOff; 297 298 int setEventReceiverCnt = 0; 299 }; 300 301 /** @brief Method to encode code update event msg 302 * @param[in] eventType - type of event 303 * @param[in] eventDataVec - vector of event data to be sent to host 304 * @param[in/out] requestMsg - request msg to be encoded 305 * @param[in] instanceId - instance ID 306 * @return PLDM status code 307 */ 308 int encodeEventMsg(uint8_t eventType, const std::vector<uint8_t>& eventDataVec, 309 std::vector<uint8_t>& requestMsg, uint8_t instanceId); 310 311 } // namespace oem_ibm_platform 312 313 } // namespace responder 314 315 } // namespace pldm 316