1 #include "oem_ibm_handler.hpp"
2
3 #include "file_io_type_lid.hpp"
4 #include "libpldmresponder/file_io.hpp"
5 #include "libpldmresponder/pdr_utils.hpp"
6
7 #include <libpldm/entity.h>
8 #include <libpldm/oem/ibm/entity.h>
9
10 #include <phosphor-logging/lg2.hpp>
11 #include <xyz/openbmc_project/State/BMC/client.hpp>
12
13 PHOSPHOR_LOG2_USING;
14
15 using namespace pldm::pdr;
16 using namespace pldm::utils;
17
18 namespace pldm
19 {
20 namespace responder
21 {
22 namespace oem_ibm_platform
23 {
24 int pldm::responder::oem_ibm_platform::Handler::
getOemStateSensorReadingsHandler(pldm::pdr::EntityType entityType,EntityInstance entityInstance,StateSetId stateSetId,CompositeCount compSensorCnt,std::vector<get_sensor_state_field> & stateField)25 getOemStateSensorReadingsHandler(
26 pldm::pdr::EntityType entityType, EntityInstance entityInstance,
27 StateSetId stateSetId, CompositeCount compSensorCnt,
28 std::vector<get_sensor_state_field>& stateField)
29 {
30 int rc = PLDM_SUCCESS;
31 stateField.clear();
32
33 for (size_t i = 0; i < compSensorCnt; i++)
34 {
35 uint8_t sensorOpState{};
36 if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE &&
37 stateSetId == PLDM_OEM_IBM_BOOT_STATE)
38 {
39 sensorOpState = fetchBootSide(entityInstance, codeUpdate);
40 }
41 else
42 {
43 rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
44 break;
45 }
46 stateField.push_back({PLDM_SENSOR_ENABLED, PLDM_SENSOR_UNKNOWN,
47 PLDM_SENSOR_UNKNOWN, sensorOpState});
48 }
49 return rc;
50 }
51
52 int pldm::responder::oem_ibm_platform::Handler::
oemSetStateEffecterStatesHandler(uint16_t entityType,uint16_t entityInstance,uint16_t stateSetId,uint8_t compEffecterCnt,std::vector<set_effecter_state_field> & stateField,uint16_t)53 oemSetStateEffecterStatesHandler(
54 uint16_t entityType, uint16_t entityInstance, uint16_t stateSetId,
55 uint8_t compEffecterCnt,
56 std::vector<set_effecter_state_field>& stateField,
57 uint16_t /*effecterId*/)
58 {
59 int rc = PLDM_SUCCESS;
60
61 for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
62 {
63 if (stateField[currState].set_request == PLDM_REQUEST_SET)
64 {
65 if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE &&
66 stateSetId == PLDM_OEM_IBM_BOOT_STATE)
67 {
68 rc = setBootSide(entityInstance, currState, stateField,
69 codeUpdate);
70 }
71 else if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE &&
72 stateSetId == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
73 {
74 if (stateField[currState].effecter_state ==
75 uint8_t(CodeUpdateState::START))
76 {
77 codeUpdate->setCodeUpdateProgress(true);
78 startUpdateEvent =
79 std::make_unique<sdeventplus::source::Defer>(
80 event,
81 std::bind(std::mem_fn(&oem_ibm_platform::Handler::
82 _processStartUpdate),
83 this, std::placeholders::_1));
84 }
85 else if (stateField[currState].effecter_state ==
86 uint8_t(CodeUpdateState::END))
87 {
88 rc = PLDM_SUCCESS;
89 assembleImageEvent = std::make_unique<
90 sdeventplus::source::Defer>(
91 event,
92 std::bind(
93 std::mem_fn(
94 &oem_ibm_platform::Handler::_processEndUpdate),
95 this, std::placeholders::_1));
96
97 // sendCodeUpdateEvent(effecterId, END, START);
98 }
99 else if (stateField[currState].effecter_state ==
100 uint8_t(CodeUpdateState::ABORT))
101 {
102 codeUpdate->setCodeUpdateProgress(false);
103 codeUpdate->clearDirPath(LID_STAGING_DIR);
104 auto sensorId = codeUpdate->getFirmwareUpdateSensor();
105 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
106 uint8_t(CodeUpdateState::ABORT),
107 uint8_t(CodeUpdateState::START));
108 // sendCodeUpdateEvent(effecterId, ABORT, END);
109 }
110 else if (stateField[currState].effecter_state ==
111 uint8_t(CodeUpdateState::ACCEPT))
112 {
113 auto sensorId = codeUpdate->getFirmwareUpdateSensor();
114 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
115 uint8_t(CodeUpdateState::ACCEPT),
116 uint8_t(CodeUpdateState::END));
117 // TODO Set new Dbus property provided by code update app
118 // sendCodeUpdateEvent(effecterId, ACCEPT, END);
119 }
120 else if (stateField[currState].effecter_state ==
121 uint8_t(CodeUpdateState::REJECT))
122 {
123 auto sensorId = codeUpdate->getFirmwareUpdateSensor();
124 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
125 uint8_t(CodeUpdateState::REJECT),
126 uint8_t(CodeUpdateState::END));
127 // TODO Set new Dbus property provided by code update app
128 // sendCodeUpdateEvent(effecterId, REJECT, END);
129 }
130 }
131 else if (entityType == PLDM_ENTITY_SYSTEM_CHASSIS &&
132 stateSetId == PLDM_OEM_IBM_SYSTEM_POWER_STATE)
133 {
134 if (stateField[currState].effecter_state == POWER_CYCLE_HARD)
135 {
136 systemRebootEvent =
137 std::make_unique<sdeventplus::source::Defer>(
138 event,
139 std::bind(std::mem_fn(&oem_ibm_platform::Handler::
140 _processSystemReboot),
141 this, std::placeholders::_1));
142 }
143 }
144 else
145 {
146 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
147 }
148 }
149 if (rc != PLDM_SUCCESS)
150 {
151 break;
152 }
153 }
154 return rc;
155 }
156
buildAllCodeUpdateEffecterPDR(oem_ibm_platform::Handler * platformHandler,uint16_t entityType,uint16_t entityInstance,uint16_t stateSetID,pdr_utils::Repo & repo)157 void buildAllCodeUpdateEffecterPDR(oem_ibm_platform::Handler* platformHandler,
158 uint16_t entityType, uint16_t entityInstance,
159 uint16_t stateSetID, pdr_utils::Repo& repo)
160 {
161 size_t pdrSize = 0;
162 pdrSize = sizeof(pldm_state_effecter_pdr) +
163 sizeof(state_effecter_possible_states);
164 std::vector<uint8_t> entry{};
165 entry.resize(pdrSize);
166 pldm_state_effecter_pdr* pdr =
167 reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
168 if (!pdr)
169 {
170 error("Failed to get record by PDR type, error - {ERROR}", "ERROR",
171 lg2::hex,
172 static_cast<unsigned>(PLDM_PLATFORM_INVALID_EFFECTER_ID));
173 return;
174 }
175 pdr->hdr.record_handle = 0;
176 pdr->hdr.version = 1;
177 pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
178 pdr->hdr.record_change_num = 0;
179 pdr->hdr.length = sizeof(pldm_state_effecter_pdr) - sizeof(pldm_pdr_hdr);
180 pdr->terminus_handle = TERMINUS_HANDLE;
181 pdr->effecter_id = platformHandler->getNextEffecterId();
182 pdr->entity_type = entityType;
183 pdr->entity_instance = entityInstance;
184 pdr->container_id = 1;
185 pdr->effecter_semantic_id = 0;
186 pdr->effecter_init = PLDM_NO_INIT;
187 pdr->has_description_pdr = false;
188 pdr->composite_effecter_count = 1;
189
190 auto* possibleStatesPtr = pdr->possible_states;
191 auto possibleStates =
192 reinterpret_cast<state_effecter_possible_states*>(possibleStatesPtr);
193 possibleStates->state_set_id = stateSetID;
194 possibleStates->possible_states_size = 2;
195 auto state =
196 reinterpret_cast<state_effecter_possible_states*>(possibleStates);
197 if (stateSetID == PLDM_OEM_IBM_BOOT_STATE)
198 state->states[0].byte = 6;
199 else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
200 state->states[0].byte = 126;
201 else if (stateSetID == PLDM_OEM_IBM_SYSTEM_POWER_STATE)
202 state->states[0].byte = 2;
203 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
204 pdrEntry.data = entry.data();
205 pdrEntry.size = pdrSize;
206 repo.addRecord(pdrEntry);
207 }
208
buildAllCodeUpdateSensorPDR(oem_ibm_platform::Handler * platformHandler,uint16_t entityType,uint16_t entityInstance,uint16_t stateSetID,pdr_utils::Repo & repo)209 void buildAllCodeUpdateSensorPDR(oem_ibm_platform::Handler* platformHandler,
210 uint16_t entityType, uint16_t entityInstance,
211 uint16_t stateSetID, pdr_utils::Repo& repo)
212 {
213 size_t pdrSize = 0;
214 pdrSize = sizeof(pldm_state_sensor_pdr) +
215 sizeof(state_sensor_possible_states);
216 std::vector<uint8_t> entry{};
217 entry.resize(pdrSize);
218 pldm_state_sensor_pdr* pdr =
219 reinterpret_cast<pldm_state_sensor_pdr*>(entry.data());
220 if (!pdr)
221 {
222 error("Failed to get record by PDR type, error - {ERROR}", "ERROR",
223 lg2::hex, static_cast<unsigned>(PLDM_PLATFORM_INVALID_SENSOR_ID));
224 return;
225 }
226 pdr->hdr.record_handle = 0;
227 pdr->hdr.version = 1;
228 pdr->hdr.type = PLDM_STATE_SENSOR_PDR;
229 pdr->hdr.record_change_num = 0;
230 pdr->hdr.length = sizeof(pldm_state_sensor_pdr) - sizeof(pldm_pdr_hdr);
231 pdr->terminus_handle = TERMINUS_HANDLE;
232 pdr->sensor_id = platformHandler->getNextSensorId();
233 pdr->entity_type = entityType;
234 pdr->entity_instance = entityInstance;
235 pdr->container_id = 1;
236 pdr->sensor_init = PLDM_NO_INIT;
237 pdr->sensor_auxiliary_names_pdr = false;
238 pdr->composite_sensor_count = 1;
239
240 auto* possibleStatesPtr = pdr->possible_states;
241 auto possibleStates =
242 reinterpret_cast<state_sensor_possible_states*>(possibleStatesPtr);
243 possibleStates->state_set_id = stateSetID;
244 possibleStates->possible_states_size = 2;
245 auto state =
246 reinterpret_cast<state_sensor_possible_states*>(possibleStates);
247 if ((stateSetID == PLDM_OEM_IBM_BOOT_STATE) ||
248 (stateSetID == PLDM_OEM_IBM_VERIFICATION_STATE))
249 state->states[0].byte = 6;
250 else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
251 state->states[0].byte = 126;
252 pldm::responder::pdr_utils::PdrEntry pdrEntry{};
253 pdrEntry.data = entry.data();
254 pdrEntry.size = pdrSize;
255 repo.addRecord(pdrEntry);
256 }
257
buildOEMPDR(pdr_utils::Repo & repo)258 void pldm::responder::oem_ibm_platform::Handler::buildOEMPDR(
259 pdr_utils::Repo& repo)
260 {
261 buildAllCodeUpdateEffecterPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
262 ENTITY_INSTANCE_0, PLDM_OEM_IBM_BOOT_STATE,
263 repo);
264 buildAllCodeUpdateEffecterPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
265 ENTITY_INSTANCE_1, PLDM_OEM_IBM_BOOT_STATE,
266 repo);
267 buildAllCodeUpdateEffecterPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
268 ENTITY_INSTANCE_0,
269 PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
270 buildAllCodeUpdateEffecterPDR(this, PLDM_ENTITY_SYSTEM_CHASSIS,
271 ENTITY_INSTANCE_1,
272 PLDM_OEM_IBM_SYSTEM_POWER_STATE, repo);
273
274 buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
275 ENTITY_INSTANCE_0, PLDM_OEM_IBM_BOOT_STATE,
276 repo);
277 buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
278 ENTITY_INSTANCE_1, PLDM_OEM_IBM_BOOT_STATE,
279 repo);
280 buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
281 ENTITY_INSTANCE_0,
282 PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
283 buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
284 ENTITY_INSTANCE_0,
285 PLDM_OEM_IBM_VERIFICATION_STATE, repo);
286 auto sensorId = findStateSensorId(
287 repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
288 ENTITY_INSTANCE_0, 1, PLDM_OEM_IBM_VERIFICATION_STATE);
289 codeUpdate->setMarkerLidSensor(sensorId);
290 sensorId = findStateSensorId(
291 repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
292 ENTITY_INSTANCE_0, 1, PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE);
293 codeUpdate->setFirmwareUpdateSensor(sensorId);
294 }
295
setPlatformHandler(pldm::responder::platform::Handler * handler)296 void pldm::responder::oem_ibm_platform::Handler::setPlatformHandler(
297 pldm::responder::platform::Handler* handler)
298 {
299 platformHandler = handler;
300 }
301
sendEventToHost(std::vector<uint8_t> & requestMsg,uint8_t instanceId)302 int pldm::responder::oem_ibm_platform::Handler::sendEventToHost(
303 std::vector<uint8_t>& requestMsg, uint8_t instanceId)
304 {
305 if (requestMsg.size())
306 {
307 std::ostringstream tempStream;
308 for (int byte : requestMsg)
309 {
310 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
311 << " ";
312 }
313 std::cout << tempStream.str() << std::endl;
314 }
315 auto oemPlatformEventMessageResponseHandler =
316 [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) {
317 uint8_t completionCode{};
318 uint8_t status{};
319 auto rc = decode_platform_event_message_resp(response, respMsgLen,
320 &completionCode, &status);
321 if (rc || completionCode)
322 {
323 error(
324 "Failed to decode platform event message response for code update event with response code '{RC}' and completion code '{CC}'",
325 "RC", rc, "CC", completionCode);
326 }
327 };
328 auto rc = handler->registerRequest(
329 mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
330 std::move(requestMsg),
331 std::move(oemPlatformEventMessageResponseHandler));
332 if (rc)
333 {
334 error("Failed to send BIOS attribute change event message ");
335 }
336
337 return rc;
338 }
339
encodeEventMsg(uint8_t eventType,const std::vector<uint8_t> & eventDataVec,std::vector<uint8_t> & requestMsg,uint8_t instanceId)340 int encodeEventMsg(uint8_t eventType, const std::vector<uint8_t>& eventDataVec,
341 std::vector<uint8_t>& requestMsg, uint8_t instanceId)
342 {
343 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
344
345 auto rc = encode_platform_event_message_req(
346 instanceId, 1 /*formatVersion*/, TERMINUS_ID /*tId*/, eventType,
347 eventDataVec.data(), eventDataVec.size(), request,
348 eventDataVec.size() + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
349
350 return rc;
351 }
352
sendStateSensorEvent(uint16_t sensorId,enum sensor_event_class_states sensorEventClass,uint8_t sensorOffset,uint8_t eventState,uint8_t prevEventState)353 void pldm::responder::oem_ibm_platform::Handler::sendStateSensorEvent(
354 uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
355 uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
356 {
357 std::vector<uint8_t> sensorEventDataVec{};
358 size_t sensorEventSize = PLDM_SENSOR_EVENT_DATA_MIN_LENGTH + 1;
359 sensorEventDataVec.resize(sensorEventSize);
360 auto eventData = reinterpret_cast<struct pldm_sensor_event_data*>(
361 sensorEventDataVec.data());
362 eventData->sensor_id = sensorId;
363 eventData->sensor_event_class_type = sensorEventClass;
364 auto eventClassStart = eventData->event_class;
365 auto eventClass =
366 reinterpret_cast<struct pldm_sensor_event_state_sensor_state*>(
367 eventClassStart);
368 eventClass->sensor_offset = sensorOffset;
369 eventClass->event_state = eventState;
370 eventClass->previous_event_state = prevEventState;
371 auto instanceId = instanceIdDb.next(mctp_eid);
372 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
373 PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
374 sensorEventDataVec.size());
375 auto rc = encodeEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec, requestMsg,
376 instanceId);
377 if (rc != PLDM_SUCCESS)
378 {
379 error("Failed to encode state sensor event with response code '{RC}'",
380 "RC", rc);
381 instanceIdDb.free(mctp_eid, instanceId);
382 return;
383 }
384 rc = sendEventToHost(requestMsg, instanceId);
385 if (rc != PLDM_SUCCESS)
386 {
387 error(
388 "Failed to send event to remote terminus with response code '{RC}'",
389 "RC", rc);
390 }
391 return;
392 }
393
_processEndUpdate(sdeventplus::source::EventBase &)394 void pldm::responder::oem_ibm_platform::Handler::_processEndUpdate(
395 sdeventplus::source::EventBase& /*source */)
396 {
397 assembleImageEvent.reset();
398 int retc = codeUpdate->assembleCodeUpdateImage();
399 if (retc != PLDM_SUCCESS)
400 {
401 codeUpdate->setCodeUpdateProgress(false);
402 auto sensorId = codeUpdate->getFirmwareUpdateSensor();
403 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
404 uint8_t(CodeUpdateState::FAIL),
405 uint8_t(CodeUpdateState::START));
406 }
407 }
408
_processStartUpdate(sdeventplus::source::EventBase &)409 void pldm::responder::oem_ibm_platform::Handler::_processStartUpdate(
410 sdeventplus::source::EventBase& /*source */)
411 {
412 codeUpdate->deleteImage();
413 CodeUpdateState state = CodeUpdateState::START;
414 auto rc = codeUpdate->setRequestedApplyTime();
415 if (rc != PLDM_SUCCESS)
416 {
417 error("setRequestedApplyTime failed");
418 state = CodeUpdateState::FAIL;
419 }
420 auto sensorId = codeUpdate->getFirmwareUpdateSensor();
421 sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, uint8_t(state),
422 uint8_t(CodeUpdateState::END));
423 }
424
updateOemDbusPaths(std::string & dbusPath)425 void pldm::responder::oem_ibm_platform::Handler::updateOemDbusPaths(
426 std::string& dbusPath)
427 {
428 std::string toFind("system1/chassis1/motherboard1");
429 if (dbusPath.find(toFind) != std::string::npos)
430 {
431 size_t pos = dbusPath.find(toFind);
432 dbusPath.replace(pos, toFind.length(), "system/chassis/motherboard");
433 }
434 toFind = "system1";
435 if (dbusPath.find(toFind) != std::string::npos)
436 {
437 size_t pos = dbusPath.find(toFind);
438 dbusPath.replace(pos, toFind.length(), "system");
439 }
440 /* below logic to replace path 'motherboard/socket/chassis' to
441 'motherboard/chassis' or 'motherboard/socket123/chassis' to
442 'motherboard/chassis' */
443 toFind = "socket";
444 size_t pos1 = dbusPath.find(toFind);
445 // while loop to detect multiple substring 'socket' in the path
446 while (pos1 != std::string::npos)
447 {
448 size_t pos2 = dbusPath.substr(pos1 + 1).find('/') + 1;
449 // Replacing starting from substring to next occurrence of char '/'
450 dbusPath.replace(pos1, pos2 + 1, "");
451 pos1 = dbusPath.find(toFind);
452 }
453 }
454
_processSystemReboot(sdeventplus::source::EventBase &)455 void pldm::responder::oem_ibm_platform::Handler::_processSystemReboot(
456 sdeventplus::source::EventBase& /*source */)
457 {
458 pldm::utils::PropertyValue value =
459 "xyz.openbmc_project.State.Chassis.Transition.Off";
460 pldm::utils::DBusMapping dbusMapping{"/xyz/openbmc_project/state/chassis0",
461 "xyz.openbmc_project.State.Chassis",
462 "RequestedPowerTransition", "string"};
463 try
464 {
465 dBusIntf->setDbusProperty(dbusMapping, value);
466 }
467 catch (const std::exception& e)
468 {
469 error(
470 "Failure in chassis State transition to Off, unable to set property RequestedPowerTransition, error - {ERROR}",
471 "ERROR", e);
472 }
473
474 using namespace sdbusplus::bus::match::rules;
475 chassisOffMatch = std::make_unique<sdbusplus::bus::match_t>(
476 pldm::utils::DBusHandler::getBus(),
477 propertiesChanged("/xyz/openbmc_project/state/chassis0",
478 "xyz.openbmc_project.State.Chassis"),
479 [this](sdbusplus::message_t& msg) {
480 DbusChangedProps props{};
481 std::string intf;
482 msg.read(intf, props);
483 const auto itr = props.find("CurrentPowerState");
484 if (itr != props.end())
485 {
486 PropertyValue value = itr->second;
487 auto propVal = std::get<std::string>(value);
488 if (propVal == "xyz.openbmc_project.State.Chassis.PowerState.Off")
489 {
490 pldm::utils::DBusMapping dbusMapping{
491 "/xyz/openbmc_project/control/host0/"
492 "power_restore_policy/one_time",
493 "xyz.openbmc_project.Control.Power.RestorePolicy",
494 "PowerRestorePolicy", "string"};
495 value = "xyz.openbmc_project.Control.Power.RestorePolicy."
496 "Policy.AlwaysOn";
497 try
498 {
499 dBusIntf->setDbusProperty(dbusMapping, value);
500 }
501 catch (const std::exception& e)
502 {
503 error(
504 "Failure in setting one-time restore policy, unable to set property PowerRestorePolicy, error - {ERROR}",
505 "ERROR", e);
506 }
507 dbusMapping = pldm::utils::DBusMapping{
508 "/xyz/openbmc_project/state/bmc0",
509 "xyz.openbmc_project.State.BMC", "RequestedBMCTransition",
510 "string"};
511 value = "xyz.openbmc_project.State.BMC.Transition.Reboot";
512 try
513 {
514 dBusIntf->setDbusProperty(dbusMapping, value);
515 }
516 catch (const std::exception& e)
517 {
518 error(
519 "Failure in BMC state transition to reboot, unable to set property RequestedBMCTransition , error - {ERROR}",
520 "ERROR", e);
521 }
522 }
523 }
524 });
525 }
526
checkAndDisableWatchDog()527 void pldm::responder::oem_ibm_platform::Handler::checkAndDisableWatchDog()
528 {
529 if (!hostOff && setEventReceiverCnt == SET_EVENT_RECEIVER_SENT)
530 {
531 disableWatchDogTimer();
532 }
533
534 return;
535 }
536
watchDogRunning()537 bool pldm::responder::oem_ibm_platform::Handler::watchDogRunning()
538 {
539 static constexpr auto watchDogObjectPath =
540 "/xyz/openbmc_project/watchdog/host0";
541 static constexpr auto watchDogEnablePropName = "Enabled";
542 static constexpr auto watchDogInterface =
543 "xyz.openbmc_project.State.Watchdog";
544 bool isWatchDogRunning = false;
545 try
546 {
547 isWatchDogRunning = pldm::utils::DBusHandler().getDbusProperty<bool>(
548 watchDogObjectPath, watchDogEnablePropName, watchDogInterface);
549 }
550 catch (const std::exception&)
551 {
552 return false;
553 }
554 return isWatchDogRunning;
555 }
556
resetWatchDogTimer()557 void pldm::responder::oem_ibm_platform::Handler::resetWatchDogTimer()
558 {
559 static constexpr auto watchDogService = "xyz.openbmc_project.Watchdog";
560 static constexpr auto watchDogObjectPath =
561 "/xyz/openbmc_project/watchdog/host0";
562 static constexpr auto watchDogInterface =
563 "xyz.openbmc_project.State.Watchdog";
564 static constexpr auto watchDogResetPropName = "ResetTimeRemaining";
565
566 bool wdStatus = watchDogRunning();
567 if (wdStatus == false)
568 {
569 return;
570 }
571 try
572 {
573 auto& bus = pldm::utils::DBusHandler::getBus();
574 auto resetMethod =
575 bus.new_method_call(watchDogService, watchDogObjectPath,
576 watchDogInterface, watchDogResetPropName);
577 resetMethod.append(true);
578 bus.call_noreply(resetMethod, dbusTimeout);
579 }
580 catch (const std::exception& e)
581 {
582 error("Failed to reset watchdog timer, error - {ERROR}", "ERROR", e);
583 return;
584 }
585 }
586
disableWatchDogTimer()587 void pldm::responder::oem_ibm_platform::Handler::disableWatchDogTimer()
588 {
589 setEventReceiverCnt = 0;
590 pldm::utils::DBusMapping dbusMapping{"/xyz/openbmc_project/watchdog/host0",
591 "xyz.openbmc_project.State.Watchdog",
592 "Enabled", "bool"};
593 bool wdStatus = watchDogRunning();
594
595 if (!wdStatus)
596 {
597 return;
598 }
599 try
600 {
601 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, false);
602 }
603 catch (const std::exception& e)
604 {
605 error("Failed to disable watchdog timer, error - {ERROR}", "ERROR", e);
606 }
607 }
checkBMCState()608 int pldm::responder::oem_ibm_platform::Handler::checkBMCState()
609 {
610 using BMC = sdbusplus::client::xyz::openbmc_project::state::BMC<>;
611 auto bmcPath = sdbusplus::message::object_path(BMC::namespace_path::value) /
612 BMC::namespace_path::bmc;
613 try
614 {
615 pldm::utils::PropertyValue propertyValue =
616 pldm::utils::DBusHandler().getDbusPropertyVariant(
617 bmcPath.str.c_str(), "CurrentBMCState", BMC::interface);
618
619 if (std::get<std::string>(propertyValue) ==
620 "xyz.openbmc_project.State.BMC.BMCState.NotReady")
621 {
622 error("GetPDR : PLDM stack is not ready for PDR exchange");
623 return PLDM_ERROR_NOT_READY;
624 }
625 }
626 catch (const std::exception& e)
627 {
628 error("Error getting the current BMC state, error - {ERROR}", "ERROR",
629 e);
630 return PLDM_ERROR;
631 }
632 return PLDM_SUCCESS;
633 }
634
635 const pldm_pdr_record*
fetchLastBMCRecord(const pldm_pdr * repo)636 pldm::responder::oem_ibm_platform::Handler::fetchLastBMCRecord(
637 const pldm_pdr* repo)
638 {
639 return pldm_pdr_find_last_in_range(repo, BMC_PDR_START_RANGE,
640 BMC_PDR_END_RANGE);
641 }
642
checkRecordHandleInRange(const uint32_t & record_handle)643 bool pldm::responder::oem_ibm_platform::Handler::checkRecordHandleInRange(
644 const uint32_t& record_handle)
645 {
646 return record_handle >= HOST_PDR_START_RANGE &&
647 record_handle <= HOST_PDR_END_RANGE;
648 }
649
processSetEventReceiver()650 void Handler::processSetEventReceiver()
651 {
652 this->setEventReceiver();
653 }
654
startStopTimer(bool value)655 void pldm::responder::oem_ibm_platform::Handler::startStopTimer(bool value)
656 {
657 if (value)
658 {
659 timer.restart(
660 std::chrono::seconds(HEARTBEAT_TIMEOUT + HEARTBEAT_TIMEOUT_DELTA));
661 }
662 else
663 {
664 timer.setEnabled(value);
665 }
666 }
667
setSurvTimer(uint8_t tid,bool value)668 void pldm::responder::oem_ibm_platform::Handler::setSurvTimer(uint8_t tid,
669 bool value)
670 {
671 if ((hostOff || hostTransitioningToOff || (tid != HYPERVISOR_TID)) &&
672 timer.isEnabled())
673 {
674 startStopTimer(false);
675 return;
676 }
677 if (value)
678 {
679 startStopTimer(value);
680 }
681 else if (timer.isEnabled())
682 {
683 info(
684 "Failed to stop surveillance timer while remote terminus status is ‘{HOST_TRANST_OFF}’ with Terminus ID ‘{TID}’ ",
685 "HOST_TRANST_OFF", hostTransitioningToOff, "TID", tid);
686 startStopTimer(value);
687 pldm::utils::reportError(
688 "xyz.openbmc_project.PLDM.Error.setSurvTimer.RecvSurveillancePingFail");
689 }
690 }
691
692 } // namespace oem_ibm_platform
693 } // namespace responder
694 } // namespace pldm
695