xref: /openbmc/pldm/common/utils.cpp (revision 364275c7df5ceb85cea89380f4beace5ae5f9f3e)
1 #include "utils.hpp"
2 
3 #include <libpldm/pdr.h>
4 #include <libpldm/pldm_types.h>
5 #include <linux/mctp.h>
6 
7 #include <xyz/openbmc_project/BIOSConfig/Manager/client.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 using BIOSConfigManager =
32     sdbusplus::client::xyz::openbmc_project::bios_config::Manager<>;
33 
34 constexpr const char* MCTP_INTERFACE_CC = "au.com.codeconstruct.MCTP.Endpoint1";
35 constexpr const char* MCTP_ENDPOINT_RECOVER_METHOD = "Recover";
36 
findStateEffecterPDR(uint8_t,uint16_t entityID,uint16_t stateSetId,const pldm_pdr * repo)37 std::vector<std::vector<uint8_t>> findStateEffecterPDR(
38     uint8_t /*tid*/, uint16_t entityID, uint16_t stateSetId,
39     const pldm_pdr* repo)
40 {
41     uint8_t* outData = nullptr;
42     uint32_t size{};
43     const pldm_pdr_record* record{};
44     std::vector<std::vector<uint8_t>> pdrs;
45     try
46     {
47         do
48         {
49             record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_EFFECTER_PDR,
50                                                   record, &outData, &size);
51             if (record)
52             {
53                 auto pdr = new (outData) pldm_state_effecter_pdr;
54                 auto compositeEffecterCount = pdr->composite_effecter_count;
55                 auto possible_states_start = pdr->possible_states;
56 
57                 for (auto effecters = 0x00; effecters < compositeEffecterCount;
58                      effecters++)
59                 {
60                     auto possibleStates = new (possible_states_start)
61                         state_effecter_possible_states;
62                     auto setId = possibleStates->state_set_id;
63                     auto possibleStateSize =
64                         possibleStates->possible_states_size;
65 
66                     if (pdr->entity_type == entityID && setId == stateSetId)
67                     {
68                         std::vector<uint8_t> effecter_pdr(&outData[0],
69                                                           &outData[size]);
70                         pdrs.emplace_back(std::move(effecter_pdr));
71                         break;
72                     }
73                     possible_states_start += possibleStateSize + sizeof(setId) +
74                                              sizeof(possibleStateSize);
75                 }
76             }
77 
78         } while (record);
79     }
80     catch (const std::exception& e)
81     {
82         error("Failed to obtain a record, error - {ERROR}", "ERROR", e);
83     }
84 
85     return pdrs;
86 }
87 
findStateSensorPDR(uint8_t,uint16_t entityID,uint16_t stateSetId,const pldm_pdr * repo)88 std::vector<std::vector<uint8_t>> findStateSensorPDR(
89     uint8_t /*tid*/, uint16_t entityID, uint16_t stateSetId,
90     const pldm_pdr* repo)
91 {
92     uint8_t* outData = nullptr;
93     uint32_t size{};
94     const pldm_pdr_record* record{};
95     std::vector<std::vector<uint8_t>> pdrs;
96     try
97     {
98         do
99         {
100             record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_SENSOR_PDR,
101                                                   record, &outData, &size);
102             if (record)
103             {
104                 auto pdr = new (outData) pldm_state_sensor_pdr;
105                 auto compositeSensorCount = pdr->composite_sensor_count;
106                 auto possible_states_start = pdr->possible_states;
107 
108                 for (auto sensors = 0x00; sensors < compositeSensorCount;
109                      sensors++)
110                 {
111                     auto possibleStates = new (possible_states_start)
112                         state_sensor_possible_states;
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(
239         ObjectMapper::default_service, ObjectMapper::instance_path,
240         ObjectMapper::interface, ObjectMapper::method_names::get_object);
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(
262         ObjectMapper::default_service, ObjectMapper::instance_path,
263         ObjectMapper::interface, ObjectMapper::method_names::get_sub_tree);
264     method.append(searchPath, depth, ifaceList);
265     auto reply = bus.call(method, dbusTimeout);
266     auto response = reply.unpack<GetSubTreeResponse>();
267 
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,
280         ObjectMapper::method_names::get_sub_tree_paths);
281     method.append(objectPath, depth, ifaceList);
282     auto reply = bus.call(method, dbusTimeout);
283 
284     reply.read(paths);
285     return paths;
286 }
287 
getAncestors(const std::string & path,const std::vector<std::string> & ifaceList) const288 GetAncestorsResponse DBusHandler::getAncestors(
289     const std::string& path, const std::vector<std::string>& ifaceList) const
290 {
291     auto& bus = pldm::utils::DBusHandler::getBus();
292     auto method = bus.new_method_call(
293         ObjectMapper::default_service, ObjectMapper::instance_path,
294         ObjectMapper::interface, ObjectMapper::method_names::get_ancestors);
295     method.append(path, ifaceList);
296     auto reply = bus.call(method, dbusTimeout);
297     auto response = reply.unpack<GetAncestorsResponse>();
298 
299     return response;
300 }
301 
reportError(const char * errorMsg)302 void reportError(const char* errorMsg)
303 {
304     auto& bus = pldm::utils::DBusHandler::getBus();
305     using LoggingCreate =
306         sdbusplus::client::xyz::openbmc_project::logging::Create<>;
307     try
308     {
309         using namespace sdbusplus::xyz::openbmc_project::Logging::server;
310         auto severity =
311             sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
312                 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
313                     Error);
314         auto method = bus.new_method_call(LoggingCreate::default_service,
315                                           LoggingCreate::instance_path,
316                                           LoggingCreate::interface, "Create");
317 
318         std::map<std::string, std::string> addlData{};
319         method.append(errorMsg, severity, addlData);
320         bus.call_noreply(method, dbusTimeout);
321     }
322     catch (const std::exception& e)
323     {
324         error(
325             "Failed to do dbus call for creating error log for '{ERRMSG}' at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}",
326             "ERRMSG", errorMsg, "PATH", LoggingCreate::instance_path,
327             "INTERFACE", LoggingCreate::interface, "ERROR", e);
328     }
329 }
330 
setDbusProperty(const DBusMapping & dBusMap,const PropertyValue & value) const331 void DBusHandler::setDbusProperty(const DBusMapping& dBusMap,
332                                   const PropertyValue& value) const
333 {
334     auto setDbusValue = [&dBusMap, this](const auto& variant) {
335         auto& bus = getBus();
336         auto service =
337             getService(dBusMap.objectPath.c_str(), dBusMap.interface.c_str());
338         auto method = bus.new_method_call(
339             service.c_str(), dBusMap.objectPath.c_str(), dbusProperties, "Set");
340         method.append(dBusMap.interface.c_str(), dBusMap.propertyName.c_str(),
341                       variant);
342         bus.call_noreply(method, dbusTimeout);
343     };
344 
345     if (dBusMap.propertyType == "uint8_t")
346     {
347         std::variant<uint8_t> v = std::get<uint8_t>(value);
348         setDbusValue(v);
349     }
350     else if (dBusMap.propertyType == "bool")
351     {
352         std::variant<bool> v = std::get<bool>(value);
353         setDbusValue(v);
354     }
355     else if (dBusMap.propertyType == "int16_t")
356     {
357         std::variant<int16_t> v = std::get<int16_t>(value);
358         setDbusValue(v);
359     }
360     else if (dBusMap.propertyType == "uint16_t")
361     {
362         std::variant<uint16_t> v = std::get<uint16_t>(value);
363         setDbusValue(v);
364     }
365     else if (dBusMap.propertyType == "int32_t")
366     {
367         std::variant<int32_t> v = std::get<int32_t>(value);
368         setDbusValue(v);
369     }
370     else if (dBusMap.propertyType == "uint32_t")
371     {
372         std::variant<uint32_t> v = std::get<uint32_t>(value);
373         setDbusValue(v);
374     }
375     else if (dBusMap.propertyType == "int64_t")
376     {
377         std::variant<int64_t> v = std::get<int64_t>(value);
378         setDbusValue(v);
379     }
380     else if (dBusMap.propertyType == "uint64_t")
381     {
382         std::variant<uint64_t> v = std::get<uint64_t>(value);
383         setDbusValue(v);
384     }
385     else if (dBusMap.propertyType == "double")
386     {
387         std::variant<double> v = std::get<double>(value);
388         setDbusValue(v);
389     }
390     else if (dBusMap.propertyType == "string")
391     {
392         std::variant<std::string> v = std::get<std::string>(value);
393         setDbusValue(v);
394     }
395     else if (dBusMap.propertyType == "array[string]")
396     {
397         std::variant<std::vector<std::string>> v =
398             std::get<std::vector<std::string>>(value);
399         setDbusValue(v);
400     }
401     else
402     {
403         error("Unsupported property type '{TYPE}'", "TYPE",
404               dBusMap.propertyType);
405         throw std::invalid_argument("UnSupported Dbus Type");
406     }
407 }
408 
getDbusPropertyVariant(const char * objPath,const char * dbusProp,const char * dbusInterface) const409 PropertyValue DBusHandler::getDbusPropertyVariant(
410     const char* objPath, const char* dbusProp, const char* dbusInterface) const
411 {
412     auto& bus = DBusHandler::getBus();
413     auto service = getService(objPath, dbusInterface);
414     auto method =
415         bus.new_method_call(service.c_str(), objPath, dbusProperties, "Get");
416     method.append(dbusInterface, dbusProp);
417     return bus.call(method, dbusTimeout).unpack<PropertyValue>();
418 }
419 
getAssociatedSubTree(const sdbusplus::message::object_path & objectPath,const sdbusplus::message::object_path & subtree,int depth,const std::vector<std::string> & ifaceList) const420 GetAssociatedSubTreeResponse DBusHandler::getAssociatedSubTree(
421     const sdbusplus::message::object_path& objectPath,
422     const sdbusplus::message::object_path& subtree, int depth,
423     const std::vector<std::string>& ifaceList) const
424 {
425     auto& bus = DBusHandler::getBus();
426     auto method = bus.new_method_call(
427         ObjectMapper::default_service, ObjectMapper::instance_path,
428         ObjectMapper::interface,
429         ObjectMapper::method_names::get_associated_sub_tree);
430     method.append(objectPath, subtree, depth, ifaceList);
431     auto reply = bus.call(method, dbusTimeout);
432     auto response = reply.unpack<GetAssociatedSubTreeResponse>();
433 
434     return response;
435 }
436 
getManagedObj(const char * service,const char * rootPath)437 ObjectValueTree DBusHandler::getManagedObj(const char* service,
438                                            const char* rootPath)
439 {
440     auto& bus = DBusHandler::getBus();
441     auto method = bus.new_method_call(service, rootPath,
442                                       "org.freedesktop.DBus.ObjectManager",
443                                       "GetManagedObjects");
444     return bus.call(method).unpack<ObjectValueTree>();
445 }
446 
getDbusPropertiesVariant(const char * serviceName,const char * objPath,const char * dbusInterface) const447 PropertyMap DBusHandler::getDbusPropertiesVariant(
448     const char* serviceName, const char* objPath,
449     const char* dbusInterface) const
450 {
451     auto& bus = DBusHandler::getBus();
452     auto method =
453         bus.new_method_call(serviceName, objPath, dbusProperties, "GetAll");
454     method.append(dbusInterface);
455     return bus.call(method, dbusTimeout).unpack<PropertyMap>();
456 }
457 
jsonEntryToDbusVal(std::string_view type,const nlohmann::json & value)458 PropertyValue jsonEntryToDbusVal(std::string_view type,
459                                  const nlohmann::json& value)
460 {
461     PropertyValue propValue{};
462     if (type == "uint8_t")
463     {
464         propValue = static_cast<uint8_t>(value);
465     }
466     else if (type == "uint16_t")
467     {
468         propValue = static_cast<uint16_t>(value);
469     }
470     else if (type == "uint32_t")
471     {
472         propValue = static_cast<uint32_t>(value);
473     }
474     else if (type == "uint64_t")
475     {
476         propValue = static_cast<uint64_t>(value);
477     }
478     else if (type == "int16_t")
479     {
480         propValue = static_cast<int16_t>(value);
481     }
482     else if (type == "int32_t")
483     {
484         propValue = static_cast<int32_t>(value);
485     }
486     else if (type == "int64_t")
487     {
488         propValue = static_cast<int64_t>(value);
489     }
490     else if (type == "bool")
491     {
492         propValue = static_cast<bool>(value);
493     }
494     else if (type == "double")
495     {
496         propValue = static_cast<double>(value);
497     }
498     else if (type == "string")
499     {
500         propValue = static_cast<std::string>(value);
501     }
502     else
503     {
504         error("Unknown D-Bus property type '{TYPE}'", "TYPE", type);
505     }
506 
507     return propValue;
508 }
509 
findStateEffecterId(const pldm_pdr * pdrRepo,uint16_t entityType,uint16_t entityInstance,uint16_t containerId,uint16_t stateSetId,bool localOrRemote)510 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType,
511                              uint16_t entityInstance, uint16_t containerId,
512                              uint16_t stateSetId, bool localOrRemote)
513 {
514     uint8_t* pdrData = nullptr;
515     uint32_t pdrSize{};
516     const pldm_pdr_record* record{};
517     do
518     {
519         record = pldm_pdr_find_record_by_type(pdrRepo, PLDM_STATE_EFFECTER_PDR,
520                                               record, &pdrData, &pdrSize);
521         if (record && (localOrRemote ^ pldm_pdr_record_is_remote(record)))
522         {
523             auto pdr = new (pdrData) pldm_state_effecter_pdr;
524             auto compositeEffecterCount = pdr->composite_effecter_count;
525             auto possible_states_start = pdr->possible_states;
526 
527             for (auto effecters = 0x00; effecters < compositeEffecterCount;
528                  effecters++)
529             {
530                 auto possibleStates = new (possible_states_start)
531                     state_effecter_possible_states;
532                 auto setId = possibleStates->state_set_id;
533                 auto possibleStateSize = possibleStates->possible_states_size;
534 
535                 if (entityType == pdr->entity_type &&
536                     entityInstance == pdr->entity_instance &&
537                     containerId == pdr->container_id && stateSetId == setId)
538                 {
539                     return pdr->effecter_id;
540                 }
541                 possible_states_start += possibleStateSize + sizeof(setId) +
542                                          sizeof(possibleStateSize);
543             }
544         }
545     } while (record);
546 
547     return PLDM_INVALID_EFFECTER_ID;
548 }
549 
emitStateSensorEventSignal(uint8_t tid,uint16_t sensorId,uint8_t sensorOffset,uint8_t eventState,uint8_t previousEventState)550 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId,
551                                uint8_t sensorOffset, uint8_t eventState,
552                                uint8_t previousEventState)
553 {
554     try
555     {
556         auto& bus = DBusHandler::getBus();
557         auto msg = bus.new_signal("/xyz/openbmc_project/pldm",
558                                   "xyz.openbmc_project.PLDM.Event",
559                                   "StateSensorEvent");
560         msg.append(tid, sensorId, sensorOffset, eventState, previousEventState);
561 
562         msg.signal_send();
563     }
564     catch (const std::exception& e)
565     {
566         error("Failed to emit pldm event signal, error - {ERROR}", "ERROR", e);
567         return PLDM_ERROR;
568     }
569 
570     return PLDM_SUCCESS;
571 }
572 
recoverMctpEndpoint(const std::string & endpointObjPath)573 void recoverMctpEndpoint(const std::string& endpointObjPath)
574 {
575     auto& bus = DBusHandler::getBus();
576     try
577     {
578         std::string service = DBusHandler().getService(endpointObjPath.c_str(),
579                                                        MCTP_INTERFACE_CC);
580 
581         auto method = bus.new_method_call(
582             service.c_str(), endpointObjPath.c_str(), MCTP_INTERFACE_CC,
583             MCTP_ENDPOINT_RECOVER_METHOD);
584         bus.call_noreply(method, dbusTimeout);
585     }
586     catch (const std::exception& e)
587     {
588         error(
589             "failed to make a D-Bus call to recover MCTP Endpoint, ERROR {ERR_EXCEP}",
590             "ERR_EXCEP", e);
591     }
592 }
593 
findStateSensorId(const pldm_pdr * pdrRepo,uint8_t tid,uint16_t entityType,uint16_t entityInstance,uint16_t containerId,uint16_t stateSetId)594 uint16_t findStateSensorId(const pldm_pdr* pdrRepo, uint8_t tid,
595                            uint16_t entityType, uint16_t entityInstance,
596                            uint16_t containerId, uint16_t stateSetId)
597 {
598     auto pdrs = findStateSensorPDR(tid, entityType, stateSetId, pdrRepo);
599     for (auto pdr : pdrs)
600     {
601         auto sensorPdr = new (pdr.data()) pldm_state_sensor_pdr;
602         auto compositeSensorCount = sensorPdr->composite_sensor_count;
603         auto possible_states_start = sensorPdr->possible_states;
604 
605         for (auto sensors = 0x00; sensors < compositeSensorCount; sensors++)
606         {
607             auto possibleStates = new (possible_states_start)
608                 state_sensor_possible_states;
609             auto setId = possibleStates->state_set_id;
610             auto possibleStateSize = possibleStates->possible_states_size;
611             if (entityType == sensorPdr->entity_type &&
612                 entityInstance == sensorPdr->entity_instance &&
613                 stateSetId == setId && containerId == sensorPdr->container_id)
614             {
615                 return sensorPdr->sensor_id;
616             }
617             possible_states_start +=
618                 possibleStateSize + sizeof(setId) + sizeof(possibleStateSize);
619         }
620     }
621     return PLDM_INVALID_EFFECTER_ID;
622 }
623 
printBuffer(bool isTx,const std::vector<uint8_t> & buffer)624 void printBuffer(bool isTx, const std::vector<uint8_t>& buffer)
625 {
626     if (buffer.empty())
627     {
628         return;
629     }
630 
631     std::cout << (isTx ? "Tx: " : "Rx: ");
632 
633     std::ranges::for_each(buffer, [](uint8_t byte) {
634         std::cout << std::format("{:02x} ", byte);
635     });
636 
637     std::cout << std::endl;
638 }
639 
toString(const struct variable_field & var)640 std::string toString(const struct variable_field& var)
641 {
642     if (var.ptr == nullptr || !var.length)
643     {
644         return "";
645     }
646 
647     std::string str(reinterpret_cast<const char*>(var.ptr), var.length);
648     std::replace_if(
649         str.begin(), str.end(), [](const char& c) { return !isprint(c); }, ' ');
650     return str;
651 }
652 
split(std::string_view srcStr,std::string_view delim,std::string_view trimStr)653 std::vector<std::string> split(std::string_view srcStr, std::string_view delim,
654                                std::string_view trimStr)
655 {
656     std::vector<std::string> out;
657     size_t start = 0;
658     size_t end = 0;
659 
660     while ((start = srcStr.find_first_not_of(delim, end)) != std::string::npos)
661     {
662         end = srcStr.find(delim, start);
663         std::string_view dstStr = srcStr.substr(start, end - start);
664         if (!trimStr.empty())
665         {
666             dstStr.remove_prefix(dstStr.find_first_not_of(trimStr));
667             dstStr.remove_suffix(
668                 dstStr.size() - 1 - dstStr.find_last_not_of(trimStr));
669         }
670 
671         if (!dstStr.empty())
672         {
673             out.emplace_back(dstStr);
674         }
675     }
676 
677     return out;
678 }
679 
getCurrentSystemTime()680 std::string getCurrentSystemTime()
681 {
682     const auto zonedTime{std::chrono::zoned_time{
683         std::chrono::current_zone(), std::chrono::system_clock::now()}};
684     return std::format("{:%F %Z %T}", zonedTime);
685 }
686 
checkForFruPresence(const std::string & objPath)687 bool checkForFruPresence(const std::string& objPath)
688 {
689     bool isPresent = false;
690     static constexpr auto presentInterface =
691         "xyz.openbmc_project.Inventory.Item";
692     static constexpr auto presentProperty = "Present";
693     try
694     {
695         auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant(
696             objPath.c_str(), presentProperty, presentInterface);
697         isPresent = std::get<bool>(propVal);
698     }
699     catch (const sdbusplus::exception::SdBusError& e)
700     {
701         error("Failed to check for FRU presence at {PATH}, error - {ERROR}",
702               "PATH", objPath, "ERROR", e);
703     }
704     return isPresent;
705 }
706 
checkIfLogicalBitSet(const uint16_t & containerId)707 bool checkIfLogicalBitSet(const uint16_t& containerId)
708 {
709     return !(containerId & 0x8000);
710 }
711 
setFruPresence(const std::string & fruObjPath,bool present)712 void setFruPresence(const std::string& fruObjPath, bool present)
713 {
714     pldm::utils::PropertyValue value{present};
715     pldm::utils::DBusMapping dbusMapping;
716     dbusMapping.objectPath = fruObjPath;
717     dbusMapping.interface = "xyz.openbmc_project.Inventory.Item";
718     dbusMapping.propertyName = "Present";
719     dbusMapping.propertyType = "bool";
720     try
721     {
722         pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
723     }
724     catch (const std::exception& e)
725     {
726         error(
727             "Failed to set the present property on path '{PATH}', error - {ERROR}.",
728             "PATH", fruObjPath, "ERROR", e);
729     }
730 }
731 
trimNameForDbus(std::string & name)732 std::string_view trimNameForDbus(std::string& name)
733 {
734     std::replace(name.begin(), name.end(), ' ', '_');
735     auto nullTerminatorPos = name.find('\0');
736     if (nullTerminatorPos != std::string::npos)
737     {
738         name.erase(nullTerminatorPos);
739     }
740     return name;
741 }
742 
dbusPropValuesToDouble(const std::string_view & type,const pldm::utils::PropertyValue & value,double * doubleValue)743 bool dbusPropValuesToDouble(const std::string_view& type,
744                             const pldm::utils::PropertyValue& value,
745                             double* doubleValue)
746 {
747     if (!dbusValueNumericTypeNames.contains(type))
748     {
749         return false;
750     }
751 
752     if (!doubleValue)
753     {
754         return false;
755     }
756 
757     try
758     {
759         if (type == "uint8_t")
760         {
761             *doubleValue = static_cast<double>(std::get<uint8_t>(value));
762         }
763         else if (type == "int16_t")
764         {
765             *doubleValue = static_cast<double>(std::get<int16_t>(value));
766         }
767         else if (type == "uint16_t")
768         {
769             *doubleValue = static_cast<double>(std::get<uint16_t>(value));
770         }
771         else if (type == "int32_t")
772         {
773             *doubleValue = static_cast<double>(std::get<int32_t>(value));
774         }
775         else if (type == "uint32_t")
776         {
777             *doubleValue = static_cast<double>(std::get<uint32_t>(value));
778         }
779         else if (type == "int64_t")
780         {
781             *doubleValue = static_cast<double>(std::get<int64_t>(value));
782         }
783         else if (type == "uint64_t")
784         {
785             *doubleValue = static_cast<double>(std::get<uint64_t>(value));
786         }
787         else if (type == "double")
788         {
789             *doubleValue = static_cast<double>(std::get<double>(value));
790         }
791         else
792         {
793             return false;
794         }
795     }
796     catch (const std::exception& e)
797     {
798         return false;
799     }
800 
801     return true;
802 }
803 
fruFieldValuestring(const uint8_t * value,const uint8_t & length)804 std::optional<std::string> fruFieldValuestring(const uint8_t* value,
805                                                const uint8_t& length)
806 {
807     if (!value || !length)
808     {
809         return std::nullopt;
810     }
811 
812     return std::string(reinterpret_cast<const char*>(value), length);
813 }
814 
fruFieldParserU32(const uint8_t * value,const uint8_t & length)815 std::optional<uint32_t> fruFieldParserU32(const uint8_t* value,
816                                           const uint8_t& length)
817 {
818     if (!value || length != sizeof(uint32_t))
819     {
820         lg2::error("Fru data to u32 invalid data.");
821         return std::nullopt;
822     }
823 
824     uint32_t ret;
825     std::memcpy(&ret, value, length);
826     return ret;
827 }
828 
getStateSensorPDRsByType(uint16_t entityType,const pldm_pdr * repo)829 SensorPDRs getStateSensorPDRsByType(uint16_t entityType, const pldm_pdr* repo)
830 {
831     uint8_t* outData = nullptr;
832     uint32_t size{};
833     const pldm_pdr_record* record = nullptr;
834     SensorPDRs pdrs;
835 
836     if (repo)
837     {
838         while ((record = pldm_pdr_find_record_by_type(
839                     repo, PLDM_STATE_SENSOR_PDR, record, &outData, &size)))
840         {
841             auto pdr = new (outData) pldm_state_sensor_pdr;
842             if (pdr && pdr->entity_type == entityType)
843             {
844                 pdrs.emplace_back(outData, outData + size);
845             }
846         }
847     }
848 
849     return pdrs;
850 }
851 
findSensorIds(const pldm_pdr * pdrRepo,uint16_t entityType,uint16_t entityInstance,uint16_t containerId)852 std::vector<pldm::pdr::SensorID> findSensorIds(
853     const pldm_pdr* pdrRepo, uint16_t entityType, uint16_t entityInstance,
854     uint16_t containerId)
855 {
856     std::vector<uint16_t> sensorIDs;
857     auto pdrs = getStateSensorPDRsByType(entityType, pdrRepo);
858 
859     for (const auto& pdr : pdrs)
860     {
861         auto sensorPdr =
862             reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
863 
864         if (sensorPdr && sensorPdr->entity_type == entityType &&
865             sensorPdr->entity_instance == entityInstance &&
866             sensorPdr->container_id == containerId)
867         {
868             sensorIDs.emplace_back(sensorPdr->sensor_id);
869         }
870     }
871 
872     return sensorIDs;
873 }
874 
getStateEffecterPDRsByType(uint16_t entityType,const pldm_pdr * repo)875 EffecterPDRs getStateEffecterPDRsByType(uint16_t entityType,
876                                         const pldm_pdr* repo)
877 {
878     uint8_t* outData = nullptr;
879     uint32_t size{};
880     const pldm_pdr_record* record = nullptr;
881     EffecterPDRs pdrs;
882     if (repo)
883     {
884         while ((record = pldm_pdr_find_record_by_type(
885                     repo, PLDM_STATE_EFFECTER_PDR, record, &outData, &size)))
886         {
887             auto pdr = new (outData) pldm_state_effecter_pdr;
888             if (pdr && pdr->entity_type == entityType)
889             {
890                 pdrs.emplace_back(outData, outData + size);
891             }
892         }
893     }
894     return pdrs;
895 }
896 
findEffecterIds(const pldm_pdr * pdrRepo,uint16_t entityType,uint16_t entityInstance,uint16_t containerId)897 std::vector<pldm::pdr::EffecterID> findEffecterIds(
898     const pldm_pdr* pdrRepo, uint16_t entityType, uint16_t entityInstance,
899     uint16_t containerId)
900 {
901     std::vector<uint16_t> effecterIDs;
902     auto pdrs = getStateEffecterPDRsByType(entityType, pdrRepo);
903     for (const auto& pdr : pdrs)
904     {
905         auto effecterPdr =
906             reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
907         if (effecterPdr && effecterPdr->entity_type == entityType &&
908             effecterPdr->entity_instance == entityInstance &&
909             effecterPdr->container_id == containerId)
910         {
911             effecterIDs.emplace_back(effecterPdr->effecter_id);
912         }
913     }
914     return effecterIDs;
915 }
916 
setBiosAttr(const PendingAttributesList & biosAttrList)917 void setBiosAttr(const PendingAttributesList& biosAttrList)
918 {
919     static constexpr auto SYSTEMD_PROPERTY_INTERFACE =
920         "org.freedesktop.DBus.Properties";
921 
922     for (const auto& [attrName, biosAttrDetails] : biosAttrList)
923     {
924         auto& bus = DBusHandler::getBus();
925         try
926         {
927             auto service = pldm::utils::DBusHandler().getService(
928                 biosConfigPath, BIOSConfigManager::interface);
929             auto method =
930                 bus.new_method_call(service.c_str(), biosConfigPath,
931                                     SYSTEMD_PROPERTY_INTERFACE, "Set");
932             method.append(BIOSConfigManager::interface,
933                           BIOSConfigManager::property_names::pending_attributes,
934                           std::variant<PendingAttributesList>(biosAttrList));
935             bus.call_noreply(method, dbusTimeout);
936         }
937         catch (const sdbusplus::exception::SdBusError& e)
938         {
939             AttributeType attrType;
940             AttributeValue attrValue;
941             std::tie(attrType, attrValue) = biosAttrDetails;
942             if (attrType ==
943                 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer")
944             {
945                 info(
946                     "Error setting the value {VALUE} to bios attribute {BIOS_ATTR}: {ERR_EXCEP}",
947                     "VALUE", std::get<int64_t>(attrValue), "BIOS_ATTR",
948                     attrName, "ERR_EXCEP", e);
949             }
950             else
951             {
952                 info(
953                     "Error setting the value {VALUE} to bios attribute {BIOS_ATTR}: {ERR_EXCEP}",
954                     "VALUE", std::get<std::string>(attrValue), "BIOS_ATTR",
955                     attrName, "ERR_EXCEP", e);
956             }
957         }
958     }
959 }
960 
generateSwId()961 long int generateSwId()
962 {
963     return random() % 10000;
964 }
965 
966 } // namespace utils
967 } // namespace pldm
968