xref: /openbmc/pldm/oem/ibm/libpldmresponder/oem_ibm_handler.cpp (revision fdf6da79ab3df7b06e4b52f2353dc2e55252c6de)
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 #include <xyz/openbmc_project/State/Host/common.hpp>
15 
16 PHOSPHOR_LOG2_USING;
17 
18 using namespace pldm::pdr;
19 using namespace pldm::utils;
20 
21 namespace pldm
22 {
23 namespace responder
24 {
25 namespace oem_ibm_platform
26 {
27 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)28     getOemStateSensorReadingsHandler(
29         pldm::pdr::EntityType entityType, EntityInstance entityInstance,
30         ContainerID containerId, StateSetId stateSetId,
31         CompositeCount compSensorCnt, uint16_t /*sensorId*/,
32         std::vector<get_sensor_state_field>& stateField)
33 {
34     auto& entityAssociationMap = getAssociateEntityMap();
35     int rc = PLDM_SUCCESS;
36     stateField.clear();
37 
38     for (size_t i = 0; i < compSensorCnt; i++)
39     {
40         uint8_t sensorOpState{};
41         uint8_t presentState = PLDM_SENSOR_UNKNOWN;
42         if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE &&
43             stateSetId == PLDM_OEM_IBM_BOOT_STATE)
44         {
45             sensorOpState = fetchBootSide(entityInstance, codeUpdate);
46         }
47         else if (entityType == PLDM_ENTITY_SLOT &&
48                  stateSetId == PLDM_OEM_IBM_PCIE_SLOT_SENSOR_STATE)
49         {
50             for (const auto& [key, value] : entityAssociationMap)
51             {
52                 if (value.entity_type == entityType &&
53                     value.entity_instance_num == entityInstance &&
54                     value.entity_container_id == containerId)
55                 {
56                     sensorOpState = slotHandler->fetchSlotSensorState(key);
57                     break;
58                 }
59             }
60         }
61         else if (entityType == PLDM_OEM_IBM_ENTITY_REAL_SAI &&
62                  stateSetId == PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS)
63         {
64             sensorOpState = fetchRealSAIStatus();
65             presentState = PLDM_SENSOR_NORMAL;
66         }
67         else
68         {
69             rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
70             break;
71         }
72         stateField.push_back({PLDM_SENSOR_ENABLED, presentState,
73                               PLDM_SENSOR_UNKNOWN, sensorOpState});
74     }
75     return rc;
76 }
77 
78 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)79     oemSetStateEffecterStatesHandler(
80         uint16_t entityType, uint16_t entityInstance, uint16_t stateSetId,
81         uint8_t compEffecterCnt,
82         std::vector<set_effecter_state_field>& stateField, uint16_t effecterId)
83 {
84     int rc = PLDM_SUCCESS;
85     auto& entityAssociationMap = getAssociateEntityMap();
86 
87     for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
88     {
89         if (stateField[currState].set_request == PLDM_REQUEST_SET)
90         {
91             if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE &&
92                 stateSetId == PLDM_OEM_IBM_BOOT_STATE)
93             {
94                 rc = setBootSide(entityInstance, currState, stateField,
95                                  codeUpdate);
96             }
97             else if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE &&
98                      stateSetId == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
99             {
100                 if (stateField[currState].effecter_state ==
101                     uint8_t(CodeUpdateState::START))
102                 {
103                     codeUpdate->setCodeUpdateProgress(true);
104                     startUpdateEvent =
105                         std::make_unique<sdeventplus::source::Defer>(
106                             event,
107                             std::bind(std::mem_fn(&oem_ibm_platform::Handler::
108                                                       _processStartUpdate),
109                                       this, std::placeholders::_1));
110                 }
111                 else if (stateField[currState].effecter_state ==
112                          uint8_t(CodeUpdateState::END))
113                 {
114                     rc = PLDM_SUCCESS;
115                     assembleImageEvent = std::make_unique<
116                         sdeventplus::source::Defer>(
117                         event,
118                         std::bind(
119                             std::mem_fn(
120                                 &oem_ibm_platform::Handler::_processEndUpdate),
121                             this, std::placeholders::_1));
122 
123                     // sendCodeUpdateEvent(effecterId, END, START);
124                 }
125                 else if (stateField[currState].effecter_state ==
126                          uint8_t(CodeUpdateState::ABORT))
127                 {
128                     codeUpdate->setCodeUpdateProgress(false);
129                     codeUpdate->clearDirPath(LID_STAGING_DIR);
130                     auto sensorId = codeUpdate->getFirmwareUpdateSensor();
131                     sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
132                                          uint8_t(CodeUpdateState::ABORT),
133                                          uint8_t(CodeUpdateState::START));
134                     // sendCodeUpdateEvent(effecterId, ABORT, END);
135                 }
136                 else if (stateField[currState].effecter_state ==
137                          uint8_t(CodeUpdateState::ACCEPT))
138                 {
139                     auto sensorId = codeUpdate->getFirmwareUpdateSensor();
140                     sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
141                                          uint8_t(CodeUpdateState::ACCEPT),
142                                          uint8_t(CodeUpdateState::END));
143                     // TODO Set new Dbus property provided by code update app
144                     // sendCodeUpdateEvent(effecterId, ACCEPT, END);
145                 }
146                 else if (stateField[currState].effecter_state ==
147                          uint8_t(CodeUpdateState::REJECT))
148                 {
149                     auto sensorId = codeUpdate->getFirmwareUpdateSensor();
150                     sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
151                                          uint8_t(CodeUpdateState::REJECT),
152                                          uint8_t(CodeUpdateState::END));
153                     // TODO Set new Dbus property provided by code update app
154                     // sendCodeUpdateEvent(effecterId, REJECT, END);
155                 }
156             }
157             else if (entityType == PLDM_ENTITY_SYSTEM_CHASSIS &&
158                      stateSetId == PLDM_OEM_IBM_SYSTEM_POWER_STATE)
159             {
160                 if (stateField[currState].effecter_state == POWER_CYCLE_HARD)
161                 {
162                     systemRebootEvent =
163                         std::make_unique<sdeventplus::source::Defer>(
164                             event,
165                             std::bind(std::mem_fn(&oem_ibm_platform::Handler::
166                                                       _processSystemReboot),
167                                       this, std::placeholders::_1));
168                 }
169             }
170             else if (stateSetId == PLDM_OEM_IBM_PCIE_SLOT_EFFECTER_STATE)
171             {
172                 slotHandler->enableSlot(effecterId, entityAssociationMap,
173                                         stateField[currState].effecter_state);
174             }
175             else if (entityType == PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE &&
176                      stateSetId == PLDM_OEM_IBM_BOOT_SIDE_RENAME)
177             {
178                 if (stateField[currState].effecter_state ==
179                     PLDM_OEM_IBM_BOOT_SIDE_RENAME_STATE_RENAMED)
180                 {
181                     codeUpdate->processRenameEvent();
182                 }
183             }
184             else if (entityType == PLDM_OEM_IBM_ENTITY_REAL_SAI &&
185                      stateSetId == PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS)
186             {
187                 turnOffRealSAIEffecter();
188             }
189             else
190             {
191                 rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
192             }
193         }
194         if (rc != PLDM_SUCCESS)
195         {
196             break;
197         }
198     }
199     return rc;
200 }
201 
buildAllCodeUpdateEffecterPDR(oem_ibm_platform::Handler * platformHandler,uint16_t entityType,uint16_t entityInstance,uint16_t stateSetID,pdr_utils::Repo & repo)202 void buildAllCodeUpdateEffecterPDR(oem_ibm_platform::Handler* platformHandler,
203                                    uint16_t entityType, uint16_t entityInstance,
204                                    uint16_t stateSetID, pdr_utils::Repo& repo)
205 {
206     size_t pdrSize = 0;
207     pdrSize = sizeof(pldm_state_effecter_pdr) +
208               sizeof(state_effecter_possible_states);
209     std::vector<uint8_t> entry{};
210     entry.resize(pdrSize);
211     pldm_state_effecter_pdr* pdr =
212         reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
213     if (!pdr)
214     {
215         error("Failed to get record by PDR type, error - {ERROR}", "ERROR",
216               lg2::hex,
217               static_cast<unsigned>(PLDM_PLATFORM_INVALID_EFFECTER_ID));
218         return;
219     }
220     pdr->hdr.record_handle = 0;
221     pdr->hdr.version = 1;
222     pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
223     pdr->hdr.record_change_num = 0;
224     pdr->hdr.length = sizeof(pldm_state_effecter_pdr) - sizeof(pldm_pdr_hdr);
225     pdr->terminus_handle = TERMINUS_HANDLE;
226     pdr->effecter_id = platformHandler->getNextEffecterId();
227     pdr->entity_type = entityType;
228     pdr->entity_instance = entityInstance;
229     pdr->container_id = 1;
230     pdr->effecter_semantic_id = 0;
231     pdr->effecter_init = PLDM_NO_INIT;
232     pdr->has_description_pdr = false;
233     pdr->composite_effecter_count = 1;
234 
235     auto* possibleStatesPtr = pdr->possible_states;
236     auto possibleStates =
237         reinterpret_cast<state_effecter_possible_states*>(possibleStatesPtr);
238     possibleStates->state_set_id = stateSetID;
239     possibleStates->possible_states_size = 2;
240     auto state =
241         reinterpret_cast<state_effecter_possible_states*>(possibleStates);
242     if ((stateSetID == PLDM_OEM_IBM_BOOT_STATE) ||
243         (stateSetID == PLDM_OEM_IBM_BOOT_SIDE_RENAME))
244         state->states[0].byte = 6;
245     else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
246         state->states[0].byte = 126;
247     else if (stateSetID == PLDM_OEM_IBM_SYSTEM_POWER_STATE)
248         state->states[0].byte = 2;
249     pldm::responder::pdr_utils::PdrEntry pdrEntry{};
250     pdrEntry.data = entry.data();
251     pdrEntry.size = pdrSize;
252     repo.addRecord(pdrEntry);
253 }
254 
buildAllSlotEnableEffecterPDR(oem_ibm_platform::Handler * platformHandler,pdr_utils::Repo & repo,const std::vector<std::string> & slotobjpaths)255 void buildAllSlotEnableEffecterPDR(oem_ibm_platform::Handler* platformHandler,
256                                    pdr_utils::Repo& repo,
257                                    const std::vector<std::string>& slotobjpaths)
258 {
259     size_t pdrSize = 0;
260     pdrSize = sizeof(pldm_state_effecter_pdr) +
261               sizeof(state_effecter_possible_states);
262     std::vector<uint8_t> entry{};
263     entry.resize(pdrSize);
264     pldm_state_effecter_pdr* pdr =
265         reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
266     if (!pdr)
267     {
268         error("Failed to get record by PDR type, ERROR:{ERR}", "ERR", lg2::hex,
269               static_cast<unsigned>(PLDM_PLATFORM_INVALID_EFFECTER_ID));
270         return;
271     }
272 
273     auto& associatedEntityMap = platformHandler->getAssociateEntityMap();
274     for (const auto& entity_path : slotobjpaths)
275     {
276         pdr->hdr.record_handle = 0;
277         pdr->hdr.version = 1;
278         pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
279         pdr->hdr.record_change_num = 0;
280         pdr->hdr.length =
281             sizeof(pldm_state_effecter_pdr) - sizeof(pldm_pdr_hdr);
282         pdr->terminus_handle = TERMINUS_HANDLE;
283         pdr->effecter_id = platformHandler->getNextEffecterId();
284 
285         if (entity_path != "" && associatedEntityMap.contains(entity_path))
286         {
287             pdr->entity_type = associatedEntityMap.at(entity_path).entity_type;
288             pdr->entity_instance =
289                 associatedEntityMap.at(entity_path).entity_instance_num;
290             pdr->container_id =
291                 associatedEntityMap.at(entity_path).entity_container_id;
292             platformHandler->effecterIdToDbusMap[pdr->effecter_id] =
293                 entity_path;
294         }
295         else
296         {
297             // the slots are not present, dont create the PDR
298             continue;
299         }
300         pdr->effecter_semantic_id = 0;
301         pdr->effecter_init = PLDM_NO_INIT;
302         pdr->has_description_pdr = false;
303         pdr->composite_effecter_count = 1;
304 
305         auto* possibleStatesPtr = pdr->possible_states;
306         auto possibleStates = reinterpret_cast<state_effecter_possible_states*>(
307             possibleStatesPtr);
308         possibleStates->state_set_id = PLDM_OEM_IBM_PCIE_SLOT_EFFECTER_STATE;
309         possibleStates->possible_states_size = 2;
310         auto state =
311             reinterpret_cast<state_effecter_possible_states*>(possibleStates);
312         state->states[0].byte = 14;
313         pldm::responder::pdr_utils::PdrEntry pdrEntry{};
314         pdrEntry.data = entry.data();
315         pdrEntry.size = pdrSize;
316         repo.addRecord(pdrEntry);
317     }
318 }
319 
buildAllCodeUpdateSensorPDR(oem_ibm_platform::Handler * platformHandler,uint16_t entityType,uint16_t entityInstance,uint16_t stateSetID,pdr_utils::Repo & repo)320 void buildAllCodeUpdateSensorPDR(oem_ibm_platform::Handler* platformHandler,
321                                  uint16_t entityType, uint16_t entityInstance,
322                                  uint16_t stateSetID, pdr_utils::Repo& repo)
323 {
324     size_t pdrSize = 0;
325     pdrSize = sizeof(pldm_state_sensor_pdr) +
326               sizeof(state_sensor_possible_states);
327     std::vector<uint8_t> entry{};
328     entry.resize(pdrSize);
329     pldm_state_sensor_pdr* pdr =
330         reinterpret_cast<pldm_state_sensor_pdr*>(entry.data());
331     if (!pdr)
332     {
333         error("Failed to get record by PDR type, error - {ERROR}", "ERROR",
334               lg2::hex, static_cast<unsigned>(PLDM_PLATFORM_INVALID_SENSOR_ID));
335         return;
336     }
337     pdr->hdr.record_handle = 0;
338     pdr->hdr.version = 1;
339     pdr->hdr.type = PLDM_STATE_SENSOR_PDR;
340     pdr->hdr.record_change_num = 0;
341     pdr->hdr.length = sizeof(pldm_state_sensor_pdr) - sizeof(pldm_pdr_hdr);
342     pdr->terminus_handle = TERMINUS_HANDLE;
343     pdr->sensor_id = platformHandler->getNextSensorId();
344     pdr->entity_type = entityType;
345     pdr->entity_instance = entityInstance;
346     pdr->container_id = 1;
347     pdr->sensor_init = PLDM_NO_INIT;
348     pdr->sensor_auxiliary_names_pdr = false;
349     pdr->composite_sensor_count = 1;
350 
351     auto* possibleStatesPtr = pdr->possible_states;
352     auto possibleStates =
353         reinterpret_cast<state_sensor_possible_states*>(possibleStatesPtr);
354     possibleStates->state_set_id = stateSetID;
355     possibleStates->possible_states_size = 2;
356     auto state =
357         reinterpret_cast<state_sensor_possible_states*>(possibleStates);
358     if ((stateSetID == PLDM_OEM_IBM_BOOT_STATE) ||
359         (stateSetID == PLDM_OEM_IBM_VERIFICATION_STATE) ||
360         (stateSetID == PLDM_OEM_IBM_BOOT_SIDE_RENAME))
361         state->states[0].byte = 6;
362     else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
363         state->states[0].byte = 126;
364     pldm::responder::pdr_utils::PdrEntry pdrEntry{};
365     pdrEntry.data = entry.data();
366     pdrEntry.size = pdrSize;
367     repo.addRecord(pdrEntry);
368 }
369 
buildAllSlotEnableSensorPDR(oem_ibm_platform::Handler * platformHandler,pdr_utils::Repo & repo,const std::vector<std::string> & slotobjpaths)370 void buildAllSlotEnableSensorPDR(oem_ibm_platform::Handler* platformHandler,
371                                  pdr_utils::Repo& repo,
372                                  const std::vector<std::string>& slotobjpaths)
373 {
374     size_t pdrSize = 0;
375     pdrSize = sizeof(pldm_state_sensor_pdr) +
376               sizeof(state_sensor_possible_states);
377     std::vector<uint8_t> entry{};
378     entry.resize(pdrSize);
379     pldm_state_sensor_pdr* pdr =
380         reinterpret_cast<pldm_state_sensor_pdr*>(entry.data());
381     if (!pdr)
382     {
383         error("Failed to get record by PDR type, ERROR:{ERR}", "ERR", lg2::hex,
384               static_cast<unsigned>(PLDM_PLATFORM_INVALID_SENSOR_ID));
385         return;
386     }
387     auto& associatedEntityMap = platformHandler->getAssociateEntityMap();
388     for (const auto& entity_path : slotobjpaths)
389     {
390         pdr->hdr.record_handle = 0;
391         pdr->hdr.version = 1;
392         pdr->hdr.type = PLDM_STATE_SENSOR_PDR;
393         pdr->hdr.record_change_num = 0;
394         pdr->hdr.length = sizeof(pldm_state_sensor_pdr) - sizeof(pldm_pdr_hdr);
395         pdr->terminus_handle = TERMINUS_HANDLE;
396         pdr->sensor_id = platformHandler->getNextSensorId();
397         if (entity_path != "" && associatedEntityMap.contains(entity_path))
398         {
399             pdr->entity_type = associatedEntityMap.at(entity_path).entity_type;
400             pdr->entity_instance =
401                 associatedEntityMap.at(entity_path).entity_instance_num;
402             pdr->container_id =
403                 associatedEntityMap.at(entity_path).entity_container_id;
404         }
405         else
406         {
407             // the slots are not present, dont create the PDR
408             continue;
409         }
410 
411         pdr->sensor_init = PLDM_NO_INIT;
412         pdr->sensor_auxiliary_names_pdr = false;
413         pdr->composite_sensor_count = 1;
414 
415         auto* possibleStatesPtr = pdr->possible_states;
416         auto possibleStates =
417             reinterpret_cast<state_sensor_possible_states*>(possibleStatesPtr);
418         possibleStates->state_set_id = PLDM_OEM_IBM_PCIE_SLOT_SENSOR_STATE;
419         possibleStates->possible_states_size = 1;
420         auto state =
421             reinterpret_cast<state_sensor_possible_states*>(possibleStates);
422         state->states[0].byte = 15;
423         pldm::responder::pdr_utils::PdrEntry pdrEntry{};
424         pdrEntry.data = entry.data();
425         pdrEntry.size = pdrSize;
426         repo.addRecord(pdrEntry);
427     }
428 }
429 
buildAllRealSAIEffecterPDR(oem_ibm_platform::Handler * platformHandler,uint16_t entityType,uint16_t entityInstance,pdr_utils::Repo & repo)430 void buildAllRealSAIEffecterPDR(oem_ibm_platform::Handler* platformHandler,
431                                 uint16_t entityType, uint16_t entityInstance,
432                                 pdr_utils::Repo& repo)
433 
434 {
435     size_t pdrSize = 0;
436     pdrSize = sizeof(pldm_state_effecter_pdr) +
437               sizeof(state_effecter_possible_states);
438     std::vector<uint8_t> entry{};
439     entry.resize(pdrSize);
440     pldm_state_effecter_pdr* pdr =
441         reinterpret_cast<pldm_state_effecter_pdr*>(entry.data());
442     if (!pdr)
443     {
444         error("Failed to get Real SAI effecter PDR record due to the "
445               "error {ERR_CODE}",
446               "ERR_CODE", lg2::hex,
447               static_cast<unsigned>(PLDM_PLATFORM_INVALID_EFFECTER_ID));
448         return;
449     }
450     pdr->hdr.record_handle = 0;
451     pdr->hdr.version = 1;
452     pdr->hdr.type = PLDM_STATE_EFFECTER_PDR;
453     pdr->hdr.record_change_num = 0;
454     pdr->hdr.length = sizeof(pldm_state_effecter_pdr) - sizeof(pldm_pdr_hdr);
455     pdr->terminus_handle = TERMINUS_HANDLE;
456     pdr->effecter_id = platformHandler->getNextEffecterId();
457     pdr->entity_type = entityType;
458     pdr->entity_instance = entityInstance;
459     pdr->container_id = 1;
460     pdr->effecter_semantic_id = 0;
461     pdr->effecter_init = PLDM_NO_INIT;
462     pdr->has_description_pdr = false;
463     pdr->composite_effecter_count = 1;
464 
465     auto* possibleStatesPtr = pdr->possible_states;
466     auto possibleStates =
467         reinterpret_cast<state_effecter_possible_states*>(possibleStatesPtr);
468     possibleStates->state_set_id = PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS;
469     possibleStates->possible_states_size = 1;
470     auto state =
471         reinterpret_cast<state_effecter_possible_states*>(possibleStates);
472     state->states[0].byte = 2;
473     pldm::responder::pdr_utils::PdrEntry pdrEntry{};
474     pdrEntry.data = entry.data();
475     pdrEntry.size = pdrSize;
476     repo.addRecord(pdrEntry);
477 }
478 
buildAllRealSAISensorPDR(oem_ibm_platform::Handler * platformHandler,uint16_t entityType,uint16_t entityInstance,pdr_utils::Repo & repo)479 void buildAllRealSAISensorPDR(oem_ibm_platform::Handler* platformHandler,
480                               uint16_t entityType, uint16_t entityInstance,
481                               pdr_utils::Repo& repo)
482 
483 {
484     size_t pdrSize = 0;
485     pdrSize = sizeof(pldm_state_sensor_pdr) +
486               sizeof(state_sensor_possible_states);
487     std::vector<uint8_t> entry{};
488     entry.resize(pdrSize);
489     pldm_state_sensor_pdr* pdr =
490         reinterpret_cast<pldm_state_sensor_pdr*>(entry.data());
491     if (!pdr)
492     {
493         error("Failed to get Real SAI sensor PDR record due to the "
494               "error {ERR_CODE}",
495               "ERR_CODE", lg2::hex,
496               static_cast<unsigned>(PLDM_PLATFORM_INVALID_SENSOR_ID));
497         return;
498     }
499     pdr->hdr.record_handle = 0;
500     pdr->hdr.version = 1;
501     pdr->hdr.type = PLDM_STATE_SENSOR_PDR;
502     pdr->hdr.record_change_num = 0;
503     pdr->hdr.length = sizeof(pldm_state_sensor_pdr) - sizeof(pldm_pdr_hdr);
504     pdr->terminus_handle = TERMINUS_HANDLE;
505     pdr->sensor_id = platformHandler->getNextSensorId();
506     pdr->entity_type = entityType;
507     pdr->entity_instance = entityInstance;
508     pdr->container_id = 1;
509     pdr->sensor_init = PLDM_NO_INIT;
510     pdr->sensor_auxiliary_names_pdr = false;
511     pdr->composite_sensor_count = 1;
512 
513     auto* possibleStatesPtr = pdr->possible_states;
514     auto possibleStates =
515         reinterpret_cast<state_sensor_possible_states*>(possibleStatesPtr);
516     possibleStates->state_set_id = PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS;
517     possibleStates->possible_states_size = 2;
518     auto state =
519         reinterpret_cast<state_sensor_possible_states*>(possibleStates);
520     state->states[0].byte = 6;
521     pldm::responder::pdr_utils::PdrEntry pdrEntry{};
522     pdrEntry.data = entry.data();
523     pdrEntry.size = pdrSize;
524     repo.addRecord(pdrEntry);
525 }
526 
buildOEMPDR(pdr_utils::Repo & repo)527 void pldm::responder::oem_ibm_platform::Handler::buildOEMPDR(
528     pdr_utils::Repo& repo)
529 {
530     buildAllCodeUpdateEffecterPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
531                                   ENTITY_INSTANCE_0, PLDM_OEM_IBM_BOOT_STATE,
532                                   repo);
533     buildAllCodeUpdateEffecterPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
534                                   ENTITY_INSTANCE_1, PLDM_OEM_IBM_BOOT_STATE,
535                                   repo);
536     buildAllCodeUpdateEffecterPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
537                                   ENTITY_INSTANCE_0,
538                                   PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
539     buildAllCodeUpdateEffecterPDR(this, PLDM_ENTITY_SYSTEM_CHASSIS,
540                                   ENTITY_INSTANCE_1,
541                                   PLDM_OEM_IBM_SYSTEM_POWER_STATE, repo);
542 
543     static constexpr auto objectPath = "/xyz/openbmc_project/inventory/system";
544     const std::vector<std::string> slotInterface = {
545         "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
546     auto slotPaths = dBusIntf->getSubTreePaths(objectPath, 0, slotInterface);
547     buildAllSlotEnableEffecterPDR(this, repo, slotPaths);
548 
549     buildAllRealSAIEffecterPDR(this, PLDM_OEM_IBM_ENTITY_REAL_SAI,
550                                ENTITY_INSTANCE_1, repo);
551 
552     buildAllSlotEnableSensorPDR(this, repo, slotPaths);
553 
554     buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
555                                 ENTITY_INSTANCE_0, PLDM_OEM_IBM_BOOT_STATE,
556                                 repo);
557     buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
558                                 ENTITY_INSTANCE_1, PLDM_OEM_IBM_BOOT_STATE,
559                                 repo);
560     buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
561                                 ENTITY_INSTANCE_0,
562                                 PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
563     buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
564                                 ENTITY_INSTANCE_0,
565                                 PLDM_OEM_IBM_VERIFICATION_STATE, repo);
566     buildAllCodeUpdateSensorPDR(this, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
567                                 ENTITY_INSTANCE_0,
568                                 PLDM_OEM_IBM_BOOT_SIDE_RENAME, repo);
569     buildAllRealSAISensorPDR(this, PLDM_OEM_IBM_ENTITY_REAL_SAI,
570                              ENTITY_INSTANCE_1, repo);
571 
572     realSAISensorId = findStateSensorId(
573         repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_REAL_SAI, ENTITY_INSTANCE_1, 1,
574         PLDM_STATE_SET_OPERATIONAL_FAULT_STATUS);
575 
576     auto sensorId = findStateSensorId(
577         repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
578         ENTITY_INSTANCE_0, 1, PLDM_OEM_IBM_VERIFICATION_STATE);
579     codeUpdate->setMarkerLidSensor(sensorId);
580     sensorId = findStateSensorId(
581         repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
582         ENTITY_INSTANCE_0, 1, PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE);
583     codeUpdate->setFirmwareUpdateSensor(sensorId);
584     sensorId =
585         findStateSensorId(repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
586                           ENTITY_INSTANCE_0, 1, PLDM_OEM_IBM_BOOT_SIDE_RENAME);
587     codeUpdate->setBootSideRenameStateSensor(sensorId);
588 }
589 
setPlatformHandler(pldm::responder::platform::Handler * handler)590 void pldm::responder::oem_ibm_platform::Handler::setPlatformHandler(
591     pldm::responder::platform::Handler* handler)
592 {
593     platformHandler = handler;
594 }
595 
sendEventToHost(std::vector<uint8_t> & requestMsg,uint8_t instanceId)596 int pldm::responder::oem_ibm_platform::Handler::sendEventToHost(
597     std::vector<uint8_t>& requestMsg, uint8_t instanceId)
598 {
599     if (requestMsg.size())
600     {
601         std::ostringstream tempStream;
602         for (int byte : requestMsg)
603         {
604             tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
605                        << " ";
606         }
607         std::cout << tempStream.str() << std::endl;
608     }
609     auto oemPlatformEventMessageResponseHandler = [](mctp_eid_t /*eid*/,
610                                                      const pldm_msg* response,
611                                                      size_t respMsgLen) {
612         uint8_t completionCode{};
613         uint8_t status{};
614         auto rc = decode_platform_event_message_resp(response, respMsgLen,
615                                                      &completionCode, &status);
616         if (rc || completionCode)
617         {
618             error(
619                 "Failed to decode platform event message response for code update event with response code '{RC}' and completion code '{CC}'",
620                 "RC", rc, "CC", completionCode);
621         }
622     };
623     auto rc = handler->registerRequest(
624         mctp_eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE,
625         std::move(requestMsg),
626         std::move(oemPlatformEventMessageResponseHandler));
627     if (rc)
628     {
629         error("Failed to send BIOS attribute change event message ");
630     }
631 
632     return rc;
633 }
634 
encodeEventMsg(uint8_t eventType,const std::vector<uint8_t> & eventDataVec,std::vector<uint8_t> & requestMsg,uint8_t instanceId)635 int encodeEventMsg(uint8_t eventType, const std::vector<uint8_t>& eventDataVec,
636                    std::vector<uint8_t>& requestMsg, uint8_t instanceId)
637 {
638     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
639 
640     auto rc = encode_platform_event_message_req(
641         instanceId, 1 /*formatVersion*/, TERMINUS_ID /*tId*/, eventType,
642         eventDataVec.data(), eventDataVec.size(), request,
643         eventDataVec.size() + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
644 
645     return rc;
646 }
647 
sendStateSensorEvent(uint16_t sensorId,enum sensor_event_class_states sensorEventClass,uint8_t sensorOffset,uint8_t eventState,uint8_t prevEventState)648 void pldm::responder::oem_ibm_platform::Handler::sendStateSensorEvent(
649     uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
650     uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
651 {
652     std::vector<uint8_t> sensorEventDataVec{};
653     size_t sensorEventSize = PLDM_SENSOR_EVENT_DATA_MIN_LENGTH + 1;
654     sensorEventDataVec.resize(sensorEventSize);
655     auto eventData = reinterpret_cast<struct pldm_sensor_event_data*>(
656         sensorEventDataVec.data());
657     eventData->sensor_id = sensorId;
658     eventData->sensor_event_class_type = sensorEventClass;
659     auto eventClassStart = eventData->event_class;
660     auto eventClass =
661         reinterpret_cast<struct pldm_sensor_event_state_sensor_state*>(
662             eventClassStart);
663     eventClass->sensor_offset = sensorOffset;
664     eventClass->event_state = eventState;
665     eventClass->previous_event_state = prevEventState;
666     auto instanceId = instanceIdDb.next(mctp_eid);
667     std::vector<uint8_t> requestMsg(
668         sizeof(pldm_msg_hdr) + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
669         sensorEventDataVec.size());
670     auto rc = encodeEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec, requestMsg,
671                              instanceId);
672     if (rc != PLDM_SUCCESS)
673     {
674         error("Failed to encode state sensor event with response code '{RC}'",
675               "RC", rc);
676         instanceIdDb.free(mctp_eid, instanceId);
677         return;
678     }
679     rc = sendEventToHost(requestMsg, instanceId);
680     if (rc != PLDM_SUCCESS)
681     {
682         error(
683             "Failed to send event to remote terminus with response code '{RC}'",
684             "RC", rc);
685     }
686     return;
687 }
688 
_processEndUpdate(sdeventplus::source::EventBase &)689 void pldm::responder::oem_ibm_platform::Handler::_processEndUpdate(
690     sdeventplus::source::EventBase& /*source */)
691 {
692     assembleImageEvent.reset();
693     int retc = codeUpdate->assembleCodeUpdateImage();
694     if (retc != PLDM_SUCCESS)
695     {
696         codeUpdate->setCodeUpdateProgress(false);
697         auto sensorId = codeUpdate->getFirmwareUpdateSensor();
698         sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
699                              uint8_t(CodeUpdateState::FAIL),
700                              uint8_t(CodeUpdateState::START));
701     }
702 }
703 
_processStartUpdate(sdeventplus::source::EventBase &)704 void pldm::responder::oem_ibm_platform::Handler::_processStartUpdate(
705     sdeventplus::source::EventBase& /*source */)
706 {
707     codeUpdate->deleteImage();
708     CodeUpdateState state = CodeUpdateState::START;
709     auto rc = codeUpdate->setRequestedApplyTime();
710     if (rc != PLDM_SUCCESS)
711     {
712         error("setRequestedApplyTime failed");
713         state = CodeUpdateState::FAIL;
714     }
715     auto sensorId = codeUpdate->getFirmwareUpdateSensor();
716     sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, uint8_t(state),
717                          uint8_t(CodeUpdateState::END));
718 }
719 
updateOemDbusPaths(std::string & dbusPath)720 void pldm::responder::oem_ibm_platform::Handler::updateOemDbusPaths(
721     std::string& dbusPath)
722 {
723     std::string toFind("system1/chassis1/motherboard1");
724     if (dbusPath.find(toFind) != std::string::npos)
725     {
726         size_t pos = dbusPath.find(toFind);
727         dbusPath.replace(pos, toFind.length(), "system/chassis/motherboard");
728     }
729     toFind = "system1";
730     if (dbusPath.find(toFind) != std::string::npos)
731     {
732         size_t pos = dbusPath.find(toFind);
733         dbusPath.replace(pos, toFind.length(), "system");
734     }
735     /* below logic to replace path 'motherboard/socket/chassis' to
736        'motherboard/chassis' or 'motherboard/socket123/chassis' to
737        'motherboard/chassis' */
738     toFind = "socket";
739     size_t pos1 = dbusPath.find(toFind);
740     // while loop to detect multiple substring 'socket' in the path
741     while (pos1 != std::string::npos)
742     {
743         size_t pos2 = dbusPath.substr(pos1 + 1).find('/') + 1;
744         // Replacing starting from substring to next occurrence of char '/'
745         dbusPath.replace(pos1, pos2 + 1, "");
746         pos1 = dbusPath.find(toFind);
747     }
748 }
749 
_processSystemReboot(sdeventplus::source::EventBase &)750 void pldm::responder::oem_ibm_platform::Handler::_processSystemReboot(
751     sdeventplus::source::EventBase& /*source */)
752 {
753     pldm::utils::PropertyValue value =
754         "xyz.openbmc_project.State.Chassis.Transition.Off";
755     pldm::utils::DBusMapping dbusMapping{"/xyz/openbmc_project/state/chassis0",
756                                          "xyz.openbmc_project.State.Chassis",
757                                          "RequestedPowerTransition", "string"};
758     try
759     {
760         dBusIntf->setDbusProperty(dbusMapping, value);
761     }
762     catch (const std::exception& e)
763     {
764         error(
765             "Failure in chassis State transition to Off, unable to set property RequestedPowerTransition, error - {ERROR}",
766             "ERROR", e);
767     }
768 
769     using namespace sdbusplus::bus::match::rules;
770     chassisOffMatch = std::make_unique<sdbusplus::bus::match_t>(
771         pldm::utils::DBusHandler::getBus(),
772         propertiesChanged("/xyz/openbmc_project/state/chassis0",
773                           "xyz.openbmc_project.State.Chassis"),
774         [this](sdbusplus::message_t& msg) {
775             DbusChangedProps props{};
776             std::string intf;
777             msg.read(intf, props);
778             const auto itr = props.find("CurrentPowerState");
779             if (itr != props.end())
780             {
781                 PropertyValue value = itr->second;
782                 auto propVal = std::get<std::string>(value);
783                 if (propVal ==
784                     "xyz.openbmc_project.State.Chassis.PowerState.Off")
785                 {
786                     pldm::utils::DBusMapping dbusMapping{
787                         "/xyz/openbmc_project/control/host0/"
788                         "power_restore_policy/one_time",
789                         "xyz.openbmc_project.Control.Power.RestorePolicy",
790                         "PowerRestorePolicy", "string"};
791                     value = "xyz.openbmc_project.Control.Power.RestorePolicy."
792                             "Policy.AlwaysOn";
793                     try
794                     {
795                         dBusIntf->setDbusProperty(dbusMapping, value);
796                     }
797                     catch (const std::exception& e)
798                     {
799                         error(
800                             "Failure in setting one-time restore policy, unable to set property PowerRestorePolicy, error - {ERROR}",
801                             "ERROR", e);
802                     }
803                     dbusMapping = pldm::utils::DBusMapping{
804                         "/xyz/openbmc_project/state/bmc0",
805                         "xyz.openbmc_project.State.BMC",
806                         "RequestedBMCTransition", "string"};
807                     value = "xyz.openbmc_project.State.BMC.Transition.Reboot";
808                     try
809                     {
810                         dBusIntf->setDbusProperty(dbusMapping, value);
811                     }
812                     catch (const std::exception& e)
813                     {
814                         error(
815                             "Failure in BMC state transition to reboot, unable to set property RequestedBMCTransition , error - {ERROR}",
816                             "ERROR", e);
817                     }
818                 }
819             }
820         });
821 }
822 
checkAndDisableWatchDog()823 void pldm::responder::oem_ibm_platform::Handler::checkAndDisableWatchDog()
824 {
825     if (!hostOff && setEventReceiverCnt == SET_EVENT_RECEIVER_SENT)
826     {
827         disableWatchDogTimer();
828     }
829 
830     return;
831 }
832 
watchDogRunning()833 bool pldm::responder::oem_ibm_platform::Handler::watchDogRunning()
834 {
835     static constexpr auto watchDogObjectPath =
836         "/xyz/openbmc_project/watchdog/host0";
837     static constexpr auto watchDogEnablePropName = "Enabled";
838     static constexpr auto watchDogInterface =
839         "xyz.openbmc_project.State.Watchdog";
840     bool isWatchDogRunning = false;
841     try
842     {
843         isWatchDogRunning = pldm::utils::DBusHandler().getDbusProperty<bool>(
844             watchDogObjectPath, watchDogEnablePropName, watchDogInterface);
845     }
846     catch (const std::exception&)
847     {
848         return false;
849     }
850     return isWatchDogRunning;
851 }
852 
resetWatchDogTimer()853 void pldm::responder::oem_ibm_platform::Handler::resetWatchDogTimer()
854 {
855     static constexpr auto watchDogService = "xyz.openbmc_project.Watchdog";
856     static constexpr auto watchDogObjectPath =
857         "/xyz/openbmc_project/watchdog/host0";
858     static constexpr auto watchDogInterface =
859         "xyz.openbmc_project.State.Watchdog";
860     static constexpr auto watchDogResetPropName = "ResetTimeRemaining";
861 
862     bool wdStatus = watchDogRunning();
863     if (wdStatus == false)
864     {
865         return;
866     }
867     try
868     {
869         auto& bus = pldm::utils::DBusHandler::getBus();
870         auto resetMethod =
871             bus.new_method_call(watchDogService, watchDogObjectPath,
872                                 watchDogInterface, watchDogResetPropName);
873         resetMethod.append(true);
874         bus.call_noreply(resetMethod, dbusTimeout);
875     }
876     catch (const std::exception& e)
877     {
878         error("Failed to reset watchdog timer, error - {ERROR}", "ERROR", e);
879         return;
880     }
881 }
882 
disableWatchDogTimer()883 void pldm::responder::oem_ibm_platform::Handler::disableWatchDogTimer()
884 {
885     setEventReceiverCnt = 0;
886     pldm::utils::DBusMapping dbusMapping{
887         "/xyz/openbmc_project/watchdog/host0",
888         "xyz.openbmc_project.State.Watchdog", "Enabled", "bool"};
889     bool wdStatus = watchDogRunning();
890 
891     if (!wdStatus)
892     {
893         return;
894     }
895     try
896     {
897         pldm::utils::DBusHandler().setDbusProperty(dbusMapping, false);
898     }
899     catch (const std::exception& e)
900     {
901         error("Failed to disable watchdog timer, error - {ERROR}", "ERROR", e);
902     }
903 }
checkBMCState()904 int pldm::responder::oem_ibm_platform::Handler::checkBMCState()
905 {
906     using BMC = sdbusplus::client::xyz::openbmc_project::state::BMC<>;
907     auto bmcPath = sdbusplus::message::object_path(BMC::namespace_path::value) /
908                    BMC::namespace_path::bmc;
909     try
910     {
911         pldm::utils::PropertyValue propertyValue =
912             pldm::utils::DBusHandler().getDbusPropertyVariant(
913                 bmcPath.str.c_str(), "CurrentBMCState", BMC::interface);
914 
915         if (std::get<std::string>(propertyValue) !=
916             "xyz.openbmc_project.State.BMC.BMCState.Ready")
917         {
918             error("GetPDR : PLDM stack is not ready for PDR exchange");
919             return PLDM_ERROR_NOT_READY;
920         }
921     }
922     catch (const std::exception& e)
923     {
924         error("Error getting the current BMC state, error - {ERROR}", "ERROR",
925               e);
926         return PLDM_ERROR;
927     }
928     return PLDM_SUCCESS;
929 }
930 
931 const pldm_pdr_record*
fetchLastBMCRecord(const pldm_pdr * repo)932     pldm::responder::oem_ibm_platform::Handler::fetchLastBMCRecord(
933         const pldm_pdr* repo)
934 {
935     return pldm_pdr_find_last_in_range(repo, BMC_PDR_START_RANGE,
936                                        BMC_PDR_END_RANGE);
937 }
938 
checkRecordHandleInRange(const uint32_t & record_handle)939 bool pldm::responder::oem_ibm_platform::Handler::checkRecordHandleInRange(
940     const uint32_t& record_handle)
941 {
942     return record_handle >= HOST_PDR_START_RANGE &&
943            record_handle <= HOST_PDR_END_RANGE;
944 }
945 
processSetEventReceiver()946 void Handler::processSetEventReceiver()
947 {
948     this->setEventReceiver();
949 }
950 
startStopTimer(bool value)951 void pldm::responder::oem_ibm_platform::Handler::startStopTimer(bool value)
952 {
953     if (value)
954     {
955         timer.restart(
956             std::chrono::seconds(HEARTBEAT_TIMEOUT + HEARTBEAT_TIMEOUT_DELTA));
957     }
958     else
959     {
960         timer.setEnabled(value);
961     }
962 }
963 
setSurvTimer(uint8_t tid,bool value)964 void pldm::responder::oem_ibm_platform::Handler::setSurvTimer(uint8_t tid,
965                                                               bool value)
966 {
967     if ((hostOff || hostTransitioningToOff || (tid != HYPERVISOR_TID)) &&
968         timer.isEnabled())
969     {
970         startStopTimer(false);
971         return;
972     }
973     if (value)
974     {
975         startStopTimer(value);
976     }
977     else if (timer.isEnabled())
978     {
979         info(
980             "Failed to stop surveillance timer while remote terminus status is ‘{HOST_TRANST_OFF}’ with Terminus ID ‘{TID}’ ",
981             "HOST_TRANST_OFF", hostTransitioningToOff, "TID", tid);
982         startStopTimer(value);
983         pldm::utils::reportError(
984             "xyz.openbmc_project.PLDM.Error.setSurvTimer.RecvSurveillancePingFail");
985     }
986 }
987 
handleBootTypesAtPowerOn()988 void pldm::responder::oem_ibm_platform::Handler::handleBootTypesAtPowerOn()
989 {
990     PendingAttributesList biosAttrList;
991     auto bootInitiator =
992         getBiosAttrValue<std::string>("pvm_boot_initiator_current")
993             .value_or("");
994     std::string restartCause;
995     if (((bootInitiator != "HMC") || (bootInitiator != "Host")) &&
996         !bootInitiator.empty())
997     {
998         try
999         {
1000             restartCause =
1001                 pldm::utils::DBusHandler().getDbusProperty<std::string>(
1002                     "/xyz/openbmc_project/state/host0",
1003                     HostState::property_names::restart_cause,
1004                     sdbusplus::common::xyz::openbmc_project::state::Host::
1005                         interface);
1006             setBootTypesBiosAttr(restartCause);
1007         }
1008         catch (const std::exception& e)
1009         {
1010             error(
1011                 "Failed to set the D-bus property for the Host restart reason ERROR={ERR}",
1012                 "ERR", e);
1013         }
1014     }
1015 }
1016 
setBootTypesBiosAttr(const std::string & restartCause)1017 void pldm::responder::oem_ibm_platform::Handler::setBootTypesBiosAttr(
1018     const std::string& restartCause)
1019 {
1020     PendingAttributesList biosAttrList;
1021     if (restartCause ==
1022         "xyz.openbmc_project.State.Host.RestartCause.ScheduledPowerOn")
1023     {
1024         biosAttrList.emplace_back(std::make_pair(
1025             "pvm_boot_initiator", std::make_tuple(EnumAttribute, "Host")));
1026         setBiosAttr(biosAttrList);
1027     }
1028     else if (
1029         (restartCause ==
1030          "xyz.openbmc_project.State.Host.RestartCause.PowerPolicyAlwaysOn") ||
1031         (restartCause ==
1032          "xyz.openbmc_project.State.Host.RestartCause.PowerPolicyPreviousState"))
1033     {
1034         biosAttrList.emplace_back(std::make_pair(
1035             "pvm_boot_initiator", std::make_tuple(EnumAttribute, "Auto")));
1036         setBiosAttr(biosAttrList);
1037     }
1038     else if (restartCause ==
1039              "xyz.openbmc_project.State.Host.RestartCause.HostCrash")
1040     {
1041         biosAttrList.emplace_back(std::make_pair(
1042             "pvm_boot_initiator", std::make_tuple(EnumAttribute, "Auto")));
1043         biosAttrList.emplace_back(std::make_pair(
1044             "pvm_boot_type", std::make_tuple(EnumAttribute, "ReIPL")));
1045         setBiosAttr(biosAttrList);
1046     }
1047 }
1048 
handleBootTypesAtChassisOff()1049 void pldm::responder::oem_ibm_platform::Handler::handleBootTypesAtChassisOff()
1050 {
1051     PendingAttributesList biosAttrList;
1052     auto bootInitiator =
1053         getBiosAttrValue<std::string>("pvm_boot_initiator").value_or("");
1054     auto bootType = getBiosAttrValue<std::string>("pvm_boot_type").value_or("");
1055     if (bootInitiator.empty() || bootType.empty())
1056     {
1057         error(
1058             "ERROR in fetching the pvm_boot_initiator and pvm_boot_type BIOS attribute values");
1059         return;
1060     }
1061     else if (bootInitiator != "Host")
1062     {
1063         biosAttrList.emplace_back(std::make_pair(
1064             "pvm_boot_initiator", std::make_tuple(EnumAttribute, "User")));
1065         biosAttrList.emplace_back(std::make_pair(
1066             "pvm_boot_type", std::make_tuple(EnumAttribute, "IPL")));
1067         setBiosAttr(biosAttrList);
1068     }
1069 }
1070 
turnOffRealSAIEffecter()1071 void pldm::responder::oem_ibm_platform::Handler::turnOffRealSAIEffecter()
1072 {
1073     try
1074     {
1075         pldm::utils::DBusMapping dbusPartitionMapping{
1076             "/xyz/openbmc_project/led/groups/partition_system_attention_indicator",
1077             "xyz.openbmc_project.Led.Group", "Asserted", "bool"};
1078         pldm::utils::DBusHandler().setDbusProperty(dbusPartitionMapping, false);
1079     }
1080     catch (const std::exception& e)
1081     {
1082         error("Turn off of partition SAI effecter failed with "
1083               "error:{ERR_EXCEP}",
1084               "ERR_EXCEP", e);
1085     }
1086     try
1087     {
1088         pldm::utils::DBusMapping dbusPlatformMapping{
1089             "/xyz/openbmc_project/led/groups/platform_system_attention_indicator",
1090             "xyz.openbmc_project.Led.Group", "Asserted", "bool"};
1091         pldm::utils::DBusHandler().setDbusProperty(dbusPlatformMapping, false);
1092     }
1093     catch (const std::exception& e)
1094     {
1095         error("Turn off of platform SAI effecter failed with "
1096               "error:{ERR_EXCEP}",
1097               "ERR_EXCEP", e);
1098     }
1099 }
1100 
fetchRealSAIStatus()1101 uint8_t pldm::responder::oem_ibm_platform::Handler::fetchRealSAIStatus()
1102 {
1103     try
1104     {
1105         auto isPartitionSAIOn = pldm::utils::DBusHandler().getDbusProperty<bool>(
1106             "/xyz/openbmc_project/led/groups/partition_system_attention_indicator",
1107             "Asserted", "xyz.openbmc_project.Led.Group");
1108         auto isPlatformSAIOn = pldm::utils::DBusHandler().getDbusProperty<bool>(
1109             "/xyz/openbmc_project/led/groups/platform_system_attention_indicator",
1110             "Asserted", "xyz.openbmc_project.Led.Group");
1111 
1112         if (isPartitionSAIOn || isPlatformSAIOn)
1113         {
1114             return PLDM_SENSOR_WARNING;
1115         }
1116     }
1117     catch (const std::exception& e)
1118     {
1119         error("Fetching of Real SAI sensor status failed with "
1120               "error:{ERR_EXCEP}",
1121               "ERR_EXCEP", e);
1122     }
1123     return PLDM_SENSOR_NORMAL;
1124 }
1125 
processSAIUpdate()1126 void pldm::responder::oem_ibm_platform::Handler::processSAIUpdate()
1127 {
1128     auto realSAIState = fetchRealSAIStatus();
1129     sendStateSensorEvent(realSAISensorId, PLDM_STATE_SENSOR_STATE, 0,
1130                          uint8_t(realSAIState), uint8_t(PLDM_SENSOR_UNKNOWN));
1131 }
1132 
1133 } // namespace oem_ibm_platform
1134 } // namespace responder
1135 } // namespace pldm
1136