xref: /openbmc/pldm/common/utils.cpp (revision 8fa40dbeb861ba078f5839d65abb4c48c49ece64)
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