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