1 #include "dbus_to_terminus_effecters.hpp" 2 3 #include <libpldm/pdr.h> 4 #include <libpldm/platform.h> 5 6 #include <phosphor-logging/lg2.hpp> 7 #include <xyz/openbmc_project/Common/error.hpp> 8 #include <xyz/openbmc_project/State/Boot/Progress/client.hpp> 9 #include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp> 10 11 #include <fstream> 12 13 PHOSPHOR_LOG2_USING; 14 15 using namespace pldm::utils; 16 17 namespace pldm 18 { 19 namespace host_effecters 20 { 21 using InternalFailure = 22 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 23 24 constexpr auto hostEffecterJson = "dbus_to_terminus_effecter.json"; 25 26 void HostEffecterParser::populatePropVals( 27 const Json& dBusValues, std::vector<PropertyValue>& propertyValues, 28 const std::string& propertyType) 29 30 { 31 for (const auto& elem : dBusValues) 32 { 33 auto value = jsonEntryToDbusVal(propertyType, elem); 34 propertyValues.emplace_back(value); 35 } 36 } 37 38 void HostEffecterParser::parseEffecterJson(const std::string& jsonPath) 39 { 40 fs::path jsonDir(jsonPath); 41 if (!fs::exists(jsonDir) || fs::is_empty(jsonDir)) 42 { 43 error("Effecter json file for remote terminus '{PATH}' does not exist.", 44 "PATH", jsonPath); 45 return; 46 } 47 48 fs::path jsonFilePath = jsonDir / hostEffecterJson; 49 if (!fs::exists(jsonFilePath)) 50 { 51 error("Json at path '{PATH}' does not exist.", "PATH", jsonFilePath); 52 throw InternalFailure(); 53 } 54 55 std::ifstream jsonFile(jsonFilePath); 56 auto data = Json::parse(jsonFile, nullptr, false); 57 if (data.is_discarded()) 58 { 59 error("Failed to parse json file {PATH}", "PATH", jsonFilePath); 60 throw InternalFailure(); 61 } 62 const Json empty{}; 63 const std::vector<Json> emptyList{}; 64 65 auto entries = data.value("entries", emptyList); 66 for (const auto& entry : entries) 67 { 68 EffecterInfo effecterInfo; 69 effecterInfo.mctpEid = entry.value("mctp_eid", 0xFF); 70 effecterInfo.terminusName = entry.value("terminus_name", ""); 71 auto jsonEffecterInfo = entry.value("effecter_info", empty); 72 auto effecterId = 73 jsonEffecterInfo.value("effecterID", PLDM_INVALID_EFFECTER_ID); 74 /* default as PLDM_STATE_EFFECTER_PDR */ 75 auto effecterPdrType = 76 jsonEffecterInfo.value("effecterPdrType", PLDM_STATE_EFFECTER_PDR); 77 if (effecterPdrType != PLDM_STATE_EFFECTER_PDR && 78 effecterPdrType != PLDM_NUMERIC_EFFECTER_PDR) 79 { 80 error( 81 "Effecter PDRType not supported {TYPE} of effecterID '{EFFECTERID}'", 82 "TYPE", effecterPdrType, "EFFECTERID", effecterId); 83 continue; 84 } 85 effecterInfo.effecterPdrType = effecterPdrType; 86 effecterInfo.containerId = jsonEffecterInfo.value("containerID", 0); 87 effecterInfo.entityType = jsonEffecterInfo.value("entityType", 0); 88 effecterInfo.entityInstance = 89 jsonEffecterInfo.value("entityInstance", 0); 90 effecterInfo.compEffecterCnt = 91 jsonEffecterInfo.value("compositeEffecterCount", 0); 92 effecterInfo.checkHostState = 93 jsonEffecterInfo.value("checkHostState", true); 94 auto effecters = entry.value("effecters", emptyList); 95 96 if (effecterPdrType == PLDM_NUMERIC_EFFECTER_PDR) 97 { 98 for (const auto& effecter : effecters) 99 { 100 DBusNumericEffecterMapping dbusInfo{}; 101 auto jsonDbusInfo = effecter.value("dbus_info", empty); 102 dbusInfo.dataSize = effecter.value("effecterDataSize", 0); 103 dbusInfo.unitModifier = effecter.value("unitModifier", 0); 104 dbusInfo.resolution = effecter.value("resolution", 1); 105 dbusInfo.offset = effecter.value("offset", 0); 106 dbusInfo.dbusMap.objectPath = 107 jsonDbusInfo.value("object_path", ""); 108 dbusInfo.dbusMap.interface = 109 jsonDbusInfo.value("interface", ""); 110 dbusInfo.dbusMap.propertyName = 111 jsonDbusInfo.value("property_name", ""); 112 dbusInfo.dbusMap.propertyType = 113 jsonDbusInfo.value("property_type", ""); 114 /** 115 * Only support these property type for Numeric Effecter D-Bus 116 * property: 117 * "uint8_t", "int16_t", "uint16_t", "int32_t", "uint32_t", 118 * "int64_t", "uint64_t", "double" 119 */ 120 if (!dbusValueNumericTypeNames.contains( 121 dbusInfo.dbusMap.propertyType)) 122 { 123 lg2::error( 124 "Invalid PropertyType {TYPE} of object path {PATH} property name {NAME}", 125 "TYPE", dbusInfo.dbusMap.propertyType, "PATH", 126 dbusInfo.dbusMap.objectPath, "NAME", 127 dbusInfo.dbusMap.propertyName); 128 continue; 129 } 130 131 dbusInfo.propertyValue = 132 std::numeric_limits<double>::quiet_NaN(); 133 auto effecterInfoIndex = hostEffecterInfo.size(); 134 auto dbusInfoIndex = effecterInfo.dbusInfo.size(); 135 createHostEffecterMatch( 136 dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface, 137 effecterInfoIndex, dbusInfoIndex, effecterId); 138 effecterInfo.dbusNumericEffecterInfo.emplace_back( 139 std::move(dbusInfo)); 140 } 141 hostEffecterInfo.emplace_back(std::move(effecterInfo)); 142 continue; 143 } 144 145 for (const auto& effecter : effecters) 146 { 147 DBusEffecterMapping dbusInfo{}; 148 auto jsonDbusInfo = effecter.value("dbus_info", empty); 149 dbusInfo.dbusMap.objectPath = jsonDbusInfo.value("object_path", ""); 150 dbusInfo.dbusMap.interface = jsonDbusInfo.value("interface", ""); 151 dbusInfo.dbusMap.propertyName = 152 jsonDbusInfo.value("property_name", ""); 153 dbusInfo.dbusMap.propertyType = 154 jsonDbusInfo.value("property_type", ""); 155 Json propertyValues = jsonDbusInfo["property_values"]; 156 157 populatePropVals(propertyValues, dbusInfo.propertyValues, 158 dbusInfo.dbusMap.propertyType); 159 160 const std::vector<uint8_t> emptyStates{}; 161 auto state = effecter.value("state", empty); 162 dbusInfo.state.stateSetId = state.value("id", 0); 163 auto states = state.value("state_values", emptyStates); 164 if (dbusInfo.propertyValues.size() != states.size()) 165 { 166 error( 167 "Number of states do not match with number of D-Bus property values in the json. Object path at '{PATH}' and property '{PROPERTY}' will not be monitored", 168 "PATH", dbusInfo.dbusMap.objectPath, "PROPERTY", 169 dbusInfo.dbusMap.propertyName); 170 continue; 171 } 172 for (const auto& s : states) 173 { 174 dbusInfo.state.states.emplace_back(s); 175 } 176 177 auto effecterInfoIndex = hostEffecterInfo.size(); 178 auto dbusInfoIndex = effecterInfo.dbusInfo.size(); 179 createHostEffecterMatch( 180 dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface, 181 effecterInfoIndex, dbusInfoIndex, effecterId); 182 effecterInfo.dbusInfo.emplace_back(std::move(dbusInfo)); 183 } 184 hostEffecterInfo.emplace_back(std::move(effecterInfo)); 185 } 186 } 187 188 bool HostEffecterParser::isHostOn(void) 189 { 190 using BootProgress = 191 sdbusplus::client::xyz::openbmc_project::state::boot::Progress<>; 192 constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0"; 193 try 194 { 195 auto propVal = dbusHandler->getDbusPropertyVariant( 196 hostStatePath, "BootProgress", BootProgress::interface); 197 198 using Stages = BootProgress::ProgressStages; 199 auto currHostState = sdbusplus::message::convert_from_string<Stages>( 200 std::get<std::string>(propVal)) 201 .value(); 202 203 if (currHostState != Stages::SystemInitComplete && 204 currHostState != Stages::OSRunning && 205 currHostState != Stages::SystemSetup && 206 currHostState != Stages::OEM) 207 { 208 info( 209 "Remote terminus is not up/active, current remote terminus state is: '{CURRENT_HOST_STATE}'", 210 "CURRENT_HOST_STATE", currHostState); 211 return false; 212 } 213 } 214 catch (const sdbusplus::exception_t& e) 215 { 216 error( 217 "Error in getting current remote terminus state. Will still continue to set the remote terminus effecter, error - {ERROR}", 218 "ERROR", e); 219 return false; 220 } 221 222 return true; 223 } 224 225 void HostEffecterParser::processHostEffecterChangeNotification( 226 const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex, 227 size_t dbusInfoIndex, uint16_t effecterId) 228 { 229 const auto& pdrType = hostEffecterInfo[effecterInfoIndex].effecterPdrType; 230 if (pdrType == PLDM_NUMERIC_EFFECTER_PDR) 231 { 232 processTerminusNumericEffecterChangeNotification( 233 chProperties, effecterInfoIndex, dbusInfoIndex, effecterId); 234 return; 235 } 236 const auto& propertyName = hostEffecterInfo[effecterInfoIndex] 237 .dbusInfo[dbusInfoIndex] 238 .dbusMap.propertyName; 239 240 const auto& it = chProperties.find(propertyName); 241 242 if (it == chProperties.end()) 243 { 244 return; 245 } 246 247 if (effecterId == PLDM_INVALID_EFFECTER_ID) 248 { 249 constexpr auto localOrRemote = false; 250 effecterId = findStateEffecterId( 251 pdrRepo, hostEffecterInfo[effecterInfoIndex].entityType, 252 hostEffecterInfo[effecterInfoIndex].entityInstance, 253 hostEffecterInfo[effecterInfoIndex].containerId, 254 hostEffecterInfo[effecterInfoIndex] 255 .dbusInfo[dbusInfoIndex] 256 .state.stateSetId, 257 localOrRemote); 258 if (effecterId == PLDM_INVALID_EFFECTER_ID) 259 { 260 error( 261 "Effecter ID '{EFFECTERID}' of entity type '{TYPE}', entityInstance '{INSTANCE}' and containerID '{CONTAINER_ID}' not found in pdr repo", 262 "EFFECTERID", effecterId, "TYPE", 263 hostEffecterInfo[effecterInfoIndex].entityType, "INSTANCE", 264 hostEffecterInfo[effecterInfoIndex].entityInstance, 265 "CONTAINER_ID", 266 hostEffecterInfo[effecterInfoIndex].containerId); 267 return; 268 } 269 } 270 271 if (!isHostOn()) 272 { 273 return; 274 } 275 276 uint8_t newState{}; 277 try 278 { 279 newState = 280 findNewStateValue(effecterInfoIndex, dbusInfoIndex, it->second); 281 } 282 catch (const std::out_of_range& e) 283 { 284 error("Failed to find new state '{NEW_STATE}' in json, error - {ERROR}", 285 "ERROR", e, "NEW_STATE", newState); 286 return; 287 } 288 289 std::vector<set_effecter_state_field> stateField; 290 for (uint8_t i = 0; i < hostEffecterInfo[effecterInfoIndex].compEffecterCnt; 291 i++) 292 { 293 if (i == dbusInfoIndex) 294 { 295 stateField.push_back({PLDM_REQUEST_SET, newState}); 296 } 297 else 298 { 299 stateField.push_back({PLDM_NO_CHANGE, 0}); 300 } 301 } 302 int rc{}; 303 try 304 { 305 rc = setHostStateEffecter(effecterInfoIndex, stateField, effecterId); 306 } 307 catch (const std::runtime_error& e) 308 { 309 error( 310 "Failed to set remote terminus state effecter for effecter ID '{EFFECTERID}', error - {ERROR}", 311 "ERROR", e, "EFFECTERID", effecterId); 312 return; 313 } 314 if (rc != PLDM_SUCCESS) 315 { 316 error( 317 "Failed to set the remote terminus state effecter for effecter ID '{EFFECTERID}', response code '{RC}'", 318 "EFFECTERID", effecterId, "RC", rc); 319 } 320 } 321 322 double HostEffecterParser::adjustValue(double value, double offset, 323 double resolution, int8_t modify) 324 { 325 double unitModifier = std::pow(10, signed(modify)); 326 return std::round((value - offset) * resolution / unitModifier); 327 } 328 329 void HostEffecterParser::processTerminusNumericEffecterChangeNotification( 330 const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex, 331 size_t dbusInfoIndex, uint16_t effecterId) 332 { 333 const auto& checkHost = hostEffecterInfo[effecterInfoIndex].checkHostState; 334 const auto& propValues = hostEffecterInfo[effecterInfoIndex] 335 .dbusNumericEffecterInfo[dbusInfoIndex]; 336 const auto& propertyName = propValues.dbusMap.propertyName; 337 const auto& propertyType = propValues.dbusMap.propertyType; 338 339 if (effecterId == PLDM_INVALID_EFFECTER_ID) 340 { 341 lg2::error( 342 "Dbus to PLDM Numeric Effecter setting requires valid effecter ID. Invalid effecter ID {EFFECTER_ID}", 343 "EFFECTER_ID", effecterId); 344 } 345 346 if (!dbusValueNumericTypeNames.contains(propertyType)) 347 { 348 lg2::error( 349 "DBus Value to PLDM Numeric Effecter setting only supports D-Bus Numeric data type. Invalid type {TYPE}", 350 "TYPE", propertyType); 351 return; 352 } 353 354 const auto& it = chProperties.find(propertyName); 355 356 if (it == chProperties.end()) 357 { 358 return; 359 } 360 361 double val = std::numeric_limits<double>::quiet_NaN(); 362 if (!pldm::utils::dbusPropValuesToDouble(propertyType, it->second, &val)) 363 { 364 lg2::error( 365 "DBus Value to PLDM Numeric Effecter setting only supports Numeric D-Bus data type. Invalid type {TYPE}", 366 "TYPE", propertyType); 367 return; 368 } 369 370 /* Update the current value of D-Bus interface*/ 371 if (std::isfinite(val) && !std::isfinite(propValues.propertyValue)) 372 { 373 hostEffecterInfo[effecterInfoIndex] 374 .dbusNumericEffecterInfo[dbusInfoIndex] 375 .propertyValue = val; 376 return; 377 } 378 379 /* Bypass the setting when the current value is NA or setting value is NA */ 380 if (!std::isfinite(propValues.propertyValue) || !std::isfinite(val)) 381 { 382 return; 383 } 384 385 /* Setting value equals the D-Bus value which is real value of effecter */ 386 if (val == propValues.propertyValue) 387 { 388 return; 389 } 390 391 double rawValue = adjustValue(val, propValues.offset, propValues.resolution, 392 propValues.unitModifier); 393 394 if (checkHost && !isHostOn()) 395 { 396 return; 397 } 398 399 try 400 { 401 auto rc = setTerminusNumericEffecter(effecterInfoIndex, effecterId, 402 propValues.dataSize, rawValue); 403 if (rc) 404 { 405 error( 406 "Could not set the numeric effecter ID '{EFFECTERID}' return code '{RC}'", 407 "EFFECTERID", effecterId, "RC", rc); 408 return; 409 } 410 } 411 catch (const std::runtime_error& e) 412 { 413 error("Could not set numeric effecter ID= '{EFFECTERID}'", "EFFECTERID", 414 effecterId); 415 return; 416 } 417 418 hostEffecterInfo[effecterInfoIndex] 419 .dbusNumericEffecterInfo[dbusInfoIndex] 420 .propertyValue = val; 421 422 return; 423 } 424 425 uint8_t HostEffecterParser::findNewStateValue( 426 size_t effecterInfoIndex, size_t dbusInfoIndex, 427 const PropertyValue& propertyValue) 428 { 429 const auto& propValues = hostEffecterInfo[effecterInfoIndex] 430 .dbusInfo[dbusInfoIndex] 431 .propertyValues; 432 auto it = std::find(propValues.begin(), propValues.end(), propertyValue); 433 uint8_t newState{}; 434 if (it != propValues.end()) 435 { 436 auto index = std::distance(propValues.begin(), it); 437 newState = hostEffecterInfo[effecterInfoIndex] 438 .dbusInfo[dbusInfoIndex] 439 .state.states[index]; 440 } 441 else 442 { 443 throw std::out_of_range("new state not found in json"); 444 } 445 return newState; 446 } 447 448 size_t getEffecterDataSize(uint8_t effecterDataSize) 449 { 450 switch (effecterDataSize) 451 { 452 case PLDM_EFFECTER_DATA_SIZE_UINT8: 453 return sizeof(uint8_t); 454 case PLDM_EFFECTER_DATA_SIZE_SINT8: 455 return sizeof(int8_t); 456 case PLDM_EFFECTER_DATA_SIZE_UINT16: 457 return sizeof(uint16_t); 458 case PLDM_EFFECTER_DATA_SIZE_SINT16: 459 return sizeof(int16_t); 460 case PLDM_EFFECTER_DATA_SIZE_UINT32: 461 return sizeof(uint32_t); 462 case PLDM_EFFECTER_DATA_SIZE_SINT32: 463 return sizeof(int32_t); 464 default: 465 return 0; 466 } 467 } 468 469 int HostEffecterParser::setTerminusNumericEffecter( 470 size_t effecterInfoIndex, uint16_t effecterId, uint8_t dataSize, 471 double rawValue) 472 { 473 std::string terminusName = hostEffecterInfo[effecterInfoIndex].terminusName; 474 uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid; 475 if (!terminusName.empty()) 476 { 477 auto tmpEid = platformManager->getActiveEidByName(terminusName); 478 if (tmpEid) 479 { 480 mctpEid = tmpEid.value(); 481 } 482 } 483 484 auto instanceIdResult = instanceIdDb->next(mctpEid); 485 if (!instanceIdResult) 486 { 487 return PLDM_ERROR; 488 } 489 auto instanceId = instanceIdResult.value(); 490 int rc = PLDM_ERROR; 491 std::vector<uint8_t> requestMsg; 492 493 /** 494 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES = 4. It includes the 1 byte 495 * value for effecterValue as `Table 48 - SetNumericEffecterValue command 496 * format` DSP0248 V1.3.0 So the payload_length of `SetNumericEffecterValue` 497 * request message will be payload_length = 498 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + sizeof(dataType) 499 */ 500 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + 501 getEffecterDataSize(dataSize); 502 requestMsg.resize(sizeof(pldm_msg_hdr) + payload_length); 503 auto request = new (requestMsg.data()) pldm_msg; 504 switch (dataSize) 505 { 506 case PLDM_EFFECTER_DATA_SIZE_UINT8: 507 { 508 auto value_uint8 = (uint8_t)rawValue; 509 rc = encode_set_numeric_effecter_value_req( 510 instanceId, effecterId, dataSize, 511 reinterpret_cast<uint8_t*>(&value_uint8), request, 512 payload_length); 513 break; 514 } 515 case PLDM_EFFECTER_DATA_SIZE_SINT8: 516 { 517 auto value_int8 = (int8_t)rawValue; 518 rc = encode_set_numeric_effecter_value_req( 519 instanceId, effecterId, dataSize, 520 reinterpret_cast<uint8_t*>(&value_int8), request, 521 payload_length); 522 break; 523 } 524 case PLDM_EFFECTER_DATA_SIZE_UINT16: 525 { 526 auto value_uint16 = (uint16_t)rawValue; 527 rc = encode_set_numeric_effecter_value_req( 528 instanceId, effecterId, dataSize, 529 reinterpret_cast<uint8_t*>(&value_uint16), request, 530 payload_length); 531 break; 532 } 533 case PLDM_EFFECTER_DATA_SIZE_SINT16: 534 { 535 auto value_int16 = (int16_t)rawValue; 536 rc = encode_set_numeric_effecter_value_req( 537 instanceId, effecterId, dataSize, 538 reinterpret_cast<uint8_t*>(&value_int16), request, 539 payload_length); 540 break; 541 } 542 case PLDM_EFFECTER_DATA_SIZE_UINT32: 543 { 544 auto value_uint32 = (uint32_t)rawValue; 545 rc = encode_set_numeric_effecter_value_req( 546 instanceId, effecterId, dataSize, 547 reinterpret_cast<uint8_t*>(&value_uint32), request, 548 payload_length); 549 break; 550 } 551 case PLDM_EFFECTER_DATA_SIZE_SINT32: 552 { 553 auto value_int32 = (int32_t)rawValue; 554 rc = encode_set_numeric_effecter_value_req( 555 instanceId, effecterId, dataSize, 556 reinterpret_cast<uint8_t*>(&value_int32), request, 557 payload_length); 558 break; 559 } 560 default: 561 break; 562 } 563 564 if (rc) 565 { 566 error( 567 "Failed to encode set numeric effecter request message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with error code '{RC}'", 568 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex, 569 rc); 570 571 instanceIdDb->free(mctpEid, instanceId); 572 return rc; 573 } 574 575 auto setNumericEffecterRespHandler = [effecterId](mctp_eid_t /*eid*/, 576 const pldm_msg* response, 577 size_t respMsgLen) { 578 if (response == nullptr || !respMsgLen) 579 { 580 error( 581 "Failed to receive response for setNumericEffecterValue command"); 582 return; 583 } 584 uint8_t completionCode{}; 585 auto rc = decode_set_numeric_effecter_value_resp(response, respMsgLen, 586 &completionCode); 587 588 if (rc) 589 { 590 error( 591 "Failed to decode set numeric effecter response message for effecter ID '{EFFECTERID}' with error code '{RC}'", 592 "EFFECTERID", effecterId, "RC", lg2::hex, rc); 593 } 594 if (completionCode) 595 { 596 error( 597 "Failed to set numeric effecter for effecter ID '{EFFECTERID}' with complete code '{CC}'", 598 "EFFECTERID", effecterId, "CC", lg2::hex, completionCode); 599 } 600 }; 601 602 rc = handler->registerRequest( 603 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE, 604 std::move(requestMsg), std::move(setNumericEffecterRespHandler)); 605 if (rc) 606 { 607 error("Failed to send request to set an effecter on Host"); 608 } 609 return rc; 610 } 611 612 int HostEffecterParser::setHostStateEffecter( 613 size_t effecterInfoIndex, std::vector<set_effecter_state_field>& stateField, 614 uint16_t effecterId) 615 { 616 std::string terminusName = hostEffecterInfo[effecterInfoIndex].terminusName; 617 uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid; 618 if (!terminusName.empty()) 619 { 620 auto tmpEid = platformManager->getActiveEidByName(terminusName); 621 if (tmpEid) 622 { 623 mctpEid = tmpEid.value(); 624 } 625 } 626 627 uint8_t& compEffCnt = hostEffecterInfo[effecterInfoIndex].compEffecterCnt; 628 auto instanceIdResult = instanceIdDb->next(mctpEid); 629 if (!instanceIdResult) 630 { 631 return PLDM_ERROR; 632 } 633 auto instanceId = instanceIdResult.value(); 634 635 std::vector<uint8_t> requestMsg( 636 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(compEffCnt) + 637 sizeof(set_effecter_state_field) * compEffCnt, 638 0); 639 auto request = new (requestMsg.data()) pldm_msg; 640 auto rc = encode_set_state_effecter_states_req( 641 instanceId, effecterId, compEffCnt, stateField.data(), request); 642 643 if (rc != PLDM_SUCCESS) 644 { 645 error( 646 "Failed to encode set state effecter states message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with response code '{RC}'", 647 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex, 648 rc); 649 instanceIdDb->free(mctpEid, instanceId); 650 return rc; 651 } 652 653 auto setStateEffecterStatesRespHandler = [](mctp_eid_t /*eid*/, 654 const pldm_msg* response, 655 size_t respMsgLen) { 656 if (response == nullptr || !respMsgLen) 657 { 658 error( 659 "Failed to receive response for setting state effecter states."); 660 return; 661 } 662 uint8_t completionCode{}; 663 auto rc = decode_set_state_effecter_states_resp(response, respMsgLen, 664 &completionCode); 665 if (rc) 666 { 667 error( 668 "Failed to decode response of set state effecter states, response code '{RC}'", 669 "RC", rc); 670 pldm::utils::reportError( 671 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed"); 672 } 673 if (completionCode) 674 { 675 error( 676 "Failed to set a remote terminus effecter, completion code '{CC}'", 677 "CC", completionCode); 678 pldm::utils::reportError( 679 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed"); 680 } 681 }; 682 683 rc = handler->registerRequest( 684 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES, 685 std::move(requestMsg), std::move(setStateEffecterStatesRespHandler)); 686 if (rc) 687 { 688 error( 689 "Failed to send request to set an effecter on remote terminus for effecter ID '{EFFECTERID}', response code '{RC}'", 690 "EFFECTERID", effecterId, "RC", rc); 691 } 692 return rc; 693 } 694 695 void HostEffecterParser::createHostEffecterMatch( 696 const std::string& objectPath, const std::string& interface, 697 size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId) 698 { 699 using namespace sdbusplus::bus::match::rules; 700 effecterInfoMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>( 701 pldm::utils::DBusHandler::getBus(), 702 propertiesChanged(objectPath, interface), 703 [this, effecterInfoIndex, dbusInfoIndex, 704 effecterId](sdbusplus::message_t& msg) { 705 DbusChgHostEffecterProps props; 706 std::string iface; 707 msg.read(iface, props); 708 processHostEffecterChangeNotification(props, effecterInfoIndex, 709 dbusInfoIndex, effecterId); 710 })); 711 } 712 713 } // namespace host_effecters 714 } // namespace pldm 715