1 #pragma once
2
3 #include "types.hpp"
4
5 #include <libpldm/base.h>
6 #include <libpldm/bios.h>
7 #include <libpldm/entity.h>
8 #include <libpldm/pdr.h>
9 #include <libpldm/platform.h>
10 #include <systemd/sd-bus.h>
11 #include <unistd.h>
12
13 #include <nlohmann/json.hpp>
14 #include <phosphor-logging/lg2.hpp>
15 #include <sdbusplus/server.hpp>
16 #include <xyz/openbmc_project/BIOSConfig/Manager/common.hpp>
17 #include <xyz/openbmc_project/Inventory/Manager/client.hpp>
18 #include <xyz/openbmc_project/Logging/Entry/server.hpp>
19 #include <xyz/openbmc_project/ObjectMapper/client.hpp>
20
21 #include <cstdint>
22 #include <deque>
23 #include <exception>
24 #include <filesystem>
25 #include <iostream>
26 #include <map>
27 #include <string>
28 #include <variant>
29 #include <vector>
30
31 constexpr uint64_t dbusTimeout =
32 std::chrono::duration_cast<std::chrono::microseconds>(
33 std::chrono::seconds(DBUS_TIMEOUT))
34 .count();
35
36 PHOSPHOR_LOG2_USING;
37
38 namespace pldm
39 {
40 namespace utils
41 {
42
43 enum class Level
44 {
45 WARNING,
46 CRITICAL,
47 PERFORMANCELOSS,
48 SOFTSHUTDOWN,
49 HARDSHUTDOWN,
50 ERROR
51 };
52 enum class Direction
53 {
54 HIGH,
55 LOW,
56 ERROR
57 };
58
59 const std::set<std::string_view> dbusValueTypeNames = {
60 "bool", "uint8_t", "int16_t", "uint16_t",
61 "int32_t", "uint32_t", "int64_t", "uint64_t",
62 "double", "string", "vector<uint8_t>", "vector<string>"};
63 const std::set<std::string_view> dbusValueNumericTypeNames = {
64 "uint8_t", "int16_t", "uint16_t", "int32_t",
65 "uint32_t", "int64_t", "uint64_t", "double"};
66
67 namespace fs = std::filesystem;
68 using Json = nlohmann::json;
69 constexpr bool Tx = true;
70 constexpr bool Rx = false;
71 using ObjectMapper = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>;
72 using inventoryManager =
73 sdbusplus::client::xyz::openbmc_project::inventory::Manager<>;
74
75 constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
76 constexpr auto mapperService = ObjectMapper::default_service;
77 constexpr auto inventoryPath = "/xyz/openbmc_project/inventory";
78
79 /** @struct CustomFD
80 *
81 * RAII wrapper for file descriptor.
82 */
83 struct CustomFD
84 {
85 CustomFD(const CustomFD&) = delete;
86 CustomFD& operator=(const CustomFD&) = delete;
87 CustomFD(CustomFD&&) = delete;
88 CustomFD& operator=(CustomFD&&) = delete;
89
CustomFDpldm::utils::CustomFD90 CustomFD(int fd) : fd(fd) {}
91
~CustomFDpldm::utils::CustomFD92 ~CustomFD()
93 {
94 if (fd >= 0)
95 {
96 close(fd);
97 }
98 }
99
operator ()pldm::utils::CustomFD100 int operator()() const
101 {
102 return fd;
103 }
104
105 private:
106 int fd = -1;
107 };
108
109 /** @brief Calculate the pad for PLDM data
110 *
111 * @param[in] data - Length of the data
112 * @return - uint8_t - number of pad bytes
113 */
114 uint8_t getNumPadBytes(uint32_t data);
115
116 /** @brief Convert uint64 to date
117 *
118 * @param[in] data - time date of uint64
119 * @param[out] year - year number in dec
120 * @param[out] month - month number in dec
121 * @param[out] day - day of the month in dec
122 * @param[out] hour - number of hours in dec
123 * @param[out] min - number of minutes in dec
124 * @param[out] sec - number of seconds in dec
125 * @return true if decode success, false if decode failed
126 */
127 bool uintToDate(uint64_t data, uint16_t* year, uint8_t* month, uint8_t* day,
128 uint8_t* hour, uint8_t* min, uint8_t* sec);
129
130 /** @brief Convert effecter data to structure of set_effecter_state_field
131 *
132 * @param[in] effecterData - the date of effecter
133 * @param[in] effecterCount - the number of individual sets of effecter
134 * information
135 * @return[out] parse success and get a valid set_effecter_state_field
136 * structure, return nullopt means parse failed
137 */
138 std::optional<std::vector<set_effecter_state_field>> parseEffecterData(
139 const std::vector<uint8_t>& effecterData, uint8_t effecterCount);
140
141 /**
142 * @brief creates an error log
143 * @param[in] errorMsg - the error message
144 */
145 void reportError(const char* errorMsg);
146
147 /** @brief Convert any Decimal number to BCD
148 *
149 * @tparam[in] decimal - Decimal number
150 * @return Corresponding BCD number
151 */
152 template <typename T>
decimalToBcd(T decimal)153 T decimalToBcd(T decimal)
154 {
155 T bcd = 0;
156 T rem = 0;
157 auto cnt = 0;
158
159 while (decimal)
160 {
161 rem = decimal % 10;
162 bcd = bcd + (rem << cnt);
163 decimal = decimal / 10;
164 cnt += 4;
165 }
166
167 return bcd;
168 }
169
170 struct DBusMapping
171 {
172 std::string objectPath; //!< D-Bus object path
173 std::string interface; //!< D-Bus interface
174 std::string propertyName; //!< D-Bus property name
175 std::string propertyType; //!< D-Bus property type
176 };
177
178 using PropertyValue =
179 std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
180 uint64_t, double, std::string, std::vector<uint8_t>,
181 std::vector<uint64_t>, std::vector<std::string>>;
182 using DbusProp = std::string;
183 using DbusChangedProps = std::map<DbusProp, PropertyValue>;
184 using DBusInterfaceAdded = std::vector<
185 std::pair<pldm::dbus::Interface,
186 std::vector<std::pair<pldm::dbus::Property,
187 std::variant<pldm::dbus::Property>>>>>;
188
189 using ObjectPath = std::string;
190 using EntityName = std::string;
191 using Entities = std::vector<pldm_entity_node*>;
192 using EntityAssociations = std::vector<Entities>;
193 using ObjectPathMaps = std::map<fs::path, pldm_entity_node*>;
194 using EntityMaps = std::map<pldm::pdr::EntityType, EntityName>;
195
196 using ServiceName = std::string;
197 using Interfaces = std::vector<std::string>;
198 using MapperServiceMap = std::vector<std::pair<ServiceName, Interfaces>>;
199 using GetSubTreeResponse = std::vector<std::pair<ObjectPath, MapperServiceMap>>;
200 using GetSubTreePathsResponse = std::vector<std::string>;
201 using GetAssociatedSubTreeResponse =
202 std::map<std::string, std::map<std::string, std::vector<std::string>>>;
203 using GetAncestorsResponse =
204 std::vector<std::pair<ObjectPath, MapperServiceMap>>;
205 using PropertyMap = std::map<std::string, PropertyValue>;
206 using InterfaceMap = std::map<std::string, PropertyMap>;
207 using ObjectValueTree = std::map<sdbusplus::message::object_path, InterfaceMap>;
208 using AttributeName = std::string;
209 using AttributeType = std::string;
210 using AttributeValue = std::variant<std::string, int64_t>;
211 using PendingAttributesList = std::vector<
212 std::pair<AttributeName, std::tuple<AttributeType, AttributeValue>>>;
213
214 using SensorPDR = std::vector<uint8_t>;
215 using SensorPDRs = std::vector<SensorPDR>;
216 using EffecterPDR = std::vector<uint8_t>;
217 using EffecterPDRs = std::vector<EffecterPDR>;
218
219 constexpr auto EnumAttribute =
220 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration";
221
222 /**
223 * @brief The interface for DBusHandler
224 */
225 class DBusHandlerInterface
226 {
227 public:
228 virtual ~DBusHandlerInterface() = default;
229
230 virtual std::string getService(const char* path,
231 const char* interface) const = 0;
232 virtual GetSubTreeResponse getSubtree(
233 const std::string& path, int depth,
234 const std::vector<std::string>& ifaceList) const = 0;
235
236 virtual GetSubTreePathsResponse getSubTreePaths(
237 const std::string& objectPath, int depth,
238 const std::vector<std::string>& ifaceList) const = 0;
239
240 virtual GetAncestorsResponse getAncestors(
241 const std::string& path,
242 const std::vector<std::string>& ifaceList) const = 0;
243
244 virtual void setDbusProperty(const DBusMapping& dBusMap,
245 const PropertyValue& value) const = 0;
246
247 virtual PropertyValue getDbusPropertyVariant(
248 const char* objPath, const char* dbusProp,
249 const char* dbusInterface) const = 0;
250
251 virtual PropertyMap getDbusPropertiesVariant(
252 const char* serviceName, const char* objPath,
253 const char* dbusInterface) const = 0;
254
255 virtual GetAssociatedSubTreeResponse getAssociatedSubTree(
256 const sdbusplus::message::object_path& objectPath,
257 const sdbusplus::message::object_path& subtree, int depth,
258 const std::vector<std::string>& ifaceList) const = 0;
259 };
260
261 /**
262 * @class DBusHandler
263 *
264 * Wrapper class to handle the D-Bus calls
265 *
266 * This class contains the APIs to handle the D-Bus calls
267 * to cater the request from pldm requester.
268 * A class is created to mock the apis in the test cases
269 */
270 class DBusHandler : public DBusHandlerInterface
271 {
272 public:
273 /** @brief Get the bus connection. */
getBus()274 static auto& getBus()
275 {
276 static auto bus = sdbusplus::bus::new_default();
277 return bus;
278 }
279
280 /**
281 * @brief Get the DBUS Service name for the input dbus path
282 *
283 * @param[in] path - DBUS object path
284 * @param[in] interface - DBUS Interface
285 *
286 * @return std::string - the dbus service name
287 *
288 * @throw sdbusplus::exception_t when it fails
289 */
290 std::string getService(const char* path,
291 const char* interface) const override;
292
293 /**
294 * @brief Get the Subtree response from the mapper
295 *
296 * @param[in] path - DBUS object path
297 * @param[in] depth - Search depth
298 * @param[in] ifaceList - list of the interface that are being
299 * queried from the mapper
300 *
301 * @return GetSubTreeResponse - the mapper subtree response
302 *
303 * @throw sdbusplus::exception_t when it fails
304 */
305 GetSubTreeResponse getSubtree(
306 const std::string& path, int depth,
307 const std::vector<std::string>& ifaceList) const override;
308
309 /** @brief Get Subtree path response from the mapper
310 *
311 * @param[in] path - DBUS object path
312 * @param[in] depth - Search depth
313 * @param[in] ifaceList - list of the interface that are being
314 * queried from the mapper
315 *
316 * @return std::vector<std::string> vector of subtree paths
317 */
318 GetSubTreePathsResponse getSubTreePaths(
319 const std::string& objectPath, int depth,
320 const std::vector<std::string>& ifaceList) const override;
321
322 /**
323 * @brief Get the Ancestors response from the mapper
324 *
325 * @param[in] path - D-Bus object path
326 * @param[in] ifaceList - an optional list of interfaces to constrain the
327 * search to queried from the mapper
328 *
329 * @return GetAncestorsResponse - the mapper GetAncestors response
330 *
331 * @throw sdbusplus::exception_t when it fails
332 */
333 GetAncestorsResponse getAncestors(
334 const std::string& path,
335 const std::vector<std::string>& ifaceList) const override;
336
337 /** @brief Get property(type: variant) from the requested dbus
338 *
339 * @param[in] objPath - The Dbus object path
340 * @param[in] dbusProp - The property name to get
341 * @param[in] dbusInterface - The Dbus interface
342 *
343 * @return The value of the property(type: variant)
344 *
345 * @throw sdbusplus::exception_t when it fails
346 */
347 PropertyValue getDbusPropertyVariant(
348 const char* objPath, const char* dbusProp,
349 const char* dbusInterface) const override;
350
351 /** @brief Get All properties(type: variant) from the requested dbus
352 *
353 * @param[in] serviceName - The Dbus service name
354 * @param[in] objPath - The Dbus object path
355 * @param[in] dbusInterface - The Dbus interface
356 *
357 * @return The values of the properties(type: variant)
358 *
359 * @throw sdbusplus::exception_t when it fails
360 */
361 PropertyMap getDbusPropertiesVariant(
362 const char* serviceName, const char* objPath,
363 const char* dbusInterface) const override;
364
365 /** @brief The template function to get property from the requested dbus
366 * path
367 *
368 * @tparam Property - Excepted type of the property on dbus
369 *
370 * @param[in] objPath - The Dbus object path
371 * @param[in] dbusProp - The property name to get
372 * @param[in] dbusInterface - The Dbus interface
373 *
374 * @return The value of the property
375 *
376 * @throw sdbusplus::exception_t when dbus request fails
377 * std::bad_variant_access when \p Property and property on dbus do
378 * not match
379 */
380 template <typename Property>
getDbusProperty(const char * objPath,const char * dbusProp,const char * dbusInterface)381 auto getDbusProperty(const char* objPath, const char* dbusProp,
382 const char* dbusInterface)
383 {
384 auto VariantValue =
385 getDbusPropertyVariant(objPath, dbusProp, dbusInterface);
386 return std::get<Property>(VariantValue);
387 }
388
389 /** @brief Get the associated subtree from the mapper
390 *
391 * @param[in] path - The D-Bus object path
392 *
393 * @param[in] interface - The D-Bus interface
394 *
395 * @return GetAssociatedSubtreeResponse - The associated subtree
396 */
397 GetAssociatedSubTreeResponse getAssociatedSubTree(
398 const sdbusplus::message::object_path& objectPath,
399 const sdbusplus::message::object_path& subtree, int depth,
400 const std::vector<std::string>& ifaceList) const override;
401
402 /** @brief Set Dbus property
403 *
404 * @param[in] dBusMap - Object path, property name, interface and property
405 * type for the D-Bus object
406 * @param[in] value - The value to be set
407 *
408 * @throw sdbusplus::exception_t when it fails
409 */
410 void setDbusProperty(const DBusMapping& dBusMap,
411 const PropertyValue& value) const override;
412
413 /** @brief This function retrieves the properties of an object managed
414 * by the specified D-Bus service located at the given object path.
415 *
416 * @param[in] service - The D-Bus service providing the managed object
417 * @param[in] value - The object path of the managed object
418 *
419 * @return A hierarchical structure representing the properties of the
420 * managed object.
421 * @throw sdbusplus::exception_t when it fails
422 */
423 static ObjectValueTree getManagedObj(const char* service, const char* path);
424
425 /** @brief Retrieve the inventory objects managed by a specified class.
426 * The retrieved inventory objects are cached statically
427 * and returned upon subsequent calls to this function.
428 *
429 * @tparam ClassType - The class type that manages the inventory objects.
430 *
431 * @return A reference to the cached inventory objects.
432 */
433 template <typename ClassType>
getInventoryObjects()434 static auto& getInventoryObjects()
435 {
436 static ObjectValueTree object = ClassType::getManagedObj(
437 inventoryManager::interface, inventoryPath);
438 return object;
439 }
440 };
441
442 /** @brief Fetch parent D-Bus object based on pathname
443 *
444 * @param[in] dbusObj - child D-Bus object
445 *
446 * @return std::string - the parent D-Bus object path
447 */
findParent(const std::string & dbusObj)448 inline std::string findParent(const std::string& dbusObj)
449 {
450 fs::path p(dbusObj);
451 return p.parent_path().string();
452 }
453
454 /** @brief Read (static) MCTP EID of host firmware from a file
455 *
456 * @return uint8_t - MCTP EID
457 */
458 uint8_t readHostEID();
459
460 /** @brief Validate the MCTP EID of MCTP endpoint
461 * In `Table 2 - Special endpoint IDs` of DSP0236. EID 0 is NULL_EID.
462 * EID from 1 to 7 is reserved EID. EID 0xFF is broadcast EID.
463 * Those are invalid EID of one MCTP Endpoint.
464 *
465 * @param[in] eid - MCTP EID
466 *
467 * @return true if the MCTP EID is valid otherwise return false.
468 */
469 bool isValidEID(eid mctpEid);
470
471 /** @brief Convert a value in the JSON to a D-Bus property value
472 *
473 * @param[in] type - type of the D-Bus property
474 * @param[in] value - value in the JSON file
475 *
476 * @return PropertyValue - the D-Bus property value
477 */
478 PropertyValue jsonEntryToDbusVal(std::string_view type,
479 const nlohmann::json& value);
480
481 /** @brief Find State Effecter PDR
482 * @param[in] tid - PLDM terminus ID.
483 * @param[in] entityID - entity that can be associated with PLDM State set.
484 * @param[in] stateSetId - value that identifies PLDM State set.
485 * @param[in] repo - pointer to BMC's primary PDR repo.
486 * @return array[array[uint8_t]] - StateEffecterPDRs
487 */
488 std::vector<std::vector<uint8_t>> findStateEffecterPDR(
489 uint8_t tid, uint16_t entityID, uint16_t stateSetId, const pldm_pdr* repo);
490 /** @brief Find State Sensor PDR
491 * @param[in] tid - PLDM terminus ID.
492 * @param[in] entityID - entity that can be associated with PLDM State set.
493 * @param[in] stateSetId - value that identifies PLDM State set.
494 * @param[in] repo - pointer to BMC's primary PDR repo.
495 * @return array[array[uint8_t]] - StateSensorPDRs
496 */
497 std::vector<std::vector<uint8_t>> findStateSensorPDR(
498 uint8_t tid, uint16_t entityID, uint16_t stateSetId, const pldm_pdr* repo);
499
500 /** @brief Find sensor id from a state sensor PDR
501 *
502 * @param[in] pdrRepo - PDR repository
503 * @param[in] tid - terminus id
504 * @param[in] entityType - entity type
505 * @param[in] entityInstance - entity instance number
506 * @param[in] containerId - container id
507 * @param[in] stateSetId - state set id
508 *
509 * @return uint16_t - the sensor id
510 */
511 uint16_t findStateSensorId(const pldm_pdr* pdrRepo, uint8_t tid,
512 uint16_t entityType, uint16_t entityInstance,
513 uint16_t containerId, uint16_t stateSetId);
514
515 /** @brief Find effecter id from a state effecter pdr
516 * @param[in] pdrRepo - PDR repository
517 * @param[in] entityType - entity type
518 * @param[in] entityInstance - entity instance number
519 * @param[in] containerId - container id
520 * @param[in] stateSetId - state set id
521 * @param[in] localOrRemote - true for checking local repo and false for remote
522 * repo
523 *
524 * @return uint16_t - the effecter id
525 */
526 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType,
527 uint16_t entityInstance, uint16_t containerId,
528 uint16_t stateSetId, bool localOrRemote);
529
530 /** @brief Method to find all state sensor PDRs by type
531 *
532 * @param[in] entityType - the entity type
533 * @param[in] repo - opaque pointer acting as a PDR repo handle
534 *
535 * @return vector of vector of all state sensor PDRs
536 */
537 SensorPDRs getStateSensorPDRsByType(uint16_t entityType, const pldm_pdr* repo);
538
539 /** @brief method to find sensor IDs based on the pldm_entity
540 *
541 * @param[in] pdrRepo - opaque pointer acting as a PDR repo handle
542 * @param[in] entityType - the entity type
543 * @param[in] entityInstance - the entity instance number
544 * @param[in] containerId - the container ID
545 *
546 * @return vector of all sensor IDs
547 */
548 std::vector<pldm::pdr::SensorID> findSensorIds(
549 const pldm_pdr* pdrRepo, uint16_t entityType, uint16_t entityInstance,
550 uint16_t containerId);
551
552 /** @brief Method to find all state effecter PDRs by type
553 *
554 * @param[in] entityType - the entity type
555 * @param[in] repo - opaque pointer acting as a PDR repo handle
556 *
557 * @return vector of vector of all state effecter PDRs
558 */
559 EffecterPDRs getStateEffecterPDRsByType(uint16_t entityType,
560 const pldm_pdr* repo);
561
562 /** @brief method to find effecter IDs based on the pldm_entity
563 *
564 * @param[in] pdrRepo - opaque pointer acting as a PDR repo handle
565 * @param[in] entityType - the entity type
566 * @param[in] entityInstance - the entity instance number
567 * @param[in] containerId - the container ID
568 *
569 * @return vector of all effecter IDs
570 */
571 std::vector<pldm::pdr::EffecterID> findEffecterIds(
572 const pldm_pdr* pdrRepo, uint16_t entityType, uint16_t entityInstance,
573 uint16_t containerId);
574
575 /** @brief Emit the sensor event signal
576 *
577 * @param[in] tid - the terminus id
578 * @param[in] sensorId - sensorID value of the sensor
579 * @param[in] sensorOffset - Identifies which state sensor within a
580 * composite state sensor the event is being returned for
581 * @param[in] eventState - The event state value from the state change that
582 * triggered the event message
583 * @param[in] previousEventState - The event state value for the state from
584 * which the present event state was entered.
585 * @return PLDM completion code
586 */
587 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId,
588 uint8_t sensorOffset, uint8_t eventState,
589 uint8_t previousEventState);
590
591 /**
592 * @brief call Recover() method to recover an MCTP Endpoint
593 * @param[in] MCTP Endpoint's object path
594 */
595 void recoverMctpEndpoint(const std::string& endpointObjPath);
596
597 /** @brief Print the buffer
598 *
599 * @param[in] isTx - True if the buffer is an outgoing PLDM message, false if
600 the buffer is an incoming PLDM message
601 * @param[in] buffer - Buffer to print
602 *
603 * @return - None
604 */
605 void printBuffer(bool isTx, const std::vector<uint8_t>& buffer);
606
607 /** @brief Convert the buffer to std::string
608 *
609 * If there are characters that are not printable characters, it is replaced
610 * with space(0x20).
611 *
612 * @param[in] var - pointer to data and length of the data
613 *
614 * @return std::string equivalent of variable field
615 */
616 std::string toString(const struct variable_field& var);
617
618 /** @brief Split strings according to special identifiers
619 *
620 * We can split the string according to the custom identifier(';', ',', '&' or
621 * others) and store it to vector.
622 *
623 * @param[in] srcStr - The string to be split
624 * @param[in] delim - The custom identifier
625 * @param[in] trimStr - The first and last string to be trimmed
626 *
627 * @return std::vector<std::string> Vectors are used to store strings
628 */
629 std::vector<std::string> split(std::string_view srcStr, std::string_view delim,
630 std::string_view trimStr = "");
631 /** @brief Get the current system time in readable format
632 *
633 * @return - std::string equivalent of the system time
634 */
635 std::string getCurrentSystemTime();
636
637 /** @brief checks if the FRU is actually present.
638 * @param[in] objPath - FRU object path.
639 *
640 * @return bool to indicate presence or absence of FRU.
641 */
642 bool checkForFruPresence(const std::string& objPath);
643
644 /** @brief Method to check if the logical bit is set
645 *
646 * @param[containerId] - container id of the entity
647 *
648 * @return true or false based on the logic bit set
649 */
650 bool checkIfLogicalBitSet(const uint16_t& containerId);
651
652 /** @brief setting the present property
653 *
654 * @param[in] objPath - the object path of the fru
655 * @param[in] present - status to set either true/false
656 */
657 void setFruPresence(const std::string& fruObjPath, bool present);
658
659 /** @brief Trim `\0` in string and replace ` ` by `_` to use name in D-Bus
660 * object path
661 *
662 * @param[in] name - the input string
663 *
664 * @return the result string
665 */
666 std::string_view trimNameForDbus(std::string& name);
667
668 /** @brief Convert the number type D-Bus Value to the double
669 *
670 * @param[in] type - string type should in dbusValueNumericTypeNames list
671 * @param[in] value - DBus PropertyValue variant
672 * @param[out] doubleValue - response value
673 *
674 * @return true if data type is corrected and converting is successful
675 * otherwise return false.
676 */
677 bool dbusPropValuesToDouble(const std::string_view& type,
678 const pldm::utils::PropertyValue& value,
679 double* doubleValue);
680
681 /** @brief Convert the Fru String bytes from PLDM Fru to std::string
682 *
683 * @param[in] value - the Fru String bytes
684 * @param[in] length - Number of bytes
685 *
686 * @return Fru string or nullopt.
687 */
688 std::optional<std::string> fruFieldValuestring(const uint8_t* value,
689 const uint8_t& length);
690
691 /** @brief Convert the Fru Uint32 raw data from PLDM Fru to uint32_t
692 *
693 * @param[in] value - the Fru uint32 raw data
694 * @param[in] length - Number of bytes
695 *
696 * @return Fru uint32_t or nullopt.
697 */
698 std::optional<uint32_t> fruFieldParserU32(const uint8_t* value,
699 const uint8_t& length);
700
701 /**
702 * @brief Get a random ID for firmware inventory entry
703 * @return Random ID as long integer
704 */
705 long int generateSwId();
706
707 constexpr auto biosConfigPath = "/xyz/openbmc_project/bios_config/manager";
708
709 /** @brief Method to get the value from a bios attribute
710 *
711 * @param[in] dbusAttrName - the bios attribute name from
712 * which the value must be retrieved
713 *
714 * @return the attribute value
715 */
716 template <typename T>
getBiosAttrValue(const std::string & dbusAttrName)717 std::optional<T> getBiosAttrValue(const std::string& dbusAttrName)
718 {
719 using BIOSConfigManager =
720 sdbusplus::common::xyz::openbmc_project::bios_config::Manager;
721
722 std::string var1;
723 std::variant<std::string, int64_t> var2, var3;
724 auto& bus = DBusHandler::getBus();
725 try
726 {
727 auto service = pldm::utils::DBusHandler().getService(
728 biosConfigPath, BIOSConfigManager::interface);
729 auto method = bus.new_method_call(
730 service.c_str(), biosConfigPath, BIOSConfigManager::interface,
731 BIOSConfigManager::method_names::get_attribute);
732 method.append(dbusAttrName);
733 auto reply = bus.call(method, dbusTimeout);
734 reply.read(var1, var2, var3);
735 if (auto ptr = std::get_if<T>(&var2))
736 {
737 return *ptr;
738 }
739 }
740 catch (const sdbusplus::exception::SdBusError& e)
741 {
742 info("Error getting the bios attribute {BIOS_ATTR}: {ERR_EXCEP}",
743 "BIOS_ATTR", dbusAttrName, "ERR_EXCEP", e);
744 }
745
746 return std::nullopt;
747 }
748
749 /** @brief Method to set the specified bios attribute with
750 * specified value
751 *
752 * @param[in] PendingAttributesList - the list of bios attribute and values
753 * to be set
754 */
755 void setBiosAttr(const PendingAttributesList& biosAttrList);
756
757 } // namespace utils
758 } // namespace pldm
759