blob: 594e3c4b2789cdfadb17650dbd7ea7c438470675 [file] [log] [blame]
Thu Nguyena34a64b2022-03-31 08:56:39 +07001#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
13PHOSPHOR_LOG2_USING;
14
15using namespace pldm::utils;
16
17namespace pldm
18{
19namespace host_effecters
20{
21using InternalFailure =
22 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
23
24constexpr auto hostEffecterJson = "dbus_to_terminus_effecter.json";
25
26void 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
38void 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);
Thu Nguyen38e12aa2025-01-21 22:47:56 +000070 effecterInfo.terminusName = entry.value("terminus_name", "");
Thu Nguyena34a64b2022-03-31 08:56:39 +070071 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
188bool 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
225void 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
322double 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
329void 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*/
Ed Tanous0469b562025-01-06 12:35:10 -0800371 if (std::isfinite(val) && !std::isfinite(propValues.propertyValue))
Thu Nguyena34a64b2022-03-31 08:56:39 +0700372 {
373 hostEffecterInfo[effecterInfoIndex]
374 .dbusNumericEffecterInfo[dbusInfoIndex]
375 .propertyValue = val;
376 return;
377 }
378
Manojkiran Eda04ac9972024-09-06 10:57:12 +0530379 /* Bypass the setting when the current value is NA or setting value is NA */
Ed Tanous0469b562025-01-06 12:35:10 -0800380 if (!std::isfinite(propValues.propertyValue) || !std::isfinite(val))
Thu Nguyena34a64b2022-03-31 08:56:39 +0700381 {
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
425uint8_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
448size_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
469int HostEffecterParser::setTerminusNumericEffecter(
470 size_t effecterInfoIndex, uint16_t effecterId, uint8_t dataSize,
471 double rawValue)
472{
Thu Nguyen38e12aa2025-01-21 22:47:56 +0000473 std::string terminusName = hostEffecterInfo[effecterInfoIndex].terminusName;
Thu Nguyena34a64b2022-03-31 08:56:39 +0700474 uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid;
Thu Nguyen38e12aa2025-01-21 22:47:56 +0000475 if (!terminusName.empty())
476 {
477 auto tmpEid = platformManager->getActiveEidByName(terminusName);
478 if (tmpEid)
479 {
480 mctpEid = tmpEid.value();
481 }
482 }
483
Eric Yang70262ed2025-07-02 06:35:03 +0000484 auto instanceIdResult =
485 pldm::utils::getInstanceId(instanceIdDb->next(mctpEid));
486 if (!instanceIdResult)
487 {
488 return PLDM_ERROR;
489 }
490 auto instanceId = instanceIdResult.value();
Thu Nguyena34a64b2022-03-31 08:56:39 +0700491 int rc = PLDM_ERROR;
492 std::vector<uint8_t> requestMsg;
493
494 /**
495 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES = 4. It includes the 1 byte
496 * value for effecterValue as `Table 48 - SetNumericEffecterValue command
497 * format` DSP0248 V1.3.0 So the payload_length of `SetNumericEffecterValue`
498 * request message will be payload_length =
499 * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + sizeof(dataType)
500 */
501 size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 +
502 getEffecterDataSize(dataSize);
503 requestMsg.resize(sizeof(pldm_msg_hdr) + payload_length);
Pavithra Barithaya49575832025-01-29 16:27:30 +0530504 auto request = new (requestMsg.data()) pldm_msg;
Thu Nguyena34a64b2022-03-31 08:56:39 +0700505 switch (dataSize)
506 {
507 case PLDM_EFFECTER_DATA_SIZE_UINT8:
508 {
509 auto value_uint8 = (uint8_t)rawValue;
510 rc = encode_set_numeric_effecter_value_req(
511 instanceId, effecterId, dataSize,
512 reinterpret_cast<uint8_t*>(&value_uint8), request,
513 payload_length);
514 break;
515 }
516 case PLDM_EFFECTER_DATA_SIZE_SINT8:
517 {
518 auto value_int8 = (int8_t)rawValue;
519 rc = encode_set_numeric_effecter_value_req(
520 instanceId, effecterId, dataSize,
521 reinterpret_cast<uint8_t*>(&value_int8), request,
522 payload_length);
523 break;
524 }
525 case PLDM_EFFECTER_DATA_SIZE_UINT16:
526 {
527 auto value_uint16 = (uint16_t)rawValue;
528 rc = encode_set_numeric_effecter_value_req(
529 instanceId, effecterId, dataSize,
530 reinterpret_cast<uint8_t*>(&value_uint16), request,
531 payload_length);
532 break;
533 }
534 case PLDM_EFFECTER_DATA_SIZE_SINT16:
535 {
536 auto value_int16 = (int16_t)rawValue;
537 rc = encode_set_numeric_effecter_value_req(
538 instanceId, effecterId, dataSize,
539 reinterpret_cast<uint8_t*>(&value_int16), request,
540 payload_length);
541 break;
542 }
543 case PLDM_EFFECTER_DATA_SIZE_UINT32:
544 {
545 auto value_uint32 = (uint32_t)rawValue;
546 rc = encode_set_numeric_effecter_value_req(
547 instanceId, effecterId, dataSize,
548 reinterpret_cast<uint8_t*>(&value_uint32), request,
549 payload_length);
550 break;
551 }
552 case PLDM_EFFECTER_DATA_SIZE_SINT32:
553 {
554 auto value_int32 = (int32_t)rawValue;
555 rc = encode_set_numeric_effecter_value_req(
556 instanceId, effecterId, dataSize,
557 reinterpret_cast<uint8_t*>(&value_int32), request,
558 payload_length);
559 break;
560 }
561 default:
562 break;
563 }
564
565 if (rc)
566 {
567 error(
568 "Failed to encode set numeric effecter request message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with error code '{RC}'",
569 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex,
570 rc);
571
572 instanceIdDb->free(mctpEid, instanceId);
573 return rc;
574 }
575
576 auto setNumericEffecterRespHandler = [effecterId](mctp_eid_t /*eid*/,
577 const pldm_msg* response,
578 size_t respMsgLen) {
579 if (response == nullptr || !respMsgLen)
580 {
581 error(
582 "Failed to receive response for setNumericEffecterValue command");
583 return;
584 }
585 uint8_t completionCode{};
586 auto rc = decode_set_numeric_effecter_value_resp(response, respMsgLen,
587 &completionCode);
588
589 if (rc)
590 {
591 error(
592 "Failed to decode set numeric effecter response message for effecter ID '{EFFECTERID}' with error code '{RC}'",
593 "EFFECTERID", effecterId, "RC", lg2::hex, rc);
594 }
595 if (completionCode)
596 {
597 error(
598 "Failed to set numeric effecter for effecter ID '{EFFECTERID}' with complete code '{CC}'",
599 "EFFECTERID", effecterId, "CC", lg2::hex, completionCode);
600 }
601 };
602
603 rc = handler->registerRequest(
604 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE,
605 std::move(requestMsg), std::move(setNumericEffecterRespHandler));
606 if (rc)
607 {
608 error("Failed to send request to set an effecter on Host");
609 }
610 return rc;
611}
612
613int HostEffecterParser::setHostStateEffecter(
614 size_t effecterInfoIndex, std::vector<set_effecter_state_field>& stateField,
615 uint16_t effecterId)
616{
Thu Nguyen38e12aa2025-01-21 22:47:56 +0000617 std::string terminusName = hostEffecterInfo[effecterInfoIndex].terminusName;
Thu Nguyena34a64b2022-03-31 08:56:39 +0700618 uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid;
Thu Nguyen38e12aa2025-01-21 22:47:56 +0000619 if (!terminusName.empty())
620 {
621 auto tmpEid = platformManager->getActiveEidByName(terminusName);
622 if (tmpEid)
623 {
624 mctpEid = tmpEid.value();
625 }
626 }
627
Thu Nguyena34a64b2022-03-31 08:56:39 +0700628 uint8_t& compEffCnt = hostEffecterInfo[effecterInfoIndex].compEffecterCnt;
Eric Yang70262ed2025-07-02 06:35:03 +0000629 auto instanceIdResult =
630 pldm::utils::getInstanceId(instanceIdDb->next(mctpEid));
631 if (!instanceIdResult)
632 {
633 return PLDM_ERROR;
634 }
635 auto instanceId = instanceIdResult.value();
Thu Nguyena34a64b2022-03-31 08:56:39 +0700636
637 std::vector<uint8_t> requestMsg(
638 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(compEffCnt) +
639 sizeof(set_effecter_state_field) * compEffCnt,
640 0);
Pavithra Barithaya49575832025-01-29 16:27:30 +0530641 auto request = new (requestMsg.data()) pldm_msg;
Thu Nguyena34a64b2022-03-31 08:56:39 +0700642 auto rc = encode_set_state_effecter_states_req(
643 instanceId, effecterId, compEffCnt, stateField.data(), request);
644
645 if (rc != PLDM_SUCCESS)
646 {
647 error(
648 "Failed to encode set state effecter states message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with response code '{RC}'",
649 "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex,
650 rc);
651 instanceIdDb->free(mctpEid, instanceId);
652 return rc;
653 }
654
655 auto setStateEffecterStatesRespHandler = [](mctp_eid_t /*eid*/,
656 const pldm_msg* response,
657 size_t respMsgLen) {
658 if (response == nullptr || !respMsgLen)
659 {
660 error(
661 "Failed to receive response for setting state effecter states.");
662 return;
663 }
664 uint8_t completionCode{};
665 auto rc = decode_set_state_effecter_states_resp(response, respMsgLen,
666 &completionCode);
667 if (rc)
668 {
669 error(
670 "Failed to decode response of set state effecter states, response code '{RC}'",
671 "RC", rc);
672 pldm::utils::reportError(
673 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
674 }
675 if (completionCode)
676 {
677 error(
678 "Failed to set a remote terminus effecter, completion code '{CC}'",
679 "CC", completionCode);
680 pldm::utils::reportError(
681 "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
682 }
683 };
684
685 rc = handler->registerRequest(
686 mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES,
687 std::move(requestMsg), std::move(setStateEffecterStatesRespHandler));
688 if (rc)
689 {
690 error(
691 "Failed to send request to set an effecter on remote terminus for effecter ID '{EFFECTERID}', response code '{RC}'",
692 "EFFECTERID", effecterId, "RC", rc);
693 }
694 return rc;
695}
696
697void HostEffecterParser::createHostEffecterMatch(
698 const std::string& objectPath, const std::string& interface,
699 size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId)
700{
701 using namespace sdbusplus::bus::match::rules;
702 effecterInfoMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>(
703 pldm::utils::DBusHandler::getBus(),
704 propertiesChanged(objectPath, interface),
705 [this, effecterInfoIndex, dbusInfoIndex,
706 effecterId](sdbusplus::message_t& msg) {
707 DbusChgHostEffecterProps props;
708 std::string iface;
709 msg.read(iface, props);
710 processHostEffecterChangeNotification(props, effecterInfoIndex,
711 dbusInfoIndex, effecterId);
712 }));
713}
714
715} // namespace host_effecters
716} // namespace pldm