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