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 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
isHostOn(void)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
processHostEffecterChangeNotification(const DbusChgHostEffecterProps & chProperties,size_t effecterInfoIndex,size_t dbusInfoIndex,uint16_t effecterId)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
adjustValue(double value,double offset,double resolution,int8_t modify)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
processTerminusNumericEffecterChangeNotification(const DbusChgHostEffecterProps & chProperties,size_t effecterInfoIndex,size_t dbusInfoIndex,uint16_t effecterId)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
findNewStateValue(size_t effecterInfoIndex,size_t dbusInfoIndex,const PropertyValue & propertyValue)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
getEffecterDataSize(uint8_t effecterDataSize)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
setTerminusNumericEffecter(size_t effecterInfoIndex,uint16_t effecterId,uint8_t dataSize,double rawValue)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 instanceId = instanceIdDb->next(mctpEid);
485 int rc = PLDM_ERROR;
486 std::vector<uint8_t> requestMsg;
487
488 /**
489 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES = 4. It includes the 1 byte
490 * value for effecterValue as `Table 48 - SetNumericEffecterValue command
491 * format` DSP0248 V1.3.0 So the payload_length of `SetNumericEffecterValue`
492 * request message will be payload_length =
493 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + sizeof(dataType)
494 */
495 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 +
496 getEffecterDataSize(dataSize);
497 requestMsg.resize(sizeof(pldm_msg_hdr) + payload_length);
498 auto request = new (requestMsg.data()) pldm_msg;
499 switch (dataSize)
500 {
501 case PLDM_EFFECTER_DATA_SIZE_UINT8:
502 {
503 auto value_uint8 = (uint8_t)rawValue;
504 rc = encode_set_numeric_effecter_value_req(
505 instanceId, effecterId, dataSize,
506 reinterpret_cast<uint8_t*>(&value_uint8), request,
507 payload_length);
508 break;
509 }
510 case PLDM_EFFECTER_DATA_SIZE_SINT8:
511 {
512 auto value_int8 = (int8_t)rawValue;
513 rc = encode_set_numeric_effecter_value_req(
514 instanceId, effecterId, dataSize,
515 reinterpret_cast<uint8_t*>(&value_int8), request,
516 payload_length);
517 break;
518 }
519 case PLDM_EFFECTER_DATA_SIZE_UINT16:
520 {
521 auto value_uint16 = (uint16_t)rawValue;
522 rc = encode_set_numeric_effecter_value_req(
523 instanceId, effecterId, dataSize,
524 reinterpret_cast<uint8_t*>(&value_uint16), request,
525 payload_length);
526 break;
527 }
528 case PLDM_EFFECTER_DATA_SIZE_SINT16:
529 {
530 auto value_int16 = (int16_t)rawValue;
531 rc = encode_set_numeric_effecter_value_req(
532 instanceId, effecterId, dataSize,
533 reinterpret_cast<uint8_t*>(&value_int16), request,
534 payload_length);
535 break;
536 }
537 case PLDM_EFFECTER_DATA_SIZE_UINT32:
538 {
539 auto value_uint32 = (uint32_t)rawValue;
540 rc = encode_set_numeric_effecter_value_req(
541 instanceId, effecterId, dataSize,
542 reinterpret_cast<uint8_t*>(&value_uint32), request,
543 payload_length);
544 break;
545 }
546 case PLDM_EFFECTER_DATA_SIZE_SINT32:
547 {
548 auto value_int32 = (int32_t)rawValue;
549 rc = encode_set_numeric_effecter_value_req(
550 instanceId, effecterId, dataSize,
551 reinterpret_cast<uint8_t*>(&value_int32), request,
552 payload_length);
553 break;
554 }
555 default:
556 break;
557 }
558
559 if (rc)
560 {
561 error(
562 "Failed to encode set numeric effecter request message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with error code '{RC}'",
563 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex,
564 rc);
565
566 instanceIdDb->free(mctpEid, instanceId);
567 return rc;
568 }
569
570 auto setNumericEffecterRespHandler = [effecterId](mctp_eid_t /*eid*/,
571 const pldm_msg* response,
572 size_t respMsgLen) {
573 if (response == nullptr || !respMsgLen)
574 {
575 error(
576 "Failed to receive response for setNumericEffecterValue command");
577 return;
578 }
579 uint8_t completionCode{};
580 auto rc = decode_set_numeric_effecter_value_resp(response, respMsgLen,
581 &completionCode);
582
583 if (rc)
584 {
585 error(
586 "Failed to decode set numeric effecter response message for effecter ID '{EFFECTERID}' with error code '{RC}'",
587 "EFFECTERID", effecterId, "RC", lg2::hex, rc);
588 }
589 if (completionCode)
590 {
591 error(
592 "Failed to set numeric effecter for effecter ID '{EFFECTERID}' with complete code '{CC}'",
593 "EFFECTERID", effecterId, "CC", lg2::hex, completionCode);
594 }
595 };
596
597 rc = handler->registerRequest(
598 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE,
599 std::move(requestMsg), std::move(setNumericEffecterRespHandler));
600 if (rc)
601 {
602 error("Failed to send request to set an effecter on Host");
603 }
604 return rc;
605 }
606
setHostStateEffecter(size_t effecterInfoIndex,std::vector<set_effecter_state_field> & stateField,uint16_t effecterId)607 int HostEffecterParser::setHostStateEffecter(
608 size_t effecterInfoIndex, std::vector<set_effecter_state_field>& stateField,
609 uint16_t effecterId)
610 {
611 std::string terminusName = hostEffecterInfo[effecterInfoIndex].terminusName;
612 uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid;
613 if (!terminusName.empty())
614 {
615 auto tmpEid = platformManager->getActiveEidByName(terminusName);
616 if (tmpEid)
617 {
618 mctpEid = tmpEid.value();
619 }
620 }
621
622 uint8_t& compEffCnt = hostEffecterInfo[effecterInfoIndex].compEffecterCnt;
623 auto instanceId = instanceIdDb->next(mctpEid);
624
625 std::vector<uint8_t> requestMsg(
626 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(compEffCnt) +
627 sizeof(set_effecter_state_field) * compEffCnt,
628 0);
629 auto request = new (requestMsg.data()) pldm_msg;
630 auto rc = encode_set_state_effecter_states_req(
631 instanceId, effecterId, compEffCnt, stateField.data(), request);
632
633 if (rc != PLDM_SUCCESS)
634 {
635 error(
636 "Failed to encode set state effecter states message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with response code '{RC}'",
637 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex,
638 rc);
639 instanceIdDb->free(mctpEid, instanceId);
640 return rc;
641 }
642
643 auto setStateEffecterStatesRespHandler = [](mctp_eid_t /*eid*/,
644 const pldm_msg* response,
645 size_t respMsgLen) {
646 if (response == nullptr || !respMsgLen)
647 {
648 error(
649 "Failed to receive response for setting state effecter states.");
650 return;
651 }
652 uint8_t completionCode{};
653 auto rc = decode_set_state_effecter_states_resp(response, respMsgLen,
654 &completionCode);
655 if (rc)
656 {
657 error(
658 "Failed to decode response of set state effecter states, response code '{RC}'",
659 "RC", rc);
660 pldm::utils::reportError(
661 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
662 }
663 if (completionCode)
664 {
665 error(
666 "Failed to set a remote terminus effecter, completion code '{CC}'",
667 "CC", completionCode);
668 pldm::utils::reportError(
669 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
670 }
671 };
672
673 rc = handler->registerRequest(
674 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES,
675 std::move(requestMsg), std::move(setStateEffecterStatesRespHandler));
676 if (rc)
677 {
678 error(
679 "Failed to send request to set an effecter on remote terminus for effecter ID '{EFFECTERID}', response code '{RC}'",
680 "EFFECTERID", effecterId, "RC", rc);
681 }
682 return rc;
683 }
684
createHostEffecterMatch(const std::string & objectPath,const std::string & interface,size_t effecterInfoIndex,size_t dbusInfoIndex,uint16_t effecterId)685 void HostEffecterParser::createHostEffecterMatch(
686 const std::string& objectPath, const std::string& interface,
687 size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId)
688 {
689 using namespace sdbusplus::bus::match::rules;
690 effecterInfoMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>(
691 pldm::utils::DBusHandler::getBus(),
692 propertiesChanged(objectPath, interface),
693 [this, effecterInfoIndex, dbusInfoIndex,
694 effecterId](sdbusplus::message_t& msg) {
695 DbusChgHostEffecterProps props;
696 std::string iface;
697 msg.read(iface, props);
698 processHostEffecterChangeNotification(props, effecterInfoIndex,
699 dbusInfoIndex, effecterId);
700 }));
701 }
702
703 } // namespace host_effecters
704 } // namespace pldm
705