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