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