xref: /openbmc/pldm/platform-mc/dbus_to_terminus_effecters.cpp (revision f9090f3727a1a7d25c0a29b2c612fe5e3f16689a)
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