1 #pragma once
2 
3 #include "dbus_types.hpp"
4 #include "dbus_watcher.hpp"
5 
6 #ifdef PEL_ENABLE_PHAL
7 #include <libguard/guard_interface.hpp>
8 #include <libguard/include/guard_record.hpp>
9 #endif
10 
11 #include <phosphor-logging/lg2.hpp>
12 #include <sdbusplus/bus.hpp>
13 #include <sdbusplus/bus/match.hpp>
14 
15 #include <expected>
16 #include <filesystem>
17 #include <fstream>
18 #include <unordered_map>
19 
20 #ifdef PEL_ENABLE_PHAL
21 using GardType = openpower::guard::GardType;
22 namespace libguard = openpower::guard;
23 #endif
24 
25 namespace openpower
26 {
27 namespace pels
28 {
29 
30 /**
31  * @class DataInterface
32  *
33  * A base class for gathering data about the system for use
34  * in PELs. Implemented this way to facilitate mocking.
35  */
36 class DataInterfaceBase
37 {
38   public:
39     DataInterfaceBase() = default;
40     virtual ~DataInterfaceBase() = default;
41     DataInterfaceBase(const DataInterfaceBase&) = default;
42     DataInterfaceBase& operator=(const DataInterfaceBase&) = default;
43     DataInterfaceBase(DataInterfaceBase&&) = default;
44     DataInterfaceBase& operator=(DataInterfaceBase&&) = default;
45 
46     /**
47      * @brief Returns the machine Type/Model
48      *
49      * @return string - The machine Type/Model string
50      */
51     virtual std::string getMachineTypeModel() const = 0;
52 
53     /**
54      * @brief Returns the machine serial number
55      *
56      * @return string - The machine serial number
57      */
58     virtual std::string getMachineSerialNumber() const = 0;
59 
60     /**
61      * @brief Says if the system is managed by a hardware
62      *        management console.
63      * @return bool - If the system is HMC managed
64      */
isHMCManaged() const65     virtual bool isHMCManaged() const
66     {
67         return _hmcManaged;
68     }
69 
70     /**
71      * @brief Says if the host is up and running
72      *
73      * @return bool - If the host is running
74      */
isHostUp() const75     virtual bool isHostUp() const
76     {
77         return _hostUp;
78     }
79 
80     using HostStateChangeFunc = std::function<void(bool)>;
81 
82     /**
83      * @brief Register a callback function that will get
84      *        called on all host on/off transitions.
85      *
86      * The void(bool) function will get passed the new
87      * value of the host state.
88      *
89      * @param[in] name - The subscription name
90      * @param[in] func - The function to run
91      */
subscribeToHostStateChange(const std::string & name,HostStateChangeFunc func)92     void subscribeToHostStateChange(const std::string& name,
93                                     HostStateChangeFunc func)
94     {
95         _hostChangeCallbacks[name] = func;
96     }
97 
98     /**
99      * @brief Unsubscribe from host state changes.
100      *
101      * @param[in] name - The subscription name
102      */
unsubscribeFromHostStateChange(const std::string & name)103     void unsubscribeFromHostStateChange(const std::string& name)
104     {
105         _hostChangeCallbacks.erase(name);
106     }
107 
108     using FRUPresentFunc =
109         std::function<void(const std::string& /* locationCode */)>;
110 
111     /**
112      * @brief Register a callback function that will get
113      *        called when certain FRUs become present.
114      *
115      * The void(std::string) function will get passed the
116      * location code of the FRU.
117      *
118      * @param[in] name - The subscription name
119      * @param[in] func - The function to run
120      */
subscribeToFruPresent(const std::string & name,FRUPresentFunc func)121     void subscribeToFruPresent(const std::string& name, FRUPresentFunc func)
122     {
123         _fruPresentCallbacks[name] = std::move(func);
124     }
125 
126     /**
127      * @brief Returns the BMC firmware version
128      *
129      * @return std::string - The BMC version
130      */
getBMCFWVersion() const131     virtual std::string getBMCFWVersion() const
132     {
133         return _bmcFWVersion;
134     }
135 
136     /**
137      * @brief Returns the server firmware version
138      *
139      * @return std::string - The server firmware version
140      */
getServerFWVersion() const141     virtual std::string getServerFWVersion() const
142     {
143         return _serverFWVersion;
144     }
145 
146     /**
147      * @brief Returns the BMC FW version ID
148      *
149      * @return std::string - The BMC FW version ID
150      */
getBMCFWVersionID() const151     virtual std::string getBMCFWVersionID() const
152     {
153         return _bmcFWVersionID;
154     }
155 
156     /**
157      * @brief Returns the process name given its PID.
158      *
159      * @param[in] pid - The PID value as a string
160      *
161      * @return std::optional<std::string> - The name, or std::nullopt
162      */
getProcessName(const std::string & pid) const163     std::optional<std::string> getProcessName(const std::string& pid) const
164     {
165         namespace fs = std::filesystem;
166 
167         fs::path path{"/proc"};
168         path /= fs::path{pid} / "exe";
169 
170         if (fs::exists(path))
171         {
172             return fs::read_symlink(path);
173         }
174 
175         return std::nullopt;
176     }
177 
178     /**
179      * @brief Returns the time the system was running.
180      *
181      * @return std::optional<uint64_t> - The System uptime or std::nullopt
182      */
getUptimeInSeconds() const183     std::optional<uint64_t> getUptimeInSeconds() const
184     {
185         std::ifstream versionFile{"/proc/uptime"};
186         std::string line{};
187 
188         std::getline(versionFile, line);
189         auto pos = line.find(" ");
190         if (pos == std::string::npos)
191         {
192             return std::nullopt;
193         }
194 
195         uint64_t seconds = atol(line.substr(0, pos).c_str());
196         if (seconds == 0)
197         {
198             return std::nullopt;
199         }
200 
201         return seconds;
202     }
203 
204     /**
205      * @brief Returns the time the system was running.
206      *
207      * @param[in] seconds - The number of seconds the system has been running
208      *
209      * @return std::string - days/hours/minutes/seconds
210      */
getBMCUptime(uint64_t seconds) const211     std::string getBMCUptime(uint64_t seconds) const
212     {
213         time_t t(seconds);
214         tm* p = gmtime(&t);
215 
216         std::string uptime =
217             std::to_string(p->tm_year - 70) + "y " +
218             std::to_string(p->tm_yday) + "d " + std::to_string(p->tm_hour) +
219             "h " + std::to_string(p->tm_min) + "m " +
220             std::to_string(p->tm_sec) + "s";
221 
222         return uptime;
223     }
224 
225     /**
226      * @brief Returns the system load average over the past 1 minute, 5 minutes
227      *        and 15 minutes.
228      *
229      * @return std::string - The system load average
230      */
getBMCLoadAvg() const231     std::string getBMCLoadAvg() const
232     {
233         std::string loadavg{};
234 
235         std::ifstream loadavgFile{"/proc/loadavg"};
236         std::string line;
237         std::getline(loadavgFile, line);
238 
239         size_t count = 3;
240         for (size_t i = 0; i < count; i++)
241         {
242             auto pos = line.find(" ");
243             if (pos == std::string::npos)
244             {
245                 return {};
246             }
247 
248             if (i != count - 1)
249             {
250                 loadavg.append(line.substr(0, pos + 1));
251             }
252             else
253             {
254                 loadavg.append(line.substr(0, pos));
255             }
256 
257             line = line.substr(pos + 1);
258         }
259 
260         return loadavg;
261     }
262 
263     /**
264      * @brief Returns the 'send event logs to host' setting.
265      *
266      * @return bool - If sending PELs to the host is enabled.
267      */
getHostPELEnablement() const268     virtual bool getHostPELEnablement() const
269     {
270         return _sendPELsToHost;
271     }
272 
273     /**
274      * @brief Returns the BMC state
275      *
276      * @return std::string - The BMC state property value
277      */
getBMCState() const278     virtual std::string getBMCState() const
279     {
280         return _bmcState;
281     }
282 
283     /**
284      * @brief Returns the Chassis state
285      *
286      * @return std::string - The chassis state property value
287      */
getChassisState() const288     virtual std::string getChassisState() const
289     {
290         return _chassisState;
291     }
292 
293     /**
294      * @brief Returns the chassis requested power
295      *        transition value.
296      *
297      * @return std::string - The chassis transition property
298      */
getChassisTransition() const299     virtual std::string getChassisTransition() const
300     {
301         return _chassisTransition;
302     }
303 
304     /**
305      * @brief Returns the Host state
306      *
307      * @return std::string - The Host state property value
308      */
getHostState() const309     virtual std::string getHostState() const
310     {
311         return _hostState;
312     }
313 
314     /**
315      * @brief Returns the Boot state
316      *
317      * @return std::string - The Boot state property value
318      */
getBootState() const319     virtual std::string getBootState() const
320     {
321         return _bootState;
322     }
323 
324     /**
325      * @brief Returns the motherboard CCIN
326      *
327      * @return std::string The motherboard CCIN
328      */
329     virtual std::string getMotherboardCCIN() const = 0;
330 
331     /**
332      * @brief Returns the system IM
333      *
334      * @return std::string The system IM
335      */
336     virtual std::vector<uint8_t> getSystemIMKeyword() const = 0;
337 
338     /**
339      * @brief Get the fields from the inventory necessary for doing
340      *        a callout on an inventory path.
341      *
342      * @param[in] inventoryPath - The item to get the data for
343      * @param[out] fruPartNumber - Filled in with the VINI/FN keyword
344      * @param[out] ccin - Filled in with the VINI/CC keyword
345      * @param[out] serialNumber - Filled in with the VINI/SN keyword
346      */
347     virtual void getHWCalloutFields(
348         const std::string& inventoryPath, std::string& fruPartNumber,
349         std::string& ccin, std::string& serialNumber) const = 0;
350 
351     /**
352      * @brief Get the location code for an inventory item.
353      *
354      * @param[in] inventoryPath - The item to get the data for
355      *
356      * @return std::string - The location code
357      */
358     virtual std::string
359         getLocationCode(const std::string& inventoryPath) const = 0;
360 
361     /**
362      * @brief Get the list of system type names the system is called.
363      *
364      * @return std::vector<std::string> - The list of names
365      */
366     virtual std::vector<std::string> getSystemNames() const = 0;
367 
368     /**
369      * @brief Fills in the placeholder 'Ufcs' in the passed in location
370      *        code with the machine feature code and serial number, which
371      *        is needed to create a valid location code.
372      *
373      * @param[in] locationCode - Location code value starting with Ufcs-, and
374      *                           if that isn't present it will be added first.
375      *
376      * @param[in] node - The node number the location is on.
377      *
378      * @return std::string - The expanded location code
379      */
380     virtual std::string expandLocationCode(const std::string& locationCode,
381                                            uint16_t node) const = 0;
382 
383     /**
384      * @brief Returns the inventory paths for the FRU that the location
385      *        code represents.
386      *
387      * @param[in] locationCode - If an expanded location code, then the
388      *                           full location code.
389      *                           If not expanded, a location code value
390      *                           starting with Ufcs-, and if that isn't
391      *                           present it will be added first.
392      *
393      * @param[in] node - The node number the location is on.  Ignored if the
394      *                   expanded location code is passed in.
395      *
396      * @param[in] expanded - If the location code already has the relevent
397      *                       VPD fields embedded in it.
398      *
399      * @return std::vector<std::string> - The inventory D-Bus objects
400      */
401     virtual std::vector<std::string>
402         getInventoryFromLocCode(const std::string& LocationCode, uint16_t node,
403                                 bool expanded) const = 0;
404 
405     /**
406      * @brief Sets the Asserted property on the LED group passed in.
407      *
408      * @param[in] ledGroup - The LED group D-Bus path
409      * @param[in] value - The value to set it to
410      */
411     virtual void assertLEDGroup(const std::string& ledGroup,
412                                 bool value) const = 0;
413 
414     /**
415      * @brief Sets the Functional property on the OperationalStatus
416      *        interface on a D-Bus object.
417      *
418      * @param[in] objectPath - The D-Bus object path
419      * @param[in] functional - The value
420      */
421     virtual void setFunctional(const std::string& objectPath,
422                                bool functional) const = 0;
423 
424     /**
425      * @brief Sets the critical association on the D-Bus object.
426      *
427      * @param[in] objectPath - The D-Bus object path
428      */
429     virtual void
430         setCriticalAssociation(const std::string& objectPath) const = 0;
431 
432     /**
433      * @brief Returns the manufacturing QuiesceOnError property
434      *
435      * @return bool - Manufacturing QuiesceOnError property
436      */
437     virtual bool getQuiesceOnError() const = 0;
438 
439     /**
440      * @brief Split location code into base and connector segments
441      *
442      * A location code that ends in '-Tx', where 'x' is a number,
443      * represents a connector, such as a USB cable connector.
444      *
445      * This function splits the passed in location code into a
446      * base and connector segment.  e.g.:
447      *   P0-T1 -> ['P0', '-T1']
448      *   P0 -> ['P0', '']
449      *
450      * @param[in] locationCode - location code to split
451      * @return pair<string, string> - The base and connector segments
452      */
453     static std::pair<std::string, std::string>
454         extractConnectorFromLocCode(const std::string& locationCode);
455 
456 #ifdef PEL_ENABLE_PHAL
457     /**
458      * @brief Create guard record
459      *
460      *  @param[in] binPath: phal devtree binary path used as key
461      *  @param[in] eGardType: Guard type enum value
462      *  @param[in] plid: Pel ID
463      */
464     virtual void createGuardRecord(const std::vector<uint8_t>& binPath,
465                                    GardType eGardType, uint32_t plid) const = 0;
466 #endif
467 
468     /**
469      * @brief Create Progress SRC property on the boot progress
470      *        interface on a D-Bus object.
471      *
472      * @param[in] priSRC - Primary SRC value (e.g. BD8D1001)
473      * @param[in] srcStruct - Full SRC base structure
474      */
475     virtual void
476         createProgressSRC(const uint64_t& priSRC,
477                           const std::vector<uint8_t>& srcStruct) const = 0;
478 
479     /**
480      * @brief Get the list of unresolved OpenBMC event log ids that have an
481      * associated hardware isolation entry.
482      *
483      * @return std::vector<uint32_t> - The list of log ids
484      */
485     virtual std::vector<uint32_t> getLogIDWithHwIsolation() const = 0;
486 
487     /**
488      * @brief Returns the latest raw progress SRC from the State.Boot.Raw
489      *        D-Bus interface.
490      *
491      * @return std::vector<uint8_t> - The progress SRC bytes
492      */
493     virtual std::vector<uint8_t> getRawProgressSRC() const = 0;
494 
495     /**
496      * @brief Returns the FRUs DI property value hosted on the VINI iterface for
497      * the given location code.
498      *
499      * @param[in] locationCode - The location code of the FRU
500      *
501      * @return std::optional<std::vector<uint8_t>> -  The FRUs DI or
502      * std::nullopt
503      */
504     virtual std::optional<std::vector<uint8_t>>
505         getDIProperty(const std::string& locationCode) const = 0;
506 
507     /**
508      * @brief Wrpper API to call pHAL API 'getFRUType()' and check whether the
509      * given location code is DIMM or not
510      *
511      * @param[in] locCode - The location code of the FRU
512      *
513      * @return - true, if the given location code is DIMM
514      *         - false, if the given location code is not DIMM or if it fails to
515      *         determine the FRU type.
516      */
517     bool isDIMM(const std::string& locCode);
518 
519     /**
520      * @brief Check whether the given location code present in the cache
521      * memory
522      *
523      * @param[in] locCode - The location code of the FRU
524      *
525      * @return true, if the given location code present in cache and is a DIMM
526      *         false, if the given location code present in cache, but a non
527      *         DIMM FRU
528      *         std::nullopt, if the given location code is not present in the
529      *         cache.
530      */
531     std::optional<bool> isDIMMLocCode(const std::string& locCode) const;
532 
533     /**
534      * @brief add the given location code to the cache memory
535      *
536      * @param[in] locCode - The location code of the FRU
537      * @param[in] isFRUDIMM - true indicates the FRU is a DIMM
538      *                        false indicates the FRU is a non DIMM
539      *
540      */
541     void addDIMMLocCode(const std::string& locCode, bool isFRUDIMM);
542 
543     /**
544      * @brief Finds all D-Bus Associated paths that contain any of the
545      *        interfaces passed in, by using GetAssociatedSubTreePaths.
546      *
547      * @param[in] associatedPath - The D-Bus object path
548      * @param[in] subtree - The subtree path for which the result should be
549      *                      fetched
550      * @param[in] depth - The maximum subtree depth for which results should be
551      *                    fetched
552      * @param[in] interfaces - The desired interfaces
553      *
554      * @return The D-Bus paths.
555      */
556     virtual DBusPathList getAssociatedPaths(
557         const DBusPath& associatedPath, const DBusPath& subtree, int32_t depth,
558         const DBusInterfaceList& interfaces) const = 0;
559 
560   protected:
561     /**
562      * @brief Sets the host on/off state and runs any
563      *        callback functions (if there was a change).
564      */
setHostUp(bool hostUp)565     void setHostUp(bool hostUp)
566     {
567         if (_hostUp != hostUp)
568         {
569             _hostUp = hostUp;
570 
571             for (auto& [name, func] : _hostChangeCallbacks)
572             {
573                 try
574                 {
575                     func(_hostUp);
576                 }
577                 catch (const std::exception& e)
578                 {
579                     lg2::error(
580                         "A host state change callback threw an exception");
581                 }
582             }
583         }
584     }
585 
586     /**
587      * @brief Runs the callback functions registered when
588      *        FRUs become present.
589      */
setFruPresent(const std::string & locationCode)590     void setFruPresent(const std::string& locationCode)
591     {
592         for (const auto& [_, func] : _fruPresentCallbacks)
593         {
594             try
595             {
596                 func(locationCode);
597             }
598             catch (const std::exception& e)
599             {
600                 lg2::error("A FRU present callback threw an exception");
601             }
602         }
603     }
604 
605     /**
606      * @brief The hardware management console status.  Always kept
607      *        up to date.
608      */
609     bool _hmcManaged = false;
610 
611     /**
612      * @brief The host up status.  Always kept up to date.
613      */
614     bool _hostUp = false;
615 
616     /**
617      * @brief The map of host state change subscriber
618      *        names to callback functions.
619      */
620     std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks;
621 
622     /**
623      * @brief The map of FRU present subscriber
624      *        names to callback functions.
625      */
626     std::map<std::string, FRUPresentFunc> _fruPresentCallbacks;
627 
628     /**
629      * @brief The BMC firmware version string
630      */
631     std::string _bmcFWVersion;
632 
633     /**
634      * @brief The server firmware version string
635      */
636     std::string _serverFWVersion;
637 
638     /**
639      * @brief The BMC firmware version ID string
640      */
641     std::string _bmcFWVersionID;
642 
643     /**
644      * @brief If sending PELs is enabled.
645      *
646      * This is usually set to false in manufacturing test.
647      */
648     bool _sendPELsToHost = true;
649 
650     /**
651      * @brief The BMC state property
652      */
653     std::string _bmcState;
654 
655     /**
656      * @brief The Chassis current power state property
657      */
658     std::string _chassisState;
659 
660     /**
661      * @brief The Chassis requested power transition property
662      */
663     std::string _chassisTransition;
664 
665     /**
666      * @brief The host state property
667      */
668     std::string _hostState;
669 
670     /**
671      * @brief The boot state property
672      */
673     std::string _bootState;
674 
675     /**
676      * @brief A cache storage for location code and its FRU Type
677      *  - The key 'std::string' represents the locationCode of the FRU
678      *  - The bool value - true indicates the FRU is a DIMM
679      *                     false indicates the FRU is a non DIMM.
680      */
681     std::unordered_map<std::string, bool> _locationCache;
682 };
683 
684 /**
685  * @class DataInterface
686  *
687  * Concrete implementation of DataInterfaceBase.
688  */
689 class DataInterface : public DataInterfaceBase
690 {
691   public:
692     DataInterface() = delete;
693     ~DataInterface() = default;
694     DataInterface(const DataInterface&) = default;
695     DataInterface& operator=(const DataInterface&) = default;
696     DataInterface(DataInterface&&) = default;
697     DataInterface& operator=(DataInterface&&) = default;
698 
699     /**
700      * @brief Constructor
701      *
702      * @param[in] bus - The sdbusplus bus object
703      */
704     explicit DataInterface(sdbusplus::bus_t& bus);
705 
706     /**
707      * @brief Finds the D-Bus service name that hosts the
708      *        passed in path and interface.
709      *
710      * @param[in] objectPath - The D-Bus object path
711      * @param[in] interface - The D-Bus interface
712      */
713     DBusService getService(const std::string& objectPath,
714                            const std::string& interface) const;
715 
716     /**
717      * @brief Wrapper for the 'GetAll' properties method call
718      *
719      * @param[in] service - The D-Bus service to call it on
720      * @param[in] objectPath - The D-Bus object path
721      * @param[in] interface - The interface to get the props on
722      *
723      * @return DBusPropertyMap - The property results
724      */
725     DBusPropertyMap getAllProperties(const std::string& service,
726                                      const std::string& objectPath,
727                                      const std::string& interface) const;
728     /**
729      * @brief Wrapper for the 'Get' properties method call
730      *
731      * @param[in] service - The D-Bus service to call it on
732      * @param[in] objectPath - The D-Bus object path
733      * @param[in] interface - The interface to get the property on
734      * @param[in] property - The property name
735      * @param[out] value - Filled in with the property value.
736      */
737     void getProperty(const std::string& service, const std::string& objectPath,
738                      const std::string& interface, const std::string& property,
739                      DBusValue& value) const;
740     /**
741      * @brief Returns the machine Type/Model
742      *
743      * @return string - The machine Type/Model string
744      */
745     std::string getMachineTypeModel() const override;
746 
747     /**
748      * @brief Returns the machine serial number
749      *
750      * @return string - The machine serial number
751      */
752     std::string getMachineSerialNumber() const override;
753 
754     /**
755      * @brief Returns the motherboard CCIN
756      *
757      * @return std::string The motherboard CCIN
758      */
759     std::string getMotherboardCCIN() const override;
760 
761     /**
762      * @brief Returns the system IM
763      *
764      * @return std::vector The system IM keyword in 4 byte vector
765      */
766     std::vector<uint8_t> getSystemIMKeyword() const override;
767 
768     /**
769      * @brief Get the fields from the inventory necessary for doing
770      *        a callout on an inventory path.
771      *
772      * @param[in] inventoryPath - The item to get the data for
773      * @param[out] fruPartNumber - Filled in with the VINI/FN keyword
774      * @param[out] ccin - Filled in with the VINI/CC keyword
775      * @param[out] serialNumber - Filled in with the VINI/SN keyword
776      */
777     void getHWCalloutFields(const std::string& inventoryPath,
778                             std::string& fruPartNumber, std::string& ccin,
779                             std::string& serialNumber) const override;
780 
781     /**
782      * @brief Get the location code for an inventory item.
783      *
784      * Throws an exception if the inventory item doesn't have the
785      * location code interface.
786      *
787      * @param[in] inventoryPath - The item to get the data for
788      *
789      * @return std::string - The location code
790      */
791     std::string
792         getLocationCode(const std::string& inventoryPath) const override;
793 
794     /**
795      * @brief Get the list of system type names the system is called.
796      *
797      * @return std::vector<std::string> - The list of names
798      */
799     std::vector<std::string> getSystemNames() const override;
800 
801     /**
802      * @brief Fills in the placeholder 'Ufcs' in the passed in location
803      *        code with the machine feature code and serial number, which
804      *        is needed to create a valid location code.
805      *
806      * @param[in] locationCode - Location code value starting with Ufcs-, and
807      *                           if that isn't present it will be added first.
808      *
809      * @param[in] node - The node number the location is one.
810      *
811      * @return std::string - The expanded location code
812      */
813     std::string expandLocationCode(const std::string& locationCode,
814                                    uint16_t node) const override;
815 
816     /**
817      * @brief Returns the inventory paths for the FRU that the location
818      *        code represents.
819      *
820      * @param[in] locationCode - If an expanded location code, then the
821      *                           full location code.
822      *                           If not expanded, a location code value
823      *                           starting with Ufcs-, and if that isn't
824      *                           present it will be added first.
825      *
826      * @param[in] node - The node number the location is on.  Ignored if the
827      *                   expanded location code is passed in.
828      *
829      * @param[in] expanded - If the location code already has the relevent
830      *                       VPD fields embedded in it.
831      *
832      * @return std::vector<std::string> - The inventory D-Bus objects
833      */
834     std::vector<std::string>
835         getInventoryFromLocCode(const std::string& locationCode, uint16_t node,
836                                 bool expanded) const override;
837 
838     /**
839      * @brief Sets the Asserted property on the LED group passed in.
840      *
841      * @param[in] ledGroup - The LED group D-Bus path
842      * @param[in] value - The value to set it to
843      */
844     void assertLEDGroup(const std::string& ledGroup, bool value) const override;
845 
846     /**
847      * @brief Sets the Functional property on the OperationalStatus
848      *        interface on a D-Bus object.
849      *
850      * @param[in] objectPath - The D-Bus object path
851      * @param[in] functional - The value
852      */
853     void setFunctional(const std::string& objectPath,
854                        bool functional) const override;
855 
856     /**
857      * @brief Sets the critical association on the D-Bus object.
858      *
859      * @param[in] objectPath - The D-Bus object path
860      */
861     void setCriticalAssociation(const std::string& objectPath) const override;
862 
863     /**
864      * @brief Returns the manufacturing QuiesceOnError property
865      *
866      * @return bool - Manufacturing QuiesceOnError property
867      */
868     bool getQuiesceOnError() const override;
869 
870 #ifdef PEL_ENABLE_PHAL
871     /**
872      * @brief Create guard record
873      *
874      *  @param[in] binPath: phal devtree binary path used as key
875      *  @param[in] eGardType: Guard type enum value
876      *   @param[in] plid: pel id to be associated to the guard record
877      */
878     void createGuardRecord(const std::vector<uint8_t>& binPath,
879                            GardType eGardType, uint32_t plid) const override;
880 #endif
881 
882     /**
883      * @brief Create Progress SRC property on the boot progress
884      *        interface on a D-Bus object.
885      *
886      * @param[in] priSRC - Primary SRC value
887      * @param[in] srcStruct - Full SRC base structure
888      */
889     void
890         createProgressSRC(const uint64_t& priSRC,
891                           const std::vector<uint8_t>& srcStruct) const override;
892 
893     /**
894      * @brief Get the list of unresolved OpenBMC event log ids that have an
895      * associated hardware isolation entry.
896      *
897      * @return std::vector<uint32_t> - The list of log ids
898      */
899     std::vector<uint32_t> getLogIDWithHwIsolation() const override;
900 
901     /**
902      * @brief Returns the latest raw progress SRC from the State.Boot.Raw
903      *        D-Bus interface.
904      *
905      * @return std::vector<uint8_t>: The progress SRC bytes
906      */
907     std::vector<uint8_t> getRawProgressSRC() const override;
908 
909     /**
910      * @brief Returns the FRUs DI property value hosted on the VINI iterface for
911      * the given location code.
912      *
913      * @param[in] locationCode - The location code of the FRU
914      *
915      * @return std::optional<std::vector<uint8_t>> -  The FRUs DI or
916      * std::nullopt
917      */
918     std::optional<std::vector<uint8_t>>
919         getDIProperty(const std::string& locationCode) const override;
920 
921     /**
922      * @brief Finds all D-Bus Associated paths that contain any of the
923      *        interfaces passed in, by using GetAssociatedSubTreePaths.
924      *
925      * @param[in] associatedPath - The D-Bus object path
926      * @param[in] subtree - The subtree path for which the result should be
927      *                      fetched
928      * @param[in] depth - The maximum subtree depth for which results should be
929      *                    fetched
930      * @param[in] interfaces - The desired interfaces
931      *
932      * @return The D-Bus paths.
933      */
934     DBusPathList getAssociatedPaths(
935         const DBusPath& associatedPath, const DBusPath& subtree, int32_t depth,
936         const DBusInterfaceList& interfaces) const override;
937 
938   private:
939     /**
940      * @brief Reads the BMC firmware version string and puts it into
941      *        _bmcFWVersion.
942      */
943     void readBMCFWVersion();
944 
945     /**
946      * @brief Reads the server firmware version string and puts it into
947      *        _serverFWVersion.
948      */
949     void readServerFWVersion();
950 
951     /**
952      * @brief Reads the BMC firmware version ID and puts it into
953      *        _bmcFWVersionID.
954      */
955     void readBMCFWVersionID();
956 
957     /**
958      * @brief Finds all D-Bus paths that contain any of the interfaces
959      *        passed in, by using GetSubTreePaths.
960      *
961      * @param[in] interfaces - The desired interfaces
962      *
963      * @return The D-Bus paths.
964      */
965     DBusPathList getPaths(const DBusInterfaceList& interfaces) const;
966 
967     /**
968      * @brief The interfacesAdded callback used on the inventory to
969      *        find the D-Bus object that has the motherboard interface.
970      *        When the motherboard is found, it then adds a PropertyWatcher
971      *        for the motherboard CCIN.
972      */
973     void motherboardIfaceAdded(sdbusplus::message_t& msg);
974 
975     /**
976      * @brief Start watching for the hotpluggable FRUs to become
977      *        present.
978      */
979     void startFruPlugWatch();
980 
981     /**
982      * @brief Create a D-Bus match object for the Present property
983      *        to change on the path passed in.
984      * @param[in] path - The path to watch.
985      */
986     void addHotplugWatch(const std::string& path);
987 
988     /**
989      * @brief Callback when an inventory interface was added.
990      *
991      * Only does something if it's one of the hotpluggable FRUs,
992      * in which case it will treat it as a hotplug if the
993      * Present property is true.
994      *
995      * @param[in] msg - The InterfacesAdded signal contents.
996      */
997     void inventoryIfaceAdded(sdbusplus::message_t& msg);
998 
999     /**
1000      * @brief Callback when the Present property changes.
1001      *
1002      * If present, will run the registered callbacks.
1003      *
1004      * @param[in] msg - The PropertiesChanged signal contents.
1005      */
1006     void presenceChanged(sdbusplus::message_t& msg);
1007 
1008     /**
1009      * @brief If the Present property is in the properties map
1010      *        passed in and it is true, notify the subscribers.
1011      *
1012      * @param[in] path - The object path of the inventory item.
1013      * @param[in] properties - The properties map
1014      */
1015     void notifyPresenceSubsribers(const std::string& path,
1016                                   const DBusPropertyMap& properties);
1017 
1018     /**
1019      * @brief Adds the Ufcs- prefix to the location code passed in
1020      *        if necessary.
1021      *
1022      * Needed because the location codes that come back from the
1023      * message registry and device callout JSON don't have it.
1024      *
1025      * @param[in] - The location code without a prefix, like P1-C1
1026      *
1027      * @return std::string - The location code with the prefix
1028      */
1029     static std::string addLocationCodePrefix(const std::string& locationCode);
1030 
1031     /**
1032      * @brief A helper API to check whether the PHAL device tree is exists,
1033      *        ensuring the PHAL init API can be invoked.
1034      *
1035      * @return true if the PHAL device tree is exists, otherwise false
1036      */
1037     bool isPHALDevTreeExist() const;
1038 
1039 #ifdef PEL_ENABLE_PHAL
1040     /**
1041      * @brief A helper API to init PHAL libraries
1042      *
1043      * @return None
1044      */
1045     void initPHAL();
1046 #endif // PEL_ENABLE_PHAL
1047 
1048     /**
1049      * @brief A helper API to subscribe to systemd signals
1050      *
1051      * @return None
1052      */
1053     void subscribeToSystemdSignals();
1054 
1055     /**
1056      * @brief A helper API to unsubscribe to systemd signals
1057      *
1058      * @return None
1059      */
1060     void unsubscribeFromSystemdSignals();
1061 
1062     /**
1063      * @brief The D-Bus property or interface watchers that have callbacks
1064      *        registered that will set members in this class when
1065      *        they change.
1066      */
1067     std::vector<std::unique_ptr<DBusWatcher>> _properties;
1068 
1069     std::unique_ptr<sdbusplus::bus::match_t> _invIaMatch;
1070 
1071     /**
1072      * @brief The matches for watching for hotplugs.
1073      *
1074      * A map so we can check that we never get duplicates.
1075      */
1076     std::map<std::string, std::unique_ptr<sdbusplus::bus::match_t>>
1077         _invPresentMatches;
1078 
1079     /**
1080      * @brief The sdbusplus bus object for making D-Bus calls.
1081      */
1082     sdbusplus::bus_t& _bus;
1083 
1084     /**
1085      * @brief Watcher to check "openpower-update-bios-attr-table" service
1086      *        is "done" to init PHAL libraires
1087      */
1088     std::unique_ptr<sdbusplus::bus::match_t> _systemdMatch;
1089 
1090     /**
1091      * @brief A slot object for async dbus call
1092      */
1093     sdbusplus::slot_t _systemdSlot;
1094 };
1095 
1096 } // namespace pels
1097 } // namespace openpower
1098