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