1 #include "utils.hpp"
2
3 #include <libpldm/pdr.h>
4 #include <libpldm/pldm_types.h>
5 #include <linux/mctp.h>
6
7 #include <phosphor-logging/lg2.hpp>
8 #include <xyz/openbmc_project/Common/error.hpp>
9 #include <xyz/openbmc_project/Logging/Create/client.hpp>
10 #include <xyz/openbmc_project/ObjectMapper/client.hpp>
11
12 #include <algorithm>
13 #include <array>
14 #include <cctype>
15 #include <ctime>
16 #include <fstream>
17 #include <iostream>
18 #include <map>
19 #include <stdexcept>
20 #include <string>
21 #include <vector>
22
23 PHOSPHOR_LOG2_USING;
24
25 namespace pldm
26 {
27 namespace utils
28 {
29
30 using ObjectMapper = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>;
31
32 constexpr const char* MCTP_INTERFACE_CC = "au.com.codeconstruct.MCTP.Endpoint1";
33 constexpr const char* MCTP_ENDPOINT_RECOVER_METHOD = "Recover";
34
findStateEffecterPDR(uint8_t,uint16_t entityID,uint16_t stateSetId,const pldm_pdr * repo)35 std::vector<std::vector<uint8_t>> findStateEffecterPDR(
36 uint8_t /*tid*/, uint16_t entityID, uint16_t stateSetId,
37 const pldm_pdr* repo)
38 {
39 uint8_t* outData = nullptr;
40 uint32_t size{};
41 const pldm_pdr_record* record{};
42 std::vector<std::vector<uint8_t>> pdrs;
43 try
44 {
45 do
46 {
47 record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_EFFECTER_PDR,
48 record, &outData, &size);
49 if (record)
50 {
51 auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(outData);
52 auto compositeEffecterCount = pdr->composite_effecter_count;
53 auto possible_states_start = pdr->possible_states;
54
55 for (auto effecters = 0x00; effecters < compositeEffecterCount;
56 effecters++)
57 {
58 auto possibleStates =
59 reinterpret_cast<state_effecter_possible_states*>(
60 possible_states_start);
61 auto setId = possibleStates->state_set_id;
62 auto possibleStateSize =
63 possibleStates->possible_states_size;
64
65 if (pdr->entity_type == entityID && setId == stateSetId)
66 {
67 std::vector<uint8_t> effecter_pdr(&outData[0],
68 &outData[size]);
69 pdrs.emplace_back(std::move(effecter_pdr));
70 break;
71 }
72 possible_states_start += possibleStateSize + sizeof(setId) +
73 sizeof(possibleStateSize);
74 }
75 }
76
77 } while (record);
78 }
79 catch (const std::exception& e)
80 {
81 error("Failed to obtain a record, error - {ERROR}", "ERROR", e);
82 }
83
84 return pdrs;
85 }
86
findStateSensorPDR(uint8_t,uint16_t entityID,uint16_t stateSetId,const pldm_pdr * repo)87 std::vector<std::vector<uint8_t>> findStateSensorPDR(
88 uint8_t /*tid*/, uint16_t entityID, uint16_t stateSetId,
89 const pldm_pdr* repo)
90 {
91 uint8_t* outData = nullptr;
92 uint32_t size{};
93 const pldm_pdr_record* record{};
94 std::vector<std::vector<uint8_t>> pdrs;
95 try
96 {
97 do
98 {
99 record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_SENSOR_PDR,
100 record, &outData, &size);
101 if (record)
102 {
103 auto pdr = reinterpret_cast<pldm_state_sensor_pdr*>(outData);
104 auto compositeSensorCount = pdr->composite_sensor_count;
105 auto possible_states_start = pdr->possible_states;
106
107 for (auto sensors = 0x00; sensors < compositeSensorCount;
108 sensors++)
109 {
110 auto possibleStates =
111 reinterpret_cast<state_sensor_possible_states*>(
112 possible_states_start);
113 auto setId = possibleStates->state_set_id;
114 auto possibleStateSize =
115 possibleStates->possible_states_size;
116
117 if (pdr->entity_type == entityID && setId == stateSetId)
118 {
119 std::vector<uint8_t> sensor_pdr(&outData[0],
120 &outData[size]);
121 pdrs.emplace_back(std::move(sensor_pdr));
122 break;
123 }
124 possible_states_start += possibleStateSize + sizeof(setId) +
125 sizeof(possibleStateSize);
126 }
127 }
128
129 } while (record);
130 }
131 catch (const std::exception& e)
132 {
133 error(
134 "Failed to obtain a record with entity ID '{ENTITYID}', error - {ERROR}",
135 "ENTITYID", entityID, "ERROR", e);
136 }
137
138 return pdrs;
139 }
140
readHostEID()141 uint8_t readHostEID()
142 {
143 uint8_t eid{};
144 std::ifstream eidFile{HOST_EID_PATH};
145 if (!eidFile.good())
146 {
147 error("Failed to open remote terminus EID file at path '{PATH}'",
148 "PATH", static_cast<std::string>(HOST_EID_PATH));
149 }
150 else
151 {
152 std::string eidStr;
153 eidFile >> eidStr;
154 if (!eidStr.empty())
155 {
156 eid = atoi(eidStr.c_str());
157 }
158 else
159 {
160 error("Remote terminus EID file was empty");
161 }
162 }
163
164 return eid;
165 }
166
isValidEID(eid mctpEid)167 bool isValidEID(eid mctpEid)
168 {
169 if (mctpEid == MCTP_ADDR_NULL || mctpEid < MCTP_START_VALID_EID ||
170 mctpEid == MCTP_ADDR_ANY)
171 {
172 return false;
173 }
174
175 return true;
176 }
177
getNumPadBytes(uint32_t data)178 uint8_t getNumPadBytes(uint32_t data)
179 {
180 uint8_t pad;
181 pad = ((data % 4) ? (4 - data % 4) : 0);
182 return pad;
183 } // end getNumPadBytes
184
uintToDate(uint64_t data,uint16_t * year,uint8_t * month,uint8_t * day,uint8_t * hour,uint8_t * min,uint8_t * sec)185 bool uintToDate(uint64_t data, uint16_t* year, uint8_t* month, uint8_t* day,
186 uint8_t* hour, uint8_t* min, uint8_t* sec)
187 {
188 constexpr uint64_t max_data = 29991231115959;
189 constexpr uint64_t min_data = 19700101000000;
190 if (data < min_data || data > max_data)
191 {
192 return false;
193 }
194
195 *year = data / 10000000000;
196 data = data % 10000000000;
197 *month = data / 100000000;
198 data = data % 100000000;
199 *day = data / 1000000;
200 data = data % 1000000;
201 *hour = data / 10000;
202 data = data % 10000;
203 *min = data / 100;
204 *sec = data % 100;
205
206 return true;
207 }
208
parseEffecterData(const std::vector<uint8_t> & effecterData,uint8_t effecterCount)209 std::optional<std::vector<set_effecter_state_field>> parseEffecterData(
210 const std::vector<uint8_t>& effecterData, uint8_t effecterCount)
211 {
212 std::vector<set_effecter_state_field> stateField;
213
214 if (effecterData.size() != effecterCount * 2)
215 {
216 return std::nullopt;
217 }
218
219 for (uint8_t i = 0; i < effecterCount; ++i)
220 {
221 uint8_t set_request = effecterData[i * 2] == PLDM_REQUEST_SET
222 ? PLDM_REQUEST_SET
223 : PLDM_NO_CHANGE;
224 set_effecter_state_field filed{set_request, effecterData[i * 2 + 1]};
225 stateField.emplace_back(std::move(filed));
226 }
227
228 return std::make_optional(std::move(stateField));
229 }
230
getService(const char * path,const char * interface) const231 std::string DBusHandler::getService(const char* path,
232 const char* interface) const
233 {
234 using DbusInterfaceList = std::vector<std::string>;
235 std::map<std::string, std::vector<std::string>> mapperResponse;
236 auto& bus = DBusHandler::getBus();
237
238 auto mapper = bus.new_method_call(ObjectMapper::default_service,
239 ObjectMapper::instance_path,
240 ObjectMapper::interface, "GetObject");
241
242 if (interface)
243 {
244 mapper.append(path, DbusInterfaceList({interface}));
245 }
246 else
247 {
248 mapper.append(path, DbusInterfaceList({}));
249 }
250
251 auto mapperResponseMsg = bus.call(mapper, dbusTimeout);
252 mapperResponseMsg.read(mapperResponse);
253 return mapperResponse.begin()->first;
254 }
255
getSubtree(const std::string & searchPath,int depth,const std::vector<std::string> & ifaceList) const256 GetSubTreeResponse DBusHandler::getSubtree(
257 const std::string& searchPath, int depth,
258 const std::vector<std::string>& ifaceList) const
259 {
260 auto& bus = pldm::utils::DBusHandler::getBus();
261 auto method = bus.new_method_call(ObjectMapper::default_service,
262 ObjectMapper::instance_path,
263 ObjectMapper::interface, "GetSubTree");
264 method.append(searchPath, depth, ifaceList);
265 auto reply = bus.call(method, dbusTimeout);
266 GetSubTreeResponse response;
267 reply.read(response);
268 return response;
269 }
270
getSubTreePaths(const std::string & objectPath,int depth,const std::vector<std::string> & ifaceList) const271 GetSubTreePathsResponse DBusHandler::getSubTreePaths(
272 const std::string& objectPath, int depth,
273 const std::vector<std::string>& ifaceList) const
274 {
275 std::vector<std::string> paths;
276 auto& bus = pldm::utils::DBusHandler::getBus();
277 auto method = bus.new_method_call(
278 ObjectMapper::default_service, ObjectMapper::instance_path,
279 ObjectMapper::interface, "GetSubTreePaths");
280 method.append(objectPath, depth, ifaceList);
281 auto reply = bus.call(method, dbusTimeout);
282
283 reply.read(paths);
284 return paths;
285 }
286
getAncestors(const std::string & path,const std::vector<std::string> & ifaceList) const287 GetAncestorsResponse DBusHandler::getAncestors(
288 const std::string& path, const std::vector<std::string>& ifaceList) const
289 {
290 auto& bus = pldm::utils::DBusHandler::getBus();
291 auto method = bus.new_method_call(ObjectMapper::default_service,
292 ObjectMapper::instance_path,
293 ObjectMapper::interface, "GetAncestors");
294 method.append(path, ifaceList);
295 auto reply = bus.call(method, dbusTimeout);
296 GetAncestorsResponse response;
297 reply.read(response);
298 return response;
299 }
300
reportError(const char * errorMsg)301 void reportError(const char* errorMsg)
302 {
303 auto& bus = pldm::utils::DBusHandler::getBus();
304 using LoggingCreate =
305 sdbusplus::client::xyz::openbmc_project::logging::Create<>;
306 try
307 {
308 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
309 auto severity =
310 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
311 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
312 Error);
313 auto method = bus.new_method_call(LoggingCreate::default_service,
314 LoggingCreate::instance_path,
315 LoggingCreate::interface, "Create");
316
317 std::map<std::string, std::string> addlData{};
318 method.append(errorMsg, severity, addlData);
319 bus.call_noreply(method, dbusTimeout);
320 }
321 catch (const std::exception& e)
322 {
323 error(
324 "Failed to do dbus call for creating error log for '{ERRMSG}' at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}",
325 "ERRMSG", errorMsg, "PATH", LoggingCreate::instance_path,
326 "INTERFACE", LoggingCreate::interface, "ERROR", e);
327 }
328 }
329
setDbusProperty(const DBusMapping & dBusMap,const PropertyValue & value) const330 void DBusHandler::setDbusProperty(const DBusMapping& dBusMap,
331 const PropertyValue& value) const
332 {
333 auto setDbusValue = [&dBusMap, this](const auto& variant) {
334 auto& bus = getBus();
335 auto service =
336 getService(dBusMap.objectPath.c_str(), dBusMap.interface.c_str());
337 auto method = bus.new_method_call(
338 service.c_str(), dBusMap.objectPath.c_str(), dbusProperties, "Set");
339 method.append(dBusMap.interface.c_str(), dBusMap.propertyName.c_str(),
340 variant);
341 bus.call_noreply(method, dbusTimeout);
342 };
343
344 if (dBusMap.propertyType == "uint8_t")
345 {
346 std::variant<uint8_t> v = std::get<uint8_t>(value);
347 setDbusValue(v);
348 }
349 else if (dBusMap.propertyType == "bool")
350 {
351 std::variant<bool> v = std::get<bool>(value);
352 setDbusValue(v);
353 }
354 else if (dBusMap.propertyType == "int16_t")
355 {
356 std::variant<int16_t> v = std::get<int16_t>(value);
357 setDbusValue(v);
358 }
359 else if (dBusMap.propertyType == "uint16_t")
360 {
361 std::variant<uint16_t> v = std::get<uint16_t>(value);
362 setDbusValue(v);
363 }
364 else if (dBusMap.propertyType == "int32_t")
365 {
366 std::variant<int32_t> v = std::get<int32_t>(value);
367 setDbusValue(v);
368 }
369 else if (dBusMap.propertyType == "uint32_t")
370 {
371 std::variant<uint32_t> v = std::get<uint32_t>(value);
372 setDbusValue(v);
373 }
374 else if (dBusMap.propertyType == "int64_t")
375 {
376 std::variant<int64_t> v = std::get<int64_t>(value);
377 setDbusValue(v);
378 }
379 else if (dBusMap.propertyType == "uint64_t")
380 {
381 std::variant<uint64_t> v = std::get<uint64_t>(value);
382 setDbusValue(v);
383 }
384 else if (dBusMap.propertyType == "double")
385 {
386 std::variant<double> v = std::get<double>(value);
387 setDbusValue(v);
388 }
389 else if (dBusMap.propertyType == "string")
390 {
391 std::variant<std::string> v = std::get<std::string>(value);
392 setDbusValue(v);
393 }
394 else
395 {
396 error("Unsupported property type '{TYPE}'", "TYPE",
397 dBusMap.propertyType);
398 throw std::invalid_argument("UnSupported Dbus Type");
399 }
400 }
401
getDbusPropertyVariant(const char * objPath,const char * dbusProp,const char * dbusInterface) const402 PropertyValue DBusHandler::getDbusPropertyVariant(
403 const char* objPath, const char* dbusProp, const char* dbusInterface) const
404 {
405 auto& bus = DBusHandler::getBus();
406 auto service = getService(objPath, dbusInterface);
407 auto method =
408 bus.new_method_call(service.c_str(), objPath, dbusProperties, "Get");
409 method.append(dbusInterface, dbusProp);
410 return bus.call(method, dbusTimeout).unpack<PropertyValue>();
411 }
412
getManagedObj(const char * service,const char * rootPath)413 ObjectValueTree DBusHandler::getManagedObj(const char* service,
414 const char* rootPath)
415 {
416 auto& bus = DBusHandler::getBus();
417 auto method = bus.new_method_call(service, rootPath,
418 "org.freedesktop.DBus.ObjectManager",
419 "GetManagedObjects");
420 return bus.call(method).unpack<ObjectValueTree>();
421 }
422
getDbusPropertiesVariant(const char * serviceName,const char * objPath,const char * dbusInterface) const423 PropertyMap DBusHandler::getDbusPropertiesVariant(
424 const char* serviceName, const char* objPath,
425 const char* dbusInterface) const
426 {
427 auto& bus = DBusHandler::getBus();
428 auto method =
429 bus.new_method_call(serviceName, objPath, dbusProperties, "GetAll");
430 method.append(dbusInterface);
431 return bus.call(method, dbusTimeout).unpack<PropertyMap>();
432 }
433
jsonEntryToDbusVal(std::string_view type,const nlohmann::json & value)434 PropertyValue jsonEntryToDbusVal(std::string_view type,
435 const nlohmann::json& value)
436 {
437 PropertyValue propValue{};
438 if (type == "uint8_t")
439 {
440 propValue = static_cast<uint8_t>(value);
441 }
442 else if (type == "uint16_t")
443 {
444 propValue = static_cast<uint16_t>(value);
445 }
446 else if (type == "uint32_t")
447 {
448 propValue = static_cast<uint32_t>(value);
449 }
450 else if (type == "uint64_t")
451 {
452 propValue = static_cast<uint64_t>(value);
453 }
454 else if (type == "int16_t")
455 {
456 propValue = static_cast<int16_t>(value);
457 }
458 else if (type == "int32_t")
459 {
460 propValue = static_cast<int32_t>(value);
461 }
462 else if (type == "int64_t")
463 {
464 propValue = static_cast<int64_t>(value);
465 }
466 else if (type == "bool")
467 {
468 propValue = static_cast<bool>(value);
469 }
470 else if (type == "double")
471 {
472 propValue = static_cast<double>(value);
473 }
474 else if (type == "string")
475 {
476 propValue = static_cast<std::string>(value);
477 }
478 else
479 {
480 error("Unknown D-Bus property type '{TYPE}'", "TYPE", type);
481 }
482
483 return propValue;
484 }
485
findStateEffecterId(const pldm_pdr * pdrRepo,uint16_t entityType,uint16_t entityInstance,uint16_t containerId,uint16_t stateSetId,bool localOrRemote)486 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType,
487 uint16_t entityInstance, uint16_t containerId,
488 uint16_t stateSetId, bool localOrRemote)
489 {
490 uint8_t* pdrData = nullptr;
491 uint32_t pdrSize{};
492 const pldm_pdr_record* record{};
493 do
494 {
495 record = pldm_pdr_find_record_by_type(pdrRepo, PLDM_STATE_EFFECTER_PDR,
496 record, &pdrData, &pdrSize);
497 if (record && (localOrRemote ^ pldm_pdr_record_is_remote(record)))
498 {
499 auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrData);
500 auto compositeEffecterCount = pdr->composite_effecter_count;
501 auto possible_states_start = pdr->possible_states;
502
503 for (auto effecters = 0x00; effecters < compositeEffecterCount;
504 effecters++)
505 {
506 auto possibleStates =
507 reinterpret_cast<state_effecter_possible_states*>(
508 possible_states_start);
509 auto setId = possibleStates->state_set_id;
510 auto possibleStateSize = possibleStates->possible_states_size;
511
512 if (entityType == pdr->entity_type &&
513 entityInstance == pdr->entity_instance &&
514 containerId == pdr->container_id && stateSetId == setId)
515 {
516 return pdr->effecter_id;
517 }
518 possible_states_start += possibleStateSize + sizeof(setId) +
519 sizeof(possibleStateSize);
520 }
521 }
522 } while (record);
523
524 return PLDM_INVALID_EFFECTER_ID;
525 }
526
emitStateSensorEventSignal(uint8_t tid,uint16_t sensorId,uint8_t sensorOffset,uint8_t eventState,uint8_t previousEventState)527 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId,
528 uint8_t sensorOffset, uint8_t eventState,
529 uint8_t previousEventState)
530 {
531 try
532 {
533 auto& bus = DBusHandler::getBus();
534 auto msg = bus.new_signal("/xyz/openbmc_project/pldm",
535 "xyz.openbmc_project.PLDM.Event",
536 "StateSensorEvent");
537 msg.append(tid, sensorId, sensorOffset, eventState, previousEventState);
538
539 msg.signal_send();
540 }
541 catch (const std::exception& e)
542 {
543 error("Failed to emit pldm event signal, error - {ERROR}", "ERROR", e);
544 return PLDM_ERROR;
545 }
546
547 return PLDM_SUCCESS;
548 }
549
recoverMctpEndpoint(const std::string & endpointObjPath)550 void recoverMctpEndpoint(const std::string& endpointObjPath)
551 {
552 auto& bus = DBusHandler::getBus();
553 try
554 {
555 std::string service = DBusHandler().getService(endpointObjPath.c_str(),
556 MCTP_INTERFACE_CC);
557
558 auto method = bus.new_method_call(
559 service.c_str(), endpointObjPath.c_str(), MCTP_INTERFACE_CC,
560 MCTP_ENDPOINT_RECOVER_METHOD);
561 bus.call_noreply(method, dbusTimeout);
562 }
563 catch (const std::exception& e)
564 {
565 error(
566 "failed to make a D-Bus call to recover MCTP Endpoint, ERROR {ERR_EXCEP}",
567 "ERR_EXCEP", e);
568 }
569 }
570
findStateSensorId(const pldm_pdr * pdrRepo,uint8_t tid,uint16_t entityType,uint16_t entityInstance,uint16_t containerId,uint16_t stateSetId)571 uint16_t findStateSensorId(const pldm_pdr* pdrRepo, uint8_t tid,
572 uint16_t entityType, uint16_t entityInstance,
573 uint16_t containerId, uint16_t stateSetId)
574 {
575 auto pdrs = findStateSensorPDR(tid, entityType, stateSetId, pdrRepo);
576 for (auto pdr : pdrs)
577 {
578 auto sensorPdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdr.data());
579 auto compositeSensorCount = sensorPdr->composite_sensor_count;
580 auto possible_states_start = sensorPdr->possible_states;
581
582 for (auto sensors = 0x00; sensors < compositeSensorCount; sensors++)
583 {
584 auto possibleStates =
585 reinterpret_cast<state_sensor_possible_states*>(
586 possible_states_start);
587 auto setId = possibleStates->state_set_id;
588 auto possibleStateSize = possibleStates->possible_states_size;
589 if (entityType == sensorPdr->entity_type &&
590 entityInstance == sensorPdr->entity_instance &&
591 stateSetId == setId && containerId == sensorPdr->container_id)
592 {
593 return sensorPdr->sensor_id;
594 }
595 possible_states_start +=
596 possibleStateSize + sizeof(setId) + sizeof(possibleStateSize);
597 }
598 }
599 return PLDM_INVALID_EFFECTER_ID;
600 }
601
printBuffer(bool isTx,const std::vector<uint8_t> & buffer)602 void printBuffer(bool isTx, const std::vector<uint8_t>& buffer)
603 {
604 if (buffer.empty())
605 {
606 return;
607 }
608
609 std::cout << (isTx ? "Tx: " : "Rx: ");
610
611 std::ranges::for_each(buffer, [](uint8_t byte) {
612 std::cout << std::format("{:02x} ", byte);
613 });
614
615 std::cout << std::endl;
616 }
617
toString(const struct variable_field & var)618 std::string toString(const struct variable_field& var)
619 {
620 if (var.ptr == nullptr || !var.length)
621 {
622 return "";
623 }
624
625 std::string str(reinterpret_cast<const char*>(var.ptr), var.length);
626 std::replace_if(
627 str.begin(), str.end(), [](const char& c) { return !isprint(c); }, ' ');
628 return str;
629 }
630
split(std::string_view srcStr,std::string_view delim,std::string_view trimStr)631 std::vector<std::string> split(std::string_view srcStr, std::string_view delim,
632 std::string_view trimStr)
633 {
634 std::vector<std::string> out;
635 size_t start;
636 size_t end = 0;
637
638 while ((start = srcStr.find_first_not_of(delim, end)) != std::string::npos)
639 {
640 end = srcStr.find(delim, start);
641 std::string_view dstStr = srcStr.substr(start, end - start);
642 if (!trimStr.empty())
643 {
644 dstStr.remove_prefix(dstStr.find_first_not_of(trimStr));
645 dstStr.remove_suffix(
646 dstStr.size() - 1 - dstStr.find_last_not_of(trimStr));
647 }
648
649 if (!dstStr.empty())
650 {
651 out.push_back(std::string(dstStr));
652 }
653 }
654
655 return out;
656 }
657
getCurrentSystemTime()658 std::string getCurrentSystemTime()
659 {
660 const auto zonedTime{std::chrono::zoned_time{
661 std::chrono::current_zone(), std::chrono::system_clock::now()}};
662 return std::format("{:%F %Z %T}", zonedTime);
663 }
664
checkForFruPresence(const std::string & objPath)665 bool checkForFruPresence(const std::string& objPath)
666 {
667 bool isPresent = false;
668 static constexpr auto presentInterface =
669 "xyz.openbmc_project.Inventory.Item";
670 static constexpr auto presentProperty = "Present";
671 try
672 {
673 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant(
674 objPath.c_str(), presentProperty, presentInterface);
675 isPresent = std::get<bool>(propVal);
676 }
677 catch (const sdbusplus::exception::SdBusError& e)
678 {
679 error("Failed to check for FRU presence at {PATH}, error - {ERROR}",
680 "PATH", objPath, "ERROR", e);
681 }
682 return isPresent;
683 }
684
checkIfLogicalBitSet(const uint16_t & containerId)685 bool checkIfLogicalBitSet(const uint16_t& containerId)
686 {
687 return !(containerId & 0x8000);
688 }
689
setFruPresence(const std::string & fruObjPath,bool present)690 void setFruPresence(const std::string& fruObjPath, bool present)
691 {
692 pldm::utils::PropertyValue value{present};
693 pldm::utils::DBusMapping dbusMapping;
694 dbusMapping.objectPath = fruObjPath;
695 dbusMapping.interface = "xyz.openbmc_project.Inventory.Item";
696 dbusMapping.propertyName = "Present";
697 dbusMapping.propertyType = "bool";
698 try
699 {
700 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
701 }
702 catch (const std::exception& e)
703 {
704 error(
705 "Failed to set the present property on path '{PATH}', error - {ERROR}.",
706 "PATH", fruObjPath, "ERROR", e);
707 }
708 }
709
trimNameForDbus(std::string & name)710 std::string_view trimNameForDbus(std::string& name)
711 {
712 std::replace(name.begin(), name.end(), ' ', '_');
713 auto nullTerminatorPos = name.find('\0');
714 if (nullTerminatorPos != std::string::npos)
715 {
716 name.erase(nullTerminatorPos);
717 }
718 return name;
719 }
720
dbusPropValuesToDouble(const std::string_view & type,const pldm::utils::PropertyValue & value,double * doubleValue)721 bool dbusPropValuesToDouble(const std::string_view& type,
722 const pldm::utils::PropertyValue& value,
723 double* doubleValue)
724 {
725 if (!dbusValueNumericTypeNames.contains(type))
726 {
727 return false;
728 }
729
730 if (!doubleValue)
731 {
732 return false;
733 }
734
735 try
736 {
737 if (type == "uint8_t")
738 {
739 *doubleValue = static_cast<double>(std::get<uint8_t>(value));
740 }
741 else if (type == "int16_t")
742 {
743 *doubleValue = static_cast<double>(std::get<int16_t>(value));
744 }
745 else if (type == "uint16_t")
746 {
747 *doubleValue = static_cast<double>(std::get<uint16_t>(value));
748 }
749 else if (type == "int32_t")
750 {
751 *doubleValue = static_cast<double>(std::get<int32_t>(value));
752 }
753 else if (type == "uint32_t")
754 {
755 *doubleValue = static_cast<double>(std::get<uint32_t>(value));
756 }
757 else if (type == "int64_t")
758 {
759 *doubleValue = static_cast<double>(std::get<int64_t>(value));
760 }
761 else if (type == "uint64_t")
762 {
763 *doubleValue = static_cast<double>(std::get<uint64_t>(value));
764 }
765 else if (type == "double")
766 {
767 *doubleValue = static_cast<double>(std::get<double>(value));
768 }
769 else
770 {
771 return false;
772 }
773 }
774 catch (const std::exception& e)
775 {
776 return false;
777 }
778
779 return true;
780 }
781
fruFieldValuestring(const uint8_t * value,const uint8_t & length)782 std::optional<std::string> fruFieldValuestring(const uint8_t* value,
783 const uint8_t& length)
784 {
785 if (!value || !length)
786 {
787 lg2::error("Fru data to string invalid data.");
788 return std::nullopt;
789 }
790
791 return std::string(reinterpret_cast<const char*>(value), length);
792 }
793
fruFieldParserU32(const uint8_t * value,const uint8_t & length)794 std::optional<uint32_t> fruFieldParserU32(const uint8_t* value,
795 const uint8_t& length)
796 {
797 if (!value || length != sizeof(uint32_t))
798 {
799 lg2::error("Fru data to u32 invalid data.");
800 return std::nullopt;
801 }
802
803 uint32_t ret;
804 std::memcpy(&ret, value, length);
805 return ret;
806 }
807
808 } // namespace utils
809 } // namespace pldm
810