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:: 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:: 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 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 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 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 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 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 451 void pldm::responder::oem_ibm_platform::Handler::setPlatformHandler( 452 pldm::responder::platform::Handler* handler) 453 { 454 platformHandler = handler; 455 } 456 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 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 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 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 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 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 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 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 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 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 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 } 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* 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 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 807 void Handler::processSetEventReceiver() 808 { 809 this->setEventReceiver(); 810 } 811 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 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