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