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